(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "tslib", "@alicloud/mpserverless-core", "../codec", "./collection", "./command", "./result", "../validator", "../constant", "../error"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.QueryService = exports.Query = void 0;
    const tslib_1 = require("tslib");
    const mpserverless_core_1 = require("@alicloud/mpserverless-core");
    const codec_1 = require("../codec");
    const collection_1 = require("./collection");
    const command_1 = require("./command");
    const result_1 = require("./result");
    const validator_1 = require("../validator");
    const constant_1 = require("../constant");
    const error_1 = require("../error");
    var MongoAction;
    (function (MongoAction) {
        MongoAction["AGGREGATE"] = "aggregate";
        MongoAction["COUNT"] = "count";
        MongoAction["DISTINCT"] = "distinct";
        MongoAction["FIND_ONE"] = "findone";
        MongoAction["FIND"] = "find";
        MongoAction["INSERT_ONE"] = "insertOne";
        MongoAction["INSERT_MANY"] = "insertMany";
        MongoAction["FIND_ONE_AND_UPDATE"] = "findOneAndUpdate";
        MongoAction["UPDATE_ONE"] = "updateOne";
        MongoAction["UPDATE_MANY"] = "updateMany";
        MongoAction["FIND_ONE_AND_REPLACE"] = "findOneAndReplace";
        MongoAction["REPLACE_ONE"] = "replaceOne";
        MongoAction["FIND_ONE_AND_DELETE"] = "findOneAndDelete";
        MongoAction["DELETE_ONE"] = "deleteOne";
        MongoAction["DELETE_MANY"] = "deleteMany";
    })(MongoAction || (MongoAction = {}));
    ;
    class Query {
        constructor() {
            this.encoder = new codec_1.JSONEncoder();
            this.decoder = new codec_1.JSONDecoder();
        }
        transaction() {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.comm = new command_1.StartTransactionCommand({});
                const res = yield this.execute();
                if (res) {
                    this.transId = res.transactionId;
                }
                return this.transId;
            });
        }
        commit() {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.comm = new command_1.CommitTransactionCommand({});
                return this.execute();
            });
        }
        rollback() {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.comm = new command_1.AbortTransactionCommand({});
                return this.execute();
            });
        }
        collection(name) {
            this.coll = new collection_1.Collection(name);
            return this;
        }
        aggregate(pipeline, options) {
            this.validateTransactionAction(MongoAction.AGGREGATE);
            this.comm = new command_1.AggregateCommand({ pipeline, options });
            return this.execute();
        }
        count(query, options) {
            this.validateTransactionAction(MongoAction.COUNT);
            this.comm = new command_1.CountCommand({ query, options });
            return this.execute();
        }
        distinct(key, query, options) {
            this.validateTransactionAction(MongoAction.DISTINCT);
            this.comm = new command_1.DistinctCommand({ key, query, options });
            return this.execute();
        }
        findOne(query, options) {
            this.comm = new command_1.FindDocumentCommand({ query, options });
            return this.execute();
        }
        find(query, options) {
            this.validateTransactionAction(MongoAction.FIND);
            this.comm = new command_1.FindDocumentsCommand({ query, options });
            return this.execute();
        }
        insertOne(doc, options) {
            this.comm = new command_1.InsertDocumentCommand({ doc, options });
            return this.execute();
        }
        insertMany(docs, options) {
            this.validateTransactionAction(MongoAction.INSERT_MANY);
            this.comm = new command_1.InsertDocumentsCommand({ docs, options });
            return this.execute();
        }
        findOneAndUpdate(filter, update, options) {
            this.comm = new command_1.FindAndUpdateDocumentCommand({ filter, update, options });
            return this.execute();
        }
        updateOne(filter, update, options) {
            this.comm = new command_1.UpdateDocumentCommand({ filter, update, options });
            return this.execute();
        }
        updateMany(filter, update, options) {
            this.validateTransactionAction(MongoAction.UPDATE_MANY);
            this.comm = new command_1.UpdateDocumentsCommand({ filter, update, options });
            return this.execute();
        }
        findOneAndReplace(filter, replacement, options) {
            this.comm = new command_1.FindAndReplaceDocumentCommand({ filter, replacement, options });
            return this.execute();
        }
        replaceOne(filter, doc, options) {
            this.comm = new command_1.ReplaceDocumentCommand({ filter, doc, options });
            return this.execute();
        }
        findOneAndDelete(filter, options) {
            this.comm = new command_1.FindAndDeleteDocumentCommand({ filter, options });
            return this.execute();
        }
        deleteOne(filter, options) {
            this.comm = new command_1.DeleteDocumentCommand({ filter, options });
            return this.execute();
        }
        deleteMany(filter, options) {
            this.validateTransactionAction(MongoAction.DELETE_MANY);
            this.comm = new command_1.DeleteDocumentsCommand({ filter, options });
            return this.execute();
        }
        validate() {
            const v = new validator_1.MongoValidator();
            try {
                v.validate(this.comm.schema, this.encoder.encode(this.comm.argMap));
            }
            catch (err) {
                throw err;
            }
        }
        execute(..._) {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                mpserverless_core_1.assert(this.comm, '[DBService]缺少 command 参数');
                this.validate();
                switch (this.comm.permission) {
                    case constant_1.PERMISSION.AGGREGATE:
                    case constant_1.PERMISSION.WRITE:
                    case constant_1.PERMISSION.READ:
                        mpserverless_core_1.assert(this.collection, '[DBService]缺少 collection 参数');
                        break;
                    default:
                }
                const query = Object.assign({}, this.coll && this.coll.inspect(), this.transId && { transactionId: this.transId }, this.comm.inspect());
                return this.encoder.encode(query);
            });
        }
        validateTransactionAction(action) {
            if (this.transId) {
                throw new error_1.bizError.TransactionError('transaction not support action [' + action + ']');
            }
        }
    }
    exports.Query = Query;
    class QueryService extends Query {
        execute() {
            const _super = Object.create(null, {
                execute: { get: () => super.execute }
            });
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                const params = yield _super.execute.call(this);
                const request = this.getEncoder()
                    .setBodyField({
                    method: 'serverless.db.default.execute',
                    params,
                });
                const response = yield this.getTransport().request(request);
                return (new result_1.Result(response.body)).inspect();
            });
        }
    }
    exports.QueryService = QueryService;
});
//# sourceMappingURL=data:application/json;base64, 