function $main(options) {

    options = assert(options, ['pgFormatting', 'pgNative', 'promiseLib', 'capSQL', 'noWarnings',
        'connect', 'disconnect', 'query', 'receive', 'task', 'transact', 'error', 'extend', 'schema']);

    let pg = npm.pg;
    const p = parsePromise(options.promiseLib);

    const config = {
        version: npm.package.version,
        promiseLib: p.promiseLib,
        promise: p.promise
    };

    npm.utils.addReadProp(config, '$npm', {}, true);

    // Locking properties that cannot be changed later:
    npm.utils.addReadProp(options, 'promiseLib', options.promiseLib);
    npm.utils.addReadProp(options, 'pgNative', !!options.pgNative);

    config.options = options;

    // istanbul ignore next:
    // we do not cover code specific to Native Bindings
    if (options.pgNative) {
        pg = npm.pg.native;
        if (npm.utils.isNull(pg)) {
            throw new Error(npm.text.nativeError);
        }
    } else {
        if (!originalClientConnect) {
            originalClientConnect = pg.Client.prototype.connect;
            pg.Client.prototype.connect = function () {
                const handler = msg => {
                    if (msg.parameterName === 'server_version') {
                        this.serverVersion = msg.parameterValue;
                        this.connection.removeListener('parameterStatus', handler);
                    }
                };
                this.connection.on('parameterStatus', handler);
                return originalClientConnect.call(this, ...arguments);
            };
        }
    }

    const Database = require('./database')(config);

    const inst = (cn, dc) => {
        if (npm.utils.isText(cn) || (cn && typeof cn === 'object')) {
            return new Database(cn, dc, config);
        }
        throw new TypeError('Invalid connection details: ' + npm.utils.toJson(cn));
    };

    npm.utils.addReadProperties(inst, rootNameSpace);

    /**
     * @member {external:PG} pg
     * @description
     * Instance of the $[pg] library that's being used, depending on initialization option `pgNative`:
     *  - regular `pg` module instance, without option `pgNative`, or equal to `false` (default)
     *  - `pg` module instance with $[Native Bindings], if option `pgNative` was set.
     *
     * Available as `pgp.pg`, after initializing the library.
     */
    inst.pg = pg; // keep it modifiable, so the protocol can be mocked

    /**
     * @member {function} end
     * @readonly
     * @description
     * Shuts down all connection pools created in the process, so it can terminate without delay.
     * It is available as `pgp.end`, after initializing the library.
     *
     * All {@link Database} objects created previously can no longer be used, and their query methods will be rejecting
     * with {@link external:Error Error} = `Connection pool of the database object has been destroyed.`
     *
     * And if you want to shut down only a specific connection pool, you do so via the {@link Database}
     * object that owns the pool: `db.$pool.end()` (see {@link Database#$pool Database.$pool}).
     *
     * For more details see $[Library de-initialization].
     */
    npm.utils.addReadProp(inst, 'end', () => {
        DatabasePool.shutDown();
    });

    /**
     * @member {helpers} helpers
     * @readonly
     * @description
     * Namespace for {@link helpers all query-formatting helper functions}.
     *
     * Available as `pgp.helpers`, after initializing the library.
     *
     * @see {@link helpers}.
     */
    npm.utils.addReadProp(inst, 'helpers', npm.helpers(config));

    /**
     * @member {external:spex} spex
     * @readonly
     * @description
     * Initialized instance of the $[spex] module, used by the library within tasks and transactions.
     *
     * Available as `pgp.spex`, after initializing the library.
     *
     * @see
     * {@link Task#batch},
     * {@link Task#page},
     * {@link Task#sequence}
     */
    npm.utils.addReadProp(inst, 'spex', config.$npm.spex);

    config.pgp = inst;

    return inst;
}
@author Vitaly Tomilov
@module pg-promise

@description
## pg-promise v11.14
All documentation here is for the latest official release only.

### Initialization Options

Below is the complete list of _Initialization Options_ for the library that can be passed in during
the library's initialization:

```js
const initOptions = {&#47;* options as documented below *&#47;};

const pgp = require('pg-promise')(initOptions);
```

@property {{}} [options]
Library Initialization Options.

@property {boolean} [options.pgFormatting=false]
Redirects all query formatting to the $[pg] driver.

By default (`false`), the library uses its own advanced query-formatting engine.
If you set this option to a truthy value, query formatting will be done entirely by the
$[pg] driver, which means you won't be able to use any of the feature-rich query formatting
that this library implements, restricting yourself to the very basic `$1, $2,...` syntax.

This option is dynamic (can be set before or after initialization).

@property {boolean} [options.pgNative=false]
Use $[Native Bindings]. Library $[pg-native] must be included and installed independently, or else there will
be an error thrown: {@link external:Error Error} = `Failed to initialize Native Bindings.`

This is a static option (can only be set prior to initialization).

@property {object|function} [options.promiseLib=Promise]
Overrides the default (ES6 Promise) promise library for its internal use.

Example below sets to use $[Bluebird] - the best and recommended promise library. It is the fastest one,
and supports $[Long Stack Traces], essential for debugging promises.

```js
const Promise = require('bluebird');
const initOptions = {
    promiseLib: Promise
};
const pgp = require('pg-promise')(initOptions);
```

All existing promise libraries are supported. The ones with recognizable signature are used automatically,
while the rest can be configured via the $[Promise Adapter].

This is a static option (can only be set prior to initialization).

@property {boolean} [options.capSQL=false]
Capitalizes any SQL generated by the library.

By default, all internal SQL within the library is generated using the low case.
If, however, you want all SQL to be capitalized instead, set `capSQL` = `true`.

It is purely a cosmetic feature.

This option is dynamic (can be set before or after initialization).

@property {string|Array<string>|null|undefined|function} [options.schema]
Forces change of the default database schema(s) for every fresh connection, i.e.
the library will execute `SET search_path TO schema_1, schema_2, ...` in the background
whenever a fresh physical connection is allocated.

Normally, one changes the default schema(s) by $[changing the database or the role], but sometimes you
may want to switch the default schema(s) without persisting the change, and then use this option.

It can be a string, an array of strings, or a callback function that takes `dc` (database context)
as the only parameter (and as `this`), and returns schema(s) according to the database context. A callback function
can also return nothing (`undefined` or `null`), if no schema change needed for the specified database context.

The order of schema names matters, so if a table name exists in more than one schema, its default access resolves
to the table from the first such schema on the list.

This option is dynamic (can be set before or after initialization).

@property {boolean} [options.noWarnings=false]
Disables all diagnostic warnings in the library (it is ill-advised).

This option is dynamic (can be set before or after initialization).

@property {function} [options.connect]
Global event {@link event:connect connect} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.disconnect]
Global event {@link event:disconnect disconnect} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.query]
Global event {@link event:query query} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.receive]
Global event {@link event:receive receive} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.task]
Global event {@link event:task task} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.transact]
Global event {@link event:transact transact} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.error]
Global event {@link event:error error} handler.

This option is dynamic (can be set before or after initialization).

@property {function} [options.extend]
Global event {@link event:extend extend} handler.

This option is dynamic (can be set before or after initialization).

@see
{@link module:pg-promise~end end},
{@link module:pg-promise~as as},
{@link module:pg-promise~errors errors},
{@link module:pg-promise~helpers helpers},
{@link module:pg-promise~minify minify},
{@link module:pg-promise~ParameterizedQuery ParameterizedQuery},
{@link module:pg-promise~PreparedStatement PreparedStatement},
{@link module:pg-promise~pg pg},
{@link module:pg-promise~QueryFile QueryFile},
{@link module:pg-promise~queryResult queryResult},
{@link module:pg-promise~spex spex},
{@link module:pg-promise~txMode txMode},
{@link module:pg-promise~utils utils}