The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .cspell.json
├── .github
    ├── CHANGELOG.md
    ├── CODE_OF_CONDUCT.md
    ├── CONTRIBUTING.md
    ├── ISSUE_TEMPLATE
    │   └── bug-report.md
    └── workflows
    │   └── ci.yml
├── .gitignore
├── LICENSE
├── README.md
├── eslint.config.js
├── examples
    ├── advanced.js
    ├── monitor.js
    ├── query.js
    ├── select-insert.md
    └── transaction.js
├── jsdoc
    ├── README.md
    ├── fixLinks.js
    ├── jsdoc.js
    ├── layout.html
    ├── shortLinks.js
    ├── style.css
    └── templates
    │   └── custom
    │       ├── publish.js
    │       ├── static
    │           ├── fonts
    │           │   ├── OpenSans-Bold-webfont.eot
    │           │   ├── OpenSans-Bold-webfont.svg
    │           │   ├── OpenSans-Bold-webfont.woff
    │           │   ├── OpenSans-BoldItalic-webfont.eot
    │           │   ├── OpenSans-BoldItalic-webfont.svg
    │           │   ├── OpenSans-BoldItalic-webfont.woff
    │           │   ├── OpenSans-Italic-webfont.eot
    │           │   ├── OpenSans-Italic-webfont.svg
    │           │   ├── OpenSans-Italic-webfont.woff
    │           │   ├── OpenSans-Light-webfont.eot
    │           │   ├── OpenSans-Light-webfont.svg
    │           │   ├── OpenSans-Light-webfont.woff
    │           │   ├── OpenSans-LightItalic-webfont.eot
    │           │   ├── OpenSans-LightItalic-webfont.svg
    │           │   ├── OpenSans-LightItalic-webfont.woff
    │           │   ├── OpenSans-Regular-webfont.eot
    │           │   ├── OpenSans-Regular-webfont.svg
    │           │   └── OpenSans-Regular-webfont.woff
    │           ├── scripts
    │           │   ├── linenumber.js
    │           │   └── prettify
    │           │   │   ├── Apache-License-2.0.txt
    │           │   │   ├── lang-css.js
    │           │   │   └── prettify.js
    │           └── styles
    │           │   ├── jsdoc-default.css
    │           │   ├── prettify-jsdoc.css
    │           │   └── prettify-tomorrow.css
    │       └── tmpl
    │           ├── augments.tmpl
    │           ├── container.tmpl
    │           ├── details.tmpl
    │           ├── example.tmpl
    │           ├── examples.tmpl
    │           ├── exceptions.tmpl
    │           ├── layout.tmpl
    │           ├── mainpage.tmpl
    │           ├── members.tmpl
    │           ├── method.tmpl
    │           ├── modifies.tmpl
    │           ├── params.tmpl
    │           ├── properties.tmpl
    │           ├── returns.tmpl
    │           ├── source.tmpl
    │           ├── tutorial.tmpl
    │           └── type.tmpl
├── lib
    ├── assert.js
    ├── connect.js
    ├── context.js
    ├── database-pool.js
    ├── database.js
    ├── errors
    │   ├── README.md
    │   ├── index.js
    │   ├── parameterized-query-error.js
    │   ├── prepared-statement-error.js
    │   ├── query-file-error.js
    │   └── query-result-error.js
    ├── events.js
    ├── formatting.js
    ├── helpers
    │   ├── README.md
    │   ├── column-set.js
    │   ├── column.js
    │   ├── index.js
    │   ├── methods
    │   │   ├── concat.js
    │   │   ├── index.js
    │   │   ├── insert.js
    │   │   ├── sets.js
    │   │   ├── update.js
    │   │   └── values.js
    │   └── table-name.js
    ├── index.js
    ├── inner-state.js
    ├── main.js
    ├── patterns.js
    ├── promise-adapter.js
    ├── promise-parser.js
    ├── query-file.js
    ├── query-result.js
    ├── query.js
    ├── special-query.js
    ├── stream.js
    ├── task.js
    ├── text.js
    ├── tx-mode.js
    ├── types
    │   ├── index.js
    │   ├── parameterized-query.js
    │   ├── prepared-statement.js
    │   └── server-formatting.js
    └── utils
    │   ├── README.md
    │   ├── color.js
    │   ├── index.js
    │   └── public.js
├── package.json
├── test
    ├── adapter.spec.js
    ├── color.spec.js
    ├── db.spec.js
    ├── db
    │   ├── capture.js
    │   ├── header.js
    │   ├── init.js
    │   └── tools.js
    ├── entry.spec.js
    ├── event.spec.js
    ├── file.spec.js
    ├── format.spec.js
    ├── generator.spec.js
    ├── help.spec.js
    ├── parameterized.spec.js
    ├── prepared.spec.js
    ├── protocol.spec.js
    ├── sql-special
    │   ├── dup-files
    │   │   ├── 1-one.sql
    │   │   └── one.sql
    │   ├── dup-folders
    │   │   ├── 1-sub
    │   │   │   └── first.sql
    │   │   └── sub
    │   │   │   └── first.sql
    │   ├── folders-only
    │   │   ├── one
    │   │   │   └── first.sql
    │   │   └── two
    │   │   │   └── first.sql
    │   ├── one.sql
    │   ├── sql-config.json
    │   ├── sql-invalid.json
    │   ├── sql-simple.json
    │   └── two.sql
    ├── sql
    │   ├── allUsers.sql
    │   ├── invalid.sql
    │   ├── params.sql
    │   ├── simple.sql
    │   └── sub
    │   │   ├── one.sql
    │   │   ├── one.two.three.sql
    │   │   ├── third
    │   │       └── notSql.txt
    │   │   └── two.sql
    ├── stream.spec.js
    ├── tx-mode.spec.js
    ├── typescript.spec.js
    ├── typescript
    │   ├── adapter.ts
    │   ├── build.bat
    │   ├── clean.bat
    │   ├── config.ts
    │   ├── connection.ts
    │   ├── errors.ts
    │   ├── events.ts
    │   ├── extensions.ts
    │   ├── formatting.ts
    │   ├── help.ts
    │   ├── init.ts
    │   ├── parameterized.ts
    │   ├── pg.ts
    │   ├── pool.ts
    │   ├── prepared.ts
    │   ├── queries.ts
    │   ├── tasks.ts
    │   ├── tsconfig.json
    │   ├── tx-mode.ts
    │   └── utils.ts
    └── utils.spec.js
└── typescript
    ├── README.md
    ├── pg-promise.d.ts
    ├── pg-subset.d.ts
    └── tslint.json


/.cspell.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "version": "0.2",
 3 |   "language": "en",
 4 |   "ignorePaths": [
 5 |     "**/coverage/**",
 6 |     "**/node_modules/**",
 7 |     "**/jsdoc/templates/*",
 8 |     "**/*.{json}",
 9 |     ".cspell.json"
10 |   ],
11 |   "dictionaries": [
12 |     "typescript",
13 |     "softwareTerms",
14 |     "node",
15 |     "en_US",
16 |     "npm",
17 |     "misc",
18 |     "filetypes"
19 |   ],
20 |   "ignoreRegExpList": [
21 |     "/`[^`]*`/"
22 |   ],
23 |   "words": [
24 |     "PostgreSQL",
25 |     "Vitaly",
26 |     "Tomilov",
27 |     "savepoint",
28 |     "savepoints",
29 |     "spex",
30 |     "qrec",
31 |     "Millis"
32 |   ],
33 |   "overrides": [
34 |     {
35 |       "filename": "**/*.{ts,js}",
36 |       "ignoreRegExpList": [
37 |         "/@[a-z]+/",
38 |         "/#(end)?region/"
39 |       ],
40 |       "includeRegExpList": [
41 |         "/\\/\\*[\\s\\S]*?\\*\\/|([^\\\\:]|^)\\/\\/.*$/",
42 |         "/(\\/\\/[^\\n\\r]*[\\n\\r]+)/"
43 |       ]
44 |     }
45 |   ]
46 | }
47 | 


--------------------------------------------------------------------------------
/.github/CHANGELOG.md:
--------------------------------------------------------------------------------
 1 | ### Release History
 2 | 
 3 | * 9.0.0 Major update of just about everything. Lots of breaking changes. Released: July 27, 2019.
 4 | * 8.4.0 Replacing `isFresh` with `useCount` everywhere. Released: April 18, 2018.
 5 | * 8.3.0 Adding initialization option `schema` for dynamic schema change. Released: April 17, 2018.
 6 | * 8.2.0 Adding [Conditional Tasks], plus query callbacks. Released: March 10, 2018.
 7 | * 8.1.0 Adding new method [utils.taskArgs]. Released: Feb 26, 2018
 8 | * 8.0.0 Major changes for task and transaction interfaces. Released: Feb 24, 2018
 9 | * 7.5.2 Makes Symbolic CTF within [Custom Type Formatting] global. Released: Feb 12, 2018
10 | * 7.5.1 Added alias `:list` to [CSV Filter]. Released: Feb 12, 2018
11 | * 7.5.0 Extending [CSV Filter]. Released: Feb 12, 2018
12 | * 7.4.1 Added `inTransaction` flag into [TaskContext]. Released: Jan 26, 2018
13 | * 7.4.0 This project is now sponsored by [Lisk]. Released: Jan 20, 2018
14 | * 7.3.0 Updating [as.alias] method, adding method [ColumnSet.assignColumns]. Released: Nov 05, 2017.
15 | * 7.2.0 Renaming `_rawType` into `rawType` within [Custom Type Formatting]. Released: Oct 30, 2017.
16 | * 7.1.0 Adding support for symbols within [Custom Type Formatting]. Released: Oct 29, 2017.
17 | * 7.0.0 Adding methods [multi] and [multiResult] to support multi-query results. Released: Oct 08, 2017.
18 | * 6.10.0 Initial support for [Nested Named Parameters]. Released: Sept 27, 2017
19 | * 6.9.0 Upgrading to [spex] v2.0.0, with the updated protocol. Released: Sept 21, 2017
20 | * 6.8.0 Upgrading [QueryStream] support to use version 1.1.x or later. Released: Sept 20, 2017
21 | * 6.7.0 Upgrading driver [node-postgres] to version 7.x. Released: Sept 17, 2017 
22 | * 6.5.0 [Custom Type Formatting] has been refactored (breaking change). Released: Aug 18, 2017.
23 | * 6.4.0 Adding methods `batch`, `page` and `sequence` to post-`connect` state. Released: Aug 15, 2017.
24 | * 6.3.0 Major re-work on handling connectivity issues. Released: July 01, 2017
25 | * 6.2.0 Extending Task/Transaction context with properties `duration`, `level` and `txLevel`. Released: June 28, 2017.
26 | * 6.1.0 Switching over to the latest 6.4.0 `node-postgres` driver and its new connection pool. Released: June 25, 2017.
27 | * 5.9.0 Added support SQL aliases, plus method `ColumnSet.assign`. Released: June 05, 2017.
28 | * 5.8.0 Added support for warnings to class [QueryFile]. Released: May 29, 2017.
29 | * 5.7.0 Major query formatting overhaul for passing in the calling context. Released: May 15, 2017
30 | * 5.6.0 Removed support for legacy Node.js versions, now requiring 4.x and higher. Released: Feb 25, 2017
31 | * 5.5.5 Extended type `ColumnSet` with new properties `names` and `variables`. Released: Jan 30, 2017
32 | * 5.5.0 Changed the diagnostics for invalid initialization + warnings. Released: Dec 09, 2016
33 | * 5.4.3 Major changes for supporting TypeScript 2.0 (no code changes). Released: Nov 20, 2016.
34 | * 5.4.1 Now forwarding `Date` formatting into the `node-postgres` driver. Released: Nov 20, 2016.
35 | * 5.4.0 Breaking changes: improvements in the [helpers] namespace for the event handlers. Released: Nov 20, 2016.
36 | * 5.2.0 Integrating type [QueryFile] directly into the query-formatting engine. Released: July 15, 2016.
37 | * 5.0.0 Change over to the new version of [spex] 1.0, with new rejection protocol. Released: June 26, 2016.
38 | 
39 | [Nested Named Parameters]:https://github.com/vitaly-t/pg-promise#nested-named-parameters
40 | [QueryStream]:https://github.com/brianc/node-pg-query-stream
41 | [spex]:https://github.com/vitaly-t/spex
42 | [each]:http://vitaly-t.github.io/pg-promise/Database.html#each
43 | [map]:http://vitaly-t.github.io/pg-promise/Database.html#map
44 | [Connection Syntax]:https://github.com/vitaly-t/pg-promise/wiki/Connection-Syntax
45 | [helpers]:http://vitaly-t.github.io/pg-promise/helpers.html
46 | [QueryFile]:http://vitaly-t.github.io/pg-promise/QueryFile.html
47 | [QueryFileError]:http://vitaly-t.github.io/pg-promise/QueryFileError.html
48 | [PreparedStatement]:http://vitaly-t.github.io/pg-promise/PreparedStatement.html
49 | [ParameterizedQuery]:http://vitaly-t.github.io/pg-promise/ParameterizedQuery.html
50 | [Database]:http://vitaly-t.github.io/pg-promise/Database.html
51 | [QueryResultError]:http://vitaly-t.github.io/pg-promise/QueryResultError.html
52 | [Native Bindings]:https://node-postgres.com/features/native
53 | [Initialization Options]:#advanced
54 | [pgp.as]:http://vitaly-t.github.io/pg-promise/formatting.html
55 | [as.value]:http://vitaly-t.github.io/pg-promise/formatting.html#.value
56 | [as.format]:http://vitaly-t.github.io/pg-promise/formatting.html#.format
57 | [as.name]:http://vitaly-t.github.io/pg-promise/formatting.html#.name
58 | [as.alias]:http://vitaly-t.github.io/pg-promise/formatting.html#.alias
59 | [batch]:http://vitaly-t.github.io/pg-promise/Task.html#batch
60 | [sequence]:http://vitaly-t.github.io/pg-promise/Task.html#sequence
61 | [API]:http://vitaly-t.github.io/pg-promise/Database.html
62 | [API Documentation]:http://vitaly-t.github.io/pg-promise/Database.html
63 | [pg-minify]:https://github.com/vitaly-t/pg-minify
64 | [pg-monitor]:https://github.com/vitaly-t/pg-monitor
65 | [pg-promise]:https://github.com/vitaly-t/pg-promise
66 | [PG]:https://github.com/brianc/node-postgres
67 | [pg]:https://github.com/brianc/node-postgres
68 | [node-postgres]:https://github.com/brianc/node-postgres
69 | [Promise]:https://github.com/then/promise
70 | [Learn by Example]:https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example
71 | [Promise Adapter]:https://github.com/vitaly-t/pg-promise/wiki/Promise-Adapter
72 | [Result]:https://node-postgres.com/api/result
73 | [Custom Type Formatting]:https://github.com/vitaly-t/pg-promise#custom-type-formatting
74 | [multi]:http://vitaly-t.github.io/pg-promise/Database.html#multi
75 | [multiResult]:http://vitaly-t.github.io/pg-promise/Database.html#multiResult
76 | [ColumnSet.assignColumns]:http://vitaly-t.github.io/pg-promise/helpers.ColumnSet.html#assignColumns
77 | [Lisk]:https://lisk.io/
78 | [TaskContext]:http://vitaly-t.github.io/pg-promise/global.html#TaskContext
79 | [CSV Filter]:https://github.com/vitaly-t/pg-promise#csv-filter
80 | [utils.taskArgs]:http://vitaly-t.github.io/pg-promise/utils.html#.taskArgs
81 | [Conditional Tasks]:https://github.com/vitaly-t/pg-promise#conditional-tasks
82 | 


--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
 1 | # Contributor Covenant Code of Conduct
 2 | 
 3 | ## Our Pledge
 4 | 
 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
 6 | 
 7 | ## Our Standards
 8 | 
 9 | Examples of behavior that contributes to creating a positive environment include:
10 | 
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 | 
17 | Examples of unacceptable behavior by participants include:
18 | 
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 | 
25 | ## Our Responsibilities
26 | 
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 | 
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 | 
31 | ## Scope
32 | 
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 | 
35 | ## Enforcement
36 | 
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at vitaly.tomilov@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 | 
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 | 
41 | ## Attribution
42 | 
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 | 
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 | 


--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
 1 | Contributing to pg-promise
 2 | --------------------------
 3 | 
 4 | Please take your time reading through this short document, if you want to get proper support for this library.
 5 | 
 6 | ---
 7 | 
 8 | At the time of writing this document, most of the new questions or issues appear to be repeated.
 9 | 
10 | Please search through the following before opening any new issue or asking a question:
11 | 
12 | * [List of all existing issues](https://github.com/vitaly-t/pg-promise/issues?q=is%3Aissue+is%3Aclosed)
13 | * [Questions on StackOverflow](https://stackoverflow.com/questions/tagged/pg-promise)
14 | * [Project's WiKi Pages](https://github.com/vitaly-t/pg-promise/wiki)
15 | * [Official Documentation](http://vitaly-t.github.io/pg-promise/)
16 | 
17 | If your question/issue is not covered by any of the resources above, you should post it on:
18 | 
19 | * [StackOverflow](https://stackoverflow.com), if it is a question, so it can be easily found by others (label it with `pg-promise`);
20 | * [Project's Issues](https://github.com/vitaly-t/pg-promise/issues), if you think that you have found a bug.
21 | 
22 | The author is no longer answering generic questions within [the chat](https://gitter.im/vitaly-t/pg-promise?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge),
23 | as those are neither saved no searchable.  
24 | 
25 | Please do not email me any questions related to the library usage, I do not answer those, as I do not do any support via email.
26 | 
27 | Before creating a PR, see the [Testing](https://github.com/vitaly-t/pg-promise/wiki/Testing) page for instructions on how to test the library locally.
28 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | name: Bug Report
 3 | about: New issues are for bug reports only. For everything else, use Discussions.
 4 | title: ''
 5 | labels: triage
 6 | assignees: vitaly-t
 7 | 
 8 | ---
 9 | 
10 | ### Expected behavior
11 | 
12 | 
13 | ### Actual behavior
14 | 
15 | 
16 | ### Steps to reproduce
17 | 
18 | 
19 | ### Environment
20 | 
21 | * Version of pg-promise:
22 | * OS type (Linux/Windows/Mac):
23 | * Version of Node.js:
24 | 


--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
 1 | name: ci
 2 | on:
 3 |   push:
 4 |     branches:
 5 |       - master
 6 |   pull_request:
 7 |     branches:
 8 |       - '**'
 9 | jobs:
10 |   check-pre-check:
11 |      name: PreCheck
12 |      timeout-minutes: 5
13 |      runs-on: ubuntu-latest
14 |      steps:
15 |        - uses: actions/checkout@v3
16 |        - name: Use Node.js 20
17 |          uses: actions/setup-node@v3
18 |          with:
19 |            node-version: 20
20 |        - name: Install Dependencies
21 |          run: npm install
22 |        - name: TypeScript Lint
23 |          run: npm run tslint
24 |        - name: ESLint
25 |          run: npm run lint
26 |        - name: Spelling Check
27 |          run: npm run spelling
28 |   check-postgres:
29 |     strategy:
30 |       matrix:
31 |         include:
32 |           # Note that we do keep Node v18 here, because v20 changes errors syntax for DB again,
33 |           # which requires refactoring corresponding tests again, and for no good reason at all.
34 |           - name: PostgreSQL 10, Node 18
35 |             POSTGRES_IMAGE: postgres:10
36 |             NODE_VERSION: 18
37 |           - name: PostgreSQL 16, Node 18
38 |             POSTGRES_IMAGE: postgres:16
39 |             NODE_VERSION: 18
40 |       fail-fast: false
41 |     name: ${{ matrix.name }}
42 |     timeout-minutes: 15
43 |     runs-on: ubuntu-latest
44 |     services:
45 |       postgres:
46 |         image: ${{ matrix.POSTGRES_IMAGE }}
47 |         env:
48 |           POSTGRES_HOST: postgres
49 |           POSTGRES_DB: pg_promise_test
50 |           POSTGRES_USER: postgres
51 |           POSTGRES_PASSWORD: postgres
52 |         ports:
53 |           - 5432:5432
54 |         options: >-
55 |           --health-cmd pg_isready
56 |           --health-interval 10s
57 |           --health-timeout 5s
58 |           --health-retries 5
59 |     steps:
60 |       - uses: actions/checkout@v3
61 |       - name: Use Node.js ${{ matrix.NODE_VERSION }}
62 |         uses: actions/setup-node@v3
63 |         with:
64 |           node-version: ${{ matrix.NODE_VERSION }}
65 |       - name: Cache Node.js modules
66 |         uses: actions/cache@v3
67 |         with:
68 |           path: ~/.npm
69 |           key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
70 |           restore-keys: |
71 |             ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
72 |       - name: Install Dependencies
73 |         run: npm install
74 |       - name: Initialize Database
75 |         run: npm run test:init
76 |       - name: Test and Coverage
77 |         run: npm run coverage
78 | concurrency:
79 |   group: ${{ github.workflow }}-${{ github.ref }}
80 |   cancel-in-progress: true
81 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | .idea/
 2 | node_modules/
 3 | coverage/
 4 | API/
 5 | typescript/*.js
 6 | typescript/*.map
 7 | test/typescript/*.js
 8 | test/typescript/*.map
 9 | typings/
10 | generated.js
11 | package-lock.json
12 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | The MIT License (MIT)
 2 | 
 3 | Copyright (c) 2015-2018 Vitaly Tomilov
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
 1 | const js = require("@eslint/js");
 2 | const globals = require("globals");
 3 | 
 4 | module.exports = [
 5 |     js.configs.recommended,
 6 |     {
 7 |         languageOptions: {
 8 |             globals: {
 9 |                 ...globals.es6,
10 |                 ...globals.node,
11 |                 ...globals.jasmine,
12 |                 ...globals.BigInt,
13 |             },
14 |             parserOptions: {
15 |                 ecmaFeatures: { globalReturn: true },
16 |             },
17 |             sourceType: "commonjs",
18 |             ecmaVersion: 2022,
19 |         },
20 |         rules: {
21 |             "no-var": "error",
22 |             "prefer-const": "error",
23 |             "prefer-arrow-callback": "error",
24 |             "no-else-return": "error",
25 |             "no-multi-spaces": "error",
26 |             "no-whitespace-before-property": "error",
27 |             camelcase: "error",
28 |             "new-cap": "error",
29 |             "no-console": "error",
30 |             "comma-dangle": "error",
31 |             "no-shadow": "error",
32 |             "object-shorthand": ["error", "properties"],
33 |             indent: [
34 |                 "error",
35 |                 4,
36 |                 {
37 |                     SwitchCase: 1,
38 |                 },
39 |             ],
40 |             quotes: ["error", "single"],
41 |             semi: ["error", "always"],
42 |         },
43 |     },
44 | ];
45 | 


--------------------------------------------------------------------------------
/examples/advanced.js:
--------------------------------------------------------------------------------
1 | /*
2 | 
3 |  For an advanced pg-promise demo of building enterprise-level applications see:
4 | 
5 |  https://github.com/vitaly-t/pg-promise-demo
6 | 
7 |  */
8 | 


--------------------------------------------------------------------------------
/examples/monitor.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable */
 2 | 
 3 | ////////////////////////////////////////////////////
 4 | // This is a complete test application, which shows
 5 | // how to use the following options:
 6 | //
 7 | // a) override the default promise library;
 8 | // b) use pg-monitor to output all the query events;
 9 | // c) change the default theme for pg-monitor;
10 | // d) add log handler to pg-monitor, to log events into a file or elsewhere.
11 | //
12 | // Packages used: pg-promise, pg-monitor, bluebird.
13 | ////////////////////////////////////////////////////
14 | 
15 | const promise = require('bluebird'); // or any other Promise/A+ compatible library;
16 | 
17 | const initOptions = {
18 |     promiseLib: promise // overriding the default (ES6 Promise);
19 | };
20 | 
21 | const pgp = require('pg-promise')(initOptions);
22 | // See all options: http://vitaly-t.github.io/pg-promise/module-pg-promise.html
23 | 
24 | const monitor = require('pg-monitor');
25 | 
26 | monitor.attach(initOptions); // attach to all query events;
27 | // See API: https://github.com/vitaly-t/pg-monitor#attachoptions-events-override
28 | 
29 | monitor.setTheme('matrix'); // change the default theme;
30 | // Other themes: https://github.com/vitaly-t/pg-monitor/wiki/Color-Themes
31 | 
32 | monitor.setLog((msg, info) => {
33 |     // save the screen messages into your own log file;
34 | });
35 | // See API: https://github.com/vitaly-t/pg-monitor#log
36 | 
37 | // Database connection details;
38 | const cn = {
39 |     host: 'localhost', // 'localhost' is the default;
40 |     port: 5432, // 5432 is the default;
41 |     database: 'myDatabase',
42 |     user: 'myUser',
43 |     password: 'myPassword',
44 | 
45 |     // to auto-exit on idle, without having to shut down the pool;
46 |     // see https://github.com/vitaly-t/pg-promise#library-de-initialization
47 |     allowExitOnIdle: true
48 | };
49 | 
50 | const db = pgp(cn); // database instance;
51 | 
52 | db.any('select * from users where active = $1', [true])
53 |     .then(data => {
54 |         console.log('DATA:', data);
55 |     })
56 |     .catch(error => {
57 |         console.log('ERROR:', error);
58 |     });
59 | 


--------------------------------------------------------------------------------
/examples/query.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable */
 2 | 
 3 | ///////////////////////////////////////////////
 4 | // This is to show a complete test application;
 5 | ///////////////////////////////////////////////
 6 | 
 7 | const promise = require('bluebird'); // or any other Promise/A+ compatible library;
 8 | 
 9 | const initOptions = {
10 |     promiseLib: promise // overriding the default (ES6 Promise);
11 | };
12 | 
13 | const pgp = require('pg-promise')(initOptions);
14 | // See also: http://vitaly-t.github.io/pg-promise/module-pg-promise.html
15 | 
16 | // Database connection details;
17 | const cn = {
18 |     host: 'localhost', // 'localhost' is the default;
19 |     port: 5432, // 5432 is the default;
20 |     database: 'myDatabase',
21 |     user: 'myUser',
22 |     password: 'myPassword',
23 | 
24 |     // to auto-exit on idle, without having to shut down the pool;
25 |     // see https://github.com/vitaly-t/pg-promise#library-de-initialization
26 |     allowExitOnIdle: true
27 | };
28 | // You can check for all default values in:
29 | // https://github.com/brianc/node-postgres/blob/master/packages/pg/lib/defaults.js
30 | 
31 | const db = pgp(cn); // database instance;
32 | 
33 | db.any('select * from users where active = $1', [true])
34 |     .then(data => {
35 |         console.log('DATA:', data); // print data;
36 |     })
37 |     .catch(error => {
38 |         console.log('ERROR:', error); // print the error;
39 |     });
40 | 


--------------------------------------------------------------------------------
/examples/select-insert.md:
--------------------------------------------------------------------------------
 1 | # SELECT ⇒ INSERT
 2 | 
 3 | The following scenario is very common in adding new records:
 4 | 
 5 | * try finding a specific record, and if found - return its id;
 6 | * if no record found, add a new one and return the new id.
 7 | 
 8 | ```sql
 9 | -- a simple table example
10 | CREATE TABLE Users(
11 | 	id SERIAL PRIMARY KEY,
12 | 	name TEXT UNIQUE -- unique user name
13 | );
14 | ```
15 | 
16 | Let's implement a function, according to that logic, to search by user's `name`, and return
17 | a new or existing `id` of the record. 
18 |  
19 | ```js
20 | function getInsertUserId(name) {
21 |     return db.task('getInsertUserId', t => {
22 |             return t.oneOrNone('SELECT id FROM Users WHERE name = $1', name, u => u && u.id)
23 |                 .then(userId => {
24 |                     return userId || t.one('INSERT INTO Users(name) VALUES($1) RETURNING id', name, u => u.id);
25 |                 });
26 |         });
27 | }
28 | ```
29 | 
30 | Example of calling the function:
31 | 
32 | ```js 
33 | getInsertUserId('name')
34 |     .then(userId => {
35 |         // use the id;
36 |     })
37 |     .catch(error => {
38 |         // something went wrong;
39 |     });
40 | ```
41 | 
42 | The same function `getInsertUserId`, using ES7 `async` syntax:
43 | 
44 | ```js
45 | async function getInsertUserId(name) {
46 |     return db.task('getInsertUserId', async t => {
47 |         const userId = await t.oneOrNone('SELECT id FROM Users WHERE name = $1', name, u => u && u.id);
48 |         return userId || await t.one('INSERT INTO Users(name) VALUES($1) RETURNING id', name, u => u.id);
49 |     });
50 | }
51 | ```
52 | 
53 | ## Single-query alternative
54 | 
55 | It is possible to wrap the whole operation into a single query, which would offer a better
56 | performance, executing always just one query, and more importantly - proper data integrity,
57 | by making sure that a parallel request would not try to execute a second `INSERT`. 
58 | 
59 | Implementing such a query however isn't trivial, and it can vary based on whether it is for
60 | PostgreSQL 9.5+ or an older version of the server.
61 | 
62 | The following posts will help you get started writing your own single-query solution for this:
63 | 
64 | * [Id from a conditional INSERT](http://stackoverflow.com/questions/36083669/get-id-from-a-conditional-insert)
65 | * [SELECT ⇒ INSERT in a function](http://stackoverflow.com/questions/15939902/is-select-or-insert-in-a-function-prone-to-race-conditions)
66 | 


--------------------------------------------------------------------------------
/examples/transaction.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable */
 2 | 
 3 | ///////////////////////////////////////////////
 4 | // This is to show a complete test application;
 5 | ///////////////////////////////////////////////
 6 | 
 7 | const promise = require('bluebird'); // or any other Promise/A+ compatible library;
 8 | 
 9 | const initOptions = {
10 |     promiseLib: promise // overriding the default (ES6 Promise);
11 | };
12 | 
13 | const pgp = require('pg-promise')(initOptions);
14 | // See also: http://vitaly-t.github.io/pg-promise/module-pg-promise.html
15 | 
16 | // Database connection details;
17 | const cn = {
18 |     host: 'localhost', // 'localhost' is the default;
19 |     port: 5432, // 5432 is the default;
20 |     database: 'myDatabase',
21 |     user: 'myUser',
22 |     password: 'myPassword',
23 | 
24 |     // to auto-exit on idle, without having to shut down the pool;
25 |     // see https://github.com/vitaly-t/pg-promise#library-de-initialization
26 |     allowExitOnIdle: true
27 | };
28 | // You can check for all default values in:
29 | // https://github.com/brianc/node-postgres/blob/master/packages/pg/lib/defaults.js
30 | 
31 | const db = pgp(cn); // database instance;
32 | 
33 | db.tx(async t => {
34 |     const user = await t.one('INSERT INTO users(name) VALUES($1) RETURNING id', 'John');
35 |     const event = await t.one('INSERT INTO events(code) VALUES($1) RETURNING id', 123);
36 |     return {user, event};
37 | })
38 |     .then(({user, event}) => {
39 |         // print new user id + new event id;
40 |         console.log('DATA:', user.id, event.id);
41 |     })
42 |     .catch(error => {
43 |         console.log('ERROR:', error); // print the error;
44 |     });
45 | 


--------------------------------------------------------------------------------
/jsdoc/README.md:
--------------------------------------------------------------------------------
  1 | ## Installing
  2 | 
  3 | ```
  4 | $ npm install pg-promise
  5 | ```
  6 | 
  7 | ## Initialization
  8 | 
  9 | Loading and initializing the library with [Initialization Options]:
 10 | 
 11 | ```js
 12 | const initOptions = {/* initialization options */};
 13 | const pgp = require('pg-promise')(initOptions);
 14 | ```
 15 | 
 16 | − or without [Initialization Options]:
 17 | 
 18 | ```js
 19 | const pgp = require('pg-promise')();
 20 | ```
 21 | 
 22 | ## Database
 23 | 
 24 | Create your [Database] object from the connection as `pgp(connection, [dc])`:
 25 | 
 26 | ```js
 27 | const db = pgp(connection);
 28 | ```
 29 | 
 30 | * The `connection` parameter is either a [Configuration Object] or a [Connection String].
 31 | * `dc` = Database Context - optional parameter (see [Database] constructor).
 32 | 
 33 | Object `db` represents the [Database] protocol with lazy connection, i.e. only the actual query methods acquire
 34 | and release the connection automatically. Therefore, you should create only one global/shared `db` object per connection details.
 35 | 
 36 | It is best to initialize the library and create [Database] in its own module, see [Where should I initialize pg-promise].
 37 | 
 38 | ## Usage
 39 | 
 40 | [Learn by Example] is the best quick-start tutorial. For everything else see the [WiKi] pages.
 41 | 
 42 | ## References
 43 | 
 44 | ### External Resources
 45 | 
 46 | * [The library's Main Page](https://github.com/vitaly-t/pg-promise)
 47 | * [TypeScript 4.x declarations](https://github.com/vitaly-t/pg-promise/tree/master/typescript)
 48 | * [The library's WiKi Pages](https://github.com/vitaly-t/pg-promise/wiki)
 49 | * [Popular questions on StackOverflow](https://stackoverflow.com/questions/tagged/pg-promise?sort=votes&pageSize=50) 
 50 | 
 51 | ### Main Types
 52 |  
 53 | * [Database] - database-level methods and properties
 54 | * [Task](http://vitaly-t.github.io/pg-promise/Task.html) - extends [Database] with task-level methods and properties
 55 | 
 56 | [Database]:http://vitaly-t.github.io/pg-promise/Database.html
 57 | 
 58 | ### Special Types
 59 | 
 60 | * [QueryFile] - type for working with external SQL files
 61 | * [PreparedStatement] - type for working with [Prepared Statements]
 62 | * [ParameterizedQuery] - type for working with [Parameterized Queries]
 63 | * [TransactionMode] - transaction configuration type
 64 | * [PromiseAdapter] - adapter for using non-standard promise libraries
 65 | 
 66 | [QueryFile]:http://vitaly-t.github.io/pg-promise/QueryFile.html
 67 | [PreparedStatement]:http://vitaly-t.github.io/pg-promise/PreparedStatement.html
 68 | [ParameterizedQuery]:http://vitaly-t.github.io/pg-promise/ParameterizedQuery.html
 69 | [TransactionMode]:http://vitaly-t.github.io/pg-promise/txMode.TransactionMode.html
 70 | [PromiseAdapter]:http://vitaly-t.github.io/pg-promise/PromiseAdapter.html
 71 | [Prepared Statements]:https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#prepared-statements
 72 | [Parameterized Queries]:https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#parameterized-queries
 73 | 
 74 | ### Namespaces
 75 | 
 76 | * [formatting] - the library's query formatting engine
 77 | * [ctf] - ES6 symbols used by [Custom Type Formatting]
 78 | * [helpers] - for automatic query generation
 79 | * [utils] - simplifies the use of external SQL files
 80 | * [errors] - custom error types supported by the library
 81 | * [txMode] - types for configuring a transaction
 82 | 
 83 | [formatting]:http://vitaly-t.github.io/pg-promise/formatting.html
 84 | [ctf]:http://vitaly-t.github.io/pg-promise/formatting.ctf.html
 85 | [helpers]:http://vitaly-t.github.io/pg-promise/helpers.html
 86 | [utils]:http://vitaly-t.github.io/pg-promise/utils.html
 87 | [errors]:http://vitaly-t.github.io/pg-promise/errors.html
 88 | [txMode]:http://vitaly-t.github.io/pg-promise/txMode.html
 89 | 
 90 | ### Events
 91 | 
 92 | * [connect] - connecting to the database
 93 | * [disconnect] - disconnecting from the database
 94 | * [query] - executing a query
 95 | * [task] - task start/end events
 96 | * [transact] - transaction start/end events
 97 | * [receive] - receiving data from a query
 98 | * [error] - global error handler
 99 | * [extend] - interface extension event
100 | 
101 | [connect]:http://vitaly-t.github.io/pg-promise/global.html#event:connect
102 | [disconnect]:http://vitaly-t.github.io/pg-promise/global.html#event:disconnect
103 | [query]:http://vitaly-t.github.io/pg-promise/global.html#event:query
104 | [task]:http://vitaly-t.github.io/pg-promise/global.html#event:task
105 | [transact]:http://vitaly-t.github.io/pg-promise/global.html#event:transact
106 | [receive]:http://vitaly-t.github.io/pg-promise/global.html#event:receive
107 | [error]:http://vitaly-t.github.io/pg-promise/global.html#event:error
108 | [extend]:http://vitaly-t.github.io/pg-promise/global.html#event:extend
109 | 
110 | [Configuration Object]:https://github.com/vitaly-t/pg-promise/wiki/Connection-Syntax#configuration-object
111 | [Connection String]:https://github.com/vitaly-t/pg-promise/wiki/Connection-Syntax#connection-string
112 | [Initialization Options]:http://vitaly-t.github.io/pg-promise/module-pg-promise.html
113 | [Where should I initialize pg-promise]:https://stackoverflow.com/questions/34382796/where-should-i-initialize-pg-promise
114 | [Learn by Example]:https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example
115 | [WiKi]:https://github.com/vitaly-t/pg-promise/wiki
116 | [Custom Type Formatting]:https://github.com/vitaly-t/pg-promise#custom-type-formatting
117 | 


--------------------------------------------------------------------------------
/jsdoc/fixLinks.js:
--------------------------------------------------------------------------------
 1 | // Automatic links:
 2 | const links = {
 3 |     'Promises/A+': 'https://promisesaplus.com',
 4 |     'spex': 'https://github.com/vitaly-t/spex',
 5 |     'spex.batch': 'http://vitaly-t.github.io/spex/global.html#batch',
 6 |     'spex.page': 'http://vitaly-t.github.io/spex/global.html#page',
 7 |     'spex.sequence': 'http://vitaly-t.github.io/spex/global.html#sequence',
 8 |     'Result': 'https://node-postgres.com/apis/result',
 9 |     'pg-query-stream': 'https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream',
10 |     'QueryStream': 'https://github.com/brianc/node-postgres/blob/master/packages/pg-query-stream/src/index.ts',
11 |     'pg.Client': 'https://node-postgres.com/apis/client',
12 |     'BEGIN': 'http://www.postgresql.org/docs/9.6/static/sql-begin.html',
13 |     'Transaction Isolation': 'http://www.postgresql.org/docs/9.6/static/transaction-iso.html',
14 |     'pg-minify': 'https://github.com/vitaly-t/pg-minify',
15 |     'SQLParsingError': 'https://github.com/vitaly-t/pg-minify/blob/master/lib/error.js',
16 |     'PG': 'https://github.com/brianc/node-postgres',
17 |     'pg': 'https://github.com/brianc/node-postgres',
18 |     'pg-pool': 'https://github.com/brianc/node-postgres/tree/master/packages/pg-pool',
19 |     'Native Bindings': 'https://node-postgres.com/features/native',
20 |     'pg-native': 'https://github.com/brianc/node-postgres/tree/master/packages/pg-native',
21 |     'Named Parameters': 'https://github.com/vitaly-t/pg-promise#named-parameters',
22 |     'Index Variables': 'https://github.com/vitaly-t/pg-promise#index-variables',
23 |     'Nested Named Parameters': 'https://github.com/vitaly-t/pg-promise#nested-named-parameters',
24 |     'tags': 'https://github.com/vitaly-t/pg-promise/wiki/tags',
25 |     'Chaining Queries': 'https://github.com/vitaly-t/pg-promise/wiki/Chaining-Queries',
26 |     'Performance Boost': 'https://github.com/vitaly-t/pg-promise/wiki/Performance-Boost',
27 |     'Prepared Statement': 'http://www.postgresql.org/docs/9.6/static/sql-prepare.html',
28 |     'Prepared Statements': 'http://www.postgresql.org/docs/9.6/static/sql-prepare.html',
29 |     'Custom Type Formatting': 'https://github.com/vitaly-t/pg-promise#custom-type-formatting',
30 |     'Symbolic CTF': 'https://github.com/vitaly-t/pg-promise#symbolic-ctf',
31 |     'SQL Names': 'https://github.com/vitaly-t/pg-promise#sql-names',
32 |     'pg-promise-demo': 'https://github.com/vitaly-t/pg-promise-demo',
33 |     'Robust Listeners': 'https://github.com/vitaly-t/pg-promise/wiki/Robust-Listeners',
34 |     'Promise Adapter': 'https://github.com/vitaly-t/pg-promise/wiki/Promise-Adapter',
35 |     'Bluebird': 'https://github.com/petkaantonov/bluebird',
36 |     'Long Stack Traces': 'http://bluebirdjs.com/docs/api/promise.config.html',
37 |     'Symbol': 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
38 |     'Library de-initialization': 'https://github.com/vitaly-t/pg-promise#library-de-initialization',
39 |     'Nested Transactions': 'https://github.com/vitaly-t/pg-promise#nested-transactions',
40 |     'changing the database or the role': 'https://stackoverflow.com/questions/2875610/permanently-set-postgresql-schema-path',
41 |     'Promise.allSettled': 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled'
42 | };
43 | 
44 | function fixLinks(source) {
45 |     return source.replace(/\$\[[a-z0-9\s/+-.]+\]/gi, name => {
46 |         const sln = name.replace(/\$\[|\]/g, ''); // stripped link name;
47 |         if (sln in links) {
48 |             return '<a href="' + links[sln] + '">' + sln + '</a>';
49 |         }
50 |         return name;
51 |     });
52 | }
53 | 
54 | module.exports = {fixLinks};
55 | 


--------------------------------------------------------------------------------
/jsdoc/jsdoc.js:
--------------------------------------------------------------------------------
 1 | module.exports = {
 2 |     source: {
 3 |         include: [
 4 |             'lib'
 5 |         ]
 6 |     },
 7 |     opts: {
 8 |         recurse: true,
 9 |         destination: './API'
10 |     },
11 |     templates: {
12 |         default: {
13 |             layoutFile: './jsdoc/layout.html',
14 |             staticFiles: {
15 |                 include: [
16 |                     './jsdoc/style.css'
17 |                 ]
18 |             }
19 |         }
20 |     },
21 |     plugins: [
22 |         'plugins/markdown',
23 |         './jsdoc/shortLinks'
24 |     ]
25 | };
26 | 


--------------------------------------------------------------------------------
/jsdoc/layout.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |     <meta charset="utf-8">
 5 |     <title>pg-promise API</title>
 6 |     <script src="scripts/prettify/prettify.js"></script>
 7 |     <script src="scripts/prettify/lang-css.js"></script>
 8 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 9 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
10 |     <link type="text/css" rel="stylesheet" href="style.css">
11 | </head>
12 | 
13 | <body>
14 | 
15 | <nav>
16 |     <?js= this.nav ?>
17 |     <div class="home-link">
18 |         <a href="https://github.com/vitaly-t/pg-promise">&lt;&lt; GitHub</a>
19 |     </div>
20 | </nav>
21 | 
22 | <div id="main">
23 |     <?js= content ?>
24 | </div>
25 | 
26 | <br class="clear">
27 | 
28 | <footer>
29 | </footer>
30 | 
31 | <script> prettyPrint(); </script>
32 | <script src="scripts/linenumber.js"></script>
33 | </body>
34 | </html>
35 | 


--------------------------------------------------------------------------------
/jsdoc/shortLinks.js:
--------------------------------------------------------------------------------
1 | const {fixLinks} = require('./fixLinks');
2 | 
3 | exports.handlers = {
4 |     beforeParse(e) {
5 |         e.source = fixLinks(e.source);
6 |     }
7 | };
8 | 


--------------------------------------------------------------------------------
/jsdoc/style.css:
--------------------------------------------------------------------------------
  1 | body {
  2 |     margin: 0;
  3 | }
  4 | 
  5 | html {
  6 |     font-size: 16px;
  7 | }
  8 | 
  9 | html, body, section {
 10 |     background-color: #F0F0F0;
 11 | }
 12 | 
 13 | pre.prettyprint:not(pre.source) {
 14 |     width: auto;
 15 |     border: 1px solid lightgrey;
 16 |     padding: 10px;
 17 | }
 18 | 
 19 | p>code, .description code {
 20 |     background-color: lightgray;
 21 | }
 22 | 
 23 | h4.name {
 24 |     border-radius: 7px;
 25 |     padding: 4px 10px;
 26 |     background-color: rgb(16, 71, 70);
 27 |     color: rgb(136, 191, 190);
 28 |     font-size: 24px;
 29 | }
 30 | 
 31 | div#main {
 32 |     margin-left: 280px;
 33 |     float: none;
 34 | }
 35 | 
 36 | code {
 37 |     border-radius: 3px;
 38 |     padding: 2px 4px;
 39 | }
 40 | 
 41 | nav {
 42 |     background-color: #222;
 43 |     padding: 10px 20px 20px 20px;
 44 |     width: auto;
 45 |     top: 0;
 46 |     bottom: 0;
 47 |     position: fixed;
 48 |     font-size: 18px;
 49 |     margin-top: 0px;
 50 |     line-height: 24px;
 51 |     float: none;
 52 |     overflow-y: auto;
 53 | }
 54 | 
 55 | nav h2 a,
 56 | nav h2 a:visited,
 57 | nav div.home-link a,
 58 | nav div.home-link a:visited {
 59 |     width: 100%;
 60 |     color: Gold;
 61 | }
 62 | 
 63 | nav ul li a,
 64 | nav ul li a:visited {
 65 |     color: #EEE;
 66 |     font-size: 17px;
 67 | }
 68 | 
 69 | nav ul li a:hover {
 70 |     color: #CC0;
 71 | }
 72 | 
 73 | nav h3 {
 74 |     color: LightGreen;
 75 |     font-size: 18px;
 76 | }
 77 | 
 78 | nav h2 {
 79 |     font-size: 20px;
 80 | }
 81 | 
 82 | .nav li a {
 83 |     color: white !important;
 84 | }
 85 | 
 86 | .home-link {
 87 |     padding-top: 20px;
 88 | }
 89 | 
 90 | .home-link a {
 91 |     font-size: 16px;
 92 |     font-weight: bold;
 93 | }
 94 | 
 95 | table.params th:first-child,
 96 | table.props th:first-child {
 97 |     border-top-left-radius: 5px;
 98 | }
 99 | 
100 | table.params th:last-child,
101 | table.props th:last-child {
102 |     border-top-right-radius: 5px;
103 | }
104 | 
105 | table.params th,
106 | table.props th {
107 |     border: none;
108 |     border-right: 1px solid #F5F5F5;
109 | }
110 | 
111 | table.params th,
112 | table.props th {
113 |     font-family: 'Verdana';
114 |     font-weight: normal;
115 | }
116 | 
117 | table.params th {
118 |     background-color: SteelBlue;
119 |     color: White;
120 | }
121 | 
122 | table.props th {
123 |     background-color: DarkCyan;
124 |     color: White;
125 | }
126 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Bold-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Bold-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Bold-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-BoldItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-BoldItalic-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-BoldItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-BoldItalic-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Italic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Italic-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Italic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Italic-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Light-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Light-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Light-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-LightItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-LightItalic-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-LightItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-LightItalic-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Regular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Regular-webfont.eot


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/fonts/OpenSans-Regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/jsdoc/templates/custom/static/fonts/OpenSans-Regular-webfont.woff


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/scripts/linenumber.js:
--------------------------------------------------------------------------------
 1 | /*global document */
 2 | (function() {
 3 |     var source = document.getElementsByClassName('prettyprint source linenums');
 4 |     var i = 0;
 5 |     var lineNumber = 0;
 6 |     var lineId;
 7 |     var lines;
 8 |     var totalLines;
 9 |     var anchorHash;
10 | 
11 |     if (source && source[0]) {
12 |         anchorHash = document.location.hash.substring(1);
13 |         lines = source[0].getElementsByTagName('li');
14 |         totalLines = lines.length;
15 | 
16 |         for (; i < totalLines; i++) {
17 |             lineNumber++;
18 |             lineId = 'line' + lineNumber;
19 |             lines[i].id = lineId;
20 |             if (lineId === anchorHash) {
21 |                 lines[i].className += ' selected';
22 |             }
23 |         }
24 |     }
25 | })();
26 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
3 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/styles/prettify-jsdoc.css:
--------------------------------------------------------------------------------
  1 | /* JSDoc prettify.js theme */
  2 | 
  3 | /* plain text */
  4 | .pln {
  5 |   color: #000000;
  6 |   font-weight: normal;
  7 |   font-style: normal;
  8 | }
  9 | 
 10 | /* string content */
 11 | .str {
 12 |   color: #006400;
 13 |   font-weight: normal;
 14 |   font-style: normal;
 15 | }
 16 | 
 17 | /* a keyword */
 18 | .kwd {
 19 |   color: #000000;
 20 |   font-weight: bold;
 21 |   font-style: normal;
 22 | }
 23 | 
 24 | /* a comment */
 25 | .com {
 26 |   font-weight: normal;
 27 |   font-style: italic;
 28 | }
 29 | 
 30 | /* a type name */
 31 | .typ {
 32 |   color: #000000;
 33 |   font-weight: normal;
 34 |   font-style: normal;
 35 | }
 36 | 
 37 | /* a literal value */
 38 | .lit {
 39 |   color: #006400;
 40 |   font-weight: normal;
 41 |   font-style: normal;
 42 | }
 43 | 
 44 | /* punctuation */
 45 | .pun {
 46 |   color: #000000;
 47 |   font-weight: bold;
 48 |   font-style: normal;
 49 | }
 50 | 
 51 | /* lisp open bracket */
 52 | .opn {
 53 |   color: #000000;
 54 |   font-weight: bold;
 55 |   font-style: normal;
 56 | }
 57 | 
 58 | /* lisp close bracket */
 59 | .clo {
 60 |   color: #000000;
 61 |   font-weight: bold;
 62 |   font-style: normal;
 63 | }
 64 | 
 65 | /* a markup tag name */
 66 | .tag {
 67 |   color: #006400;
 68 |   font-weight: normal;
 69 |   font-style: normal;
 70 | }
 71 | 
 72 | /* a markup attribute name */
 73 | .atn {
 74 |   color: #006400;
 75 |   font-weight: normal;
 76 |   font-style: normal;
 77 | }
 78 | 
 79 | /* a markup attribute value */
 80 | .atv {
 81 |   color: #006400;
 82 |   font-weight: normal;
 83 |   font-style: normal;
 84 | }
 85 | 
 86 | /* a declaration */
 87 | .dec {
 88 |   color: #000000;
 89 |   font-weight: bold;
 90 |   font-style: normal;
 91 | }
 92 | 
 93 | /* a variable name */
 94 | .var {
 95 |   color: #000000;
 96 |   font-weight: normal;
 97 |   font-style: normal;
 98 | }
 99 | 
100 | /* a function name */
101 | .fun {
102 |   color: #000000;
103 |   font-weight: bold;
104 |   font-style: normal;
105 | }
106 | 
107 | /* Specify class=linenums on a pre to get line numbering */
108 | ol.linenums {
109 |   margin-top: 0;
110 |   margin-bottom: 0;
111 | }
112 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/static/styles/prettify-tomorrow.css:
--------------------------------------------------------------------------------
  1 | /* Tomorrow Theme */
  2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
  3 | /* Pretty printing styles. Used with prettify.js. */
  4 | /* SPAN elements with the classes below are added by prettyprint. */
  5 | /* plain text */
  6 | .pln {
  7 |   color: #4d4d4c; }
  8 | 
  9 | @media screen {
 10 |   /* string content */
 11 |   .str {
 12 |     color: #718c00; }
 13 | 
 14 |   /* a keyword */
 15 |   .kwd {
 16 |     color: #8959a8; }
 17 | 
 18 |   /* a comment */
 19 |   .com {
 20 |     color: #8e908c; }
 21 | 
 22 |   /* a type name */
 23 |   .typ {
 24 |     color: #4271ae; }
 25 | 
 26 |   /* a literal value */
 27 |   .lit {
 28 |     color: #f5871f; }
 29 | 
 30 |   /* punctuation */
 31 |   .pun {
 32 |     color: #4d4d4c; }
 33 | 
 34 |   /* lisp open bracket */
 35 |   .opn {
 36 |     color: #4d4d4c; }
 37 | 
 38 |   /* lisp close bracket */
 39 |   .clo {
 40 |     color: #4d4d4c; }
 41 | 
 42 |   /* a markup tag name */
 43 |   .tag {
 44 |     color: #c82829; }
 45 | 
 46 |   /* a markup attribute name */
 47 |   .atn {
 48 |     color: #f5871f; }
 49 | 
 50 |   /* a markup attribute value */
 51 |   .atv {
 52 |     color: #3e999f; }
 53 | 
 54 |   /* a declaration */
 55 |   .dec {
 56 |     color: #f5871f; }
 57 | 
 58 |   /* a variable name */
 59 |   .var {
 60 |     color: #c82829; }
 61 | 
 62 |   /* a function name */
 63 |   .fun {
 64 |     color: #4271ae; } }
 65 | /* Use higher contrast and text-weight for printable form. */
 66 | @media print, projection {
 67 |   .str {
 68 |     color: #060; }
 69 | 
 70 |   .kwd {
 71 |     color: #006;
 72 |     font-weight: bold; }
 73 | 
 74 |   .com {
 75 |     color: #600;
 76 |     font-style: italic; }
 77 | 
 78 |   .typ {
 79 |     color: #404;
 80 |     font-weight: bold; }
 81 | 
 82 |   .lit {
 83 |     color: #044; }
 84 | 
 85 |   .pun, .opn, .clo {
 86 |     color: #440; }
 87 | 
 88 |   .tag {
 89 |     color: #006;
 90 |     font-weight: bold; }
 91 | 
 92 |   .atn {
 93 |     color: #404; }
 94 | 
 95 |   .atv {
 96 |     color: #060; } }
 97 | /* Style */
 98 | /*
 99 | pre.prettyprint {
100 |   background: white;
101 |   font-family: Consolas, Monaco, 'Andale Mono', monospace;
102 |   font-size: 12px;
103 |   line-height: 1.5;
104 |   border: 1px solid #ccc;
105 |   padding: 10px; }
106 | */
107 | 
108 | /* Specify class=linenums on a pre to get line numbering */
109 | ol.linenums {
110 |   margin-top: 0;
111 |   margin-bottom: 0; }
112 | 
113 | /* IE indents via margin-left */
114 | li.L0,
115 | li.L1,
116 | li.L2,
117 | li.L3,
118 | li.L4,
119 | li.L5,
120 | li.L6,
121 | li.L7,
122 | li.L8,
123 | li.L9 {
124 |   /* */ }
125 | 
126 | /* Alternate shading for lines */
127 | li.L1,
128 | li.L3,
129 | li.L5,
130 | li.L7,
131 | li.L9 {
132 |   /* */ }
133 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/augments.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 |     var data = obj;
 3 |     var self = this;
 4 | ?>
 5 | 
 6 | <?js if (data.augments && data.augments.length) { ?>
 7 |     <ul><?js data.augments.forEach(function(a) { ?>
 8 |         <li><?js= self.linkto(a, a) ?></li>
 9 |     <?js }) ?></ul>
10 | <?js } ?>
11 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/container.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var self = this;
  3 |     var isGlobalPage;
  4 | 
  5 |     docs.forEach(function(doc, i) {
  6 | ?>
  7 | 
  8 | <?js
  9 |     // we only need to check this once
 10 |     if (typeof isGlobalPage === 'undefined') {
 11 |         isGlobalPage = (doc.kind === 'globalobj');
 12 |     }
 13 | ?>
 14 | <?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?>
 15 |     <?js= self.partial('mainpage.tmpl', doc) ?>
 16 | <?js } else if (doc.kind === 'source') { ?>
 17 |     <?js= self.partial('source.tmpl', doc) ?>
 18 | <?js } else { ?>
 19 | 
 20 | <section>
 21 | 
 22 | <header>
 23 |     <?js if (!doc.longname || doc.kind !== 'module') { ?>
 24 |         <h2><?js if (doc.attribs) { ?><span class="attribs"><?js= doc.attribs ?></span><?js }
 25 |             if (doc.ancestors && doc.ancestors.length) { ?>
 26 |             <span class="ancestors"><?js= doc.ancestors.join('') ?></span><?js
 27 |          }
 28 |         ?><?js= doc.name ?><?js
 29 |          if (doc.variation) { ?>
 30 |             <sup class="variation"><?js= doc.variation ?></sup><?js }
 31 |          if (doc.signature && !doc.hideconstructor) { ?><?js= doc.signature ?><?js } ?></h2>
 32 |         <?js if (doc.classdesc) { ?>
 33 |             <div class="class-description"><?js= doc.classdesc ?></div>
 34 |         <?js } ?>
 35 |     <?js } else if (doc.kind === 'module' && doc.modules) { ?>
 36 |         <?js doc.modules.forEach(function(module) { ?>
 37 |             <?js if (module.classdesc) { ?>
 38 |                 <div class="class-description"><?js= module.classdesc ?></div>
 39 |             <?js } ?>
 40 |         <?js }) ?>
 41 |     <?js } ?>
 42 | </header>
 43 | 
 44 | <article>
 45 |     <div class="container-overview">
 46 |     <?js if (doc.kind === 'module' && doc.modules) { ?>
 47 |         <?js if (doc.description) { ?>
 48 |             <div class="description"><?js= doc.description ?></div>
 49 |         <?js } ?>
 50 | 
 51 |         <?js doc.modules.forEach(function(module) { ?>
 52 |             <?js= self.partial('method.tmpl', module) ?>
 53 |         <?js }) ?>
 54 |     <?js } else if (doc.kind === 'class' || (doc.kind === 'namespace' && doc.signature)) { ?>
 55 |         <?js= self.partial('method.tmpl', doc) ?>
 56 |     <?js } else { ?>
 57 |         <?js if (doc.description) { ?>
 58 |             <div class="description"><?js= doc.description ?></div>
 59 |         <?js } ?>
 60 | 
 61 |         <?js= self.partial('details.tmpl', doc) ?>
 62 | 
 63 |         <?js if (doc.examples && doc.examples.length) { ?>
 64 |             <h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>
 65 |             <?js= self.partial('examples.tmpl', doc.examples) ?>
 66 |         <?js } ?>
 67 |     <?js } ?>
 68 |     </div>
 69 | 
 70 |     <?js if (doc.augments && doc.augments.length) { ?>
 71 |         <h3 class="subsection-title">Extends</h3>
 72 | 
 73 |         <?js= self.partial('augments.tmpl', doc) ?>
 74 |     <?js } ?>
 75 | 
 76 |     <?js if (doc.requires && doc.requires.length) { ?>
 77 |         <h3 class="subsection-title">Requires</h3>
 78 | 
 79 |         <ul><?js doc.requires.forEach(function(r) { ?>
 80 |             <li><?js= self.linkto(r, r) ?></li>
 81 |         <?js }); ?></ul>
 82 |     <?js } ?>
 83 | 
 84 |     <?js
 85 |         var classes = self.find({kind: 'class', memberof: doc.longname});
 86 |         if (!isGlobalPage && classes && classes.length) {
 87 |     ?>
 88 |         <h3 class="subsection-title">Classes</h3>
 89 | 
 90 |         <dl><?js classes.forEach(function(c) { ?>
 91 |             <dt><?js= self.linkto(c.longname, c.name) ?></dt>
 92 |             <dd><?js if (c.summary) { ?><?js= c.summary ?><?js } ?></dd>
 93 |         <?js }); ?></dl>
 94 |     <?js } ?>
 95 | 
 96 |     <?js
 97 |         var interfaces = self.find({kind: 'interface', memberof: doc.longname});
 98 |         if (!isGlobalPage && interfaces && interfaces.length) {
 99 |     ?>
100 |         <h3 class="subsection-title">Interfaces</h3>
101 | 
102 |         <dl><?js interfaces.forEach(function(i) { ?>
103 |             <dt><?js= self.linkto(i.longname, i.name) ?></dt>
104 |             <dd><?js if (i.summary) { ?><?js= i.summary ?><?js } ?></dd>
105 |         <?js }); ?></dl>
106 |     <?js } ?>
107 | 
108 |     <?js
109 |         var mixins = self.find({kind: 'mixin', memberof: doc.longname});
110 |         if (!isGlobalPage && mixins && mixins.length) {
111 |     ?>
112 |         <h3 class="subsection-title">Mixins</h3>
113 | 
114 |         <dl><?js mixins.forEach(function(m) { ?>
115 |             <dt><?js= self.linkto(m.longname, m.name) ?></dt>
116 |             <dd><?js if (m.summary) { ?><?js= m.summary ?><?js } ?></dd>
117 |         <?js }); ?></dl>
118 |     <?js } ?>
119 | 
120 |     <?js
121 |         var namespaces = self.find({kind: 'namespace', memberof: doc.longname});
122 |         if (!isGlobalPage && namespaces && namespaces.length) {
123 |     ?>
124 |         <h3 class="subsection-title">Namespaces</h3>
125 | 
126 |         <dl><?js namespaces.forEach(function(n) { ?>
127 |             <dt><?js= self.linkto(n.longname, n.name) ?></dt>
128 |             <dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd>
129 |         <?js }); ?></dl>
130 |     <?js } ?>
131 | 
132 |     <?js
133 |         var members = self.find({kind: 'member', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
134 | 
135 |         // symbols that are assigned to module.exports are not globals, even though they're not a memberof anything
136 |         if (isGlobalPage && members && members.length && members.forEach) {
137 |             members = members.filter(function(m) {
138 |                 return m.longname && m.longname.indexOf('module:') !== 0;
139 |             });
140 |         }
141 |         if (members && members.length && members.forEach) {
142 |     ?>
143 |         <h3 class="subsection-title">Members</h3>
144 | 
145 |         <?js members.forEach(function(p) { ?>
146 |             <?js= self.partial('members.tmpl', p) ?>
147 |         <?js }); ?>
148 |     <?js } ?>
149 | 
150 |     <?js
151 |         var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
152 |         if (methods && methods.length && methods.forEach) {
153 |     ?>
154 |         <h3 class="subsection-title">Methods</h3>
155 | 
156 |         <?js methods.forEach(function(m) { ?>
157 |             <?js= self.partial('method.tmpl', m) ?>
158 |         <?js }); ?>
159 |     <?js } ?>
160 | 
161 |     <?js
162 |         var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
163 |         if (typedefs && typedefs.length && typedefs.forEach) {
164 |     ?>
165 |         <h3 class="subsection-title">Type Definitions</h3>
166 | 
167 |         <?js typedefs.forEach(function(e) {
168 |                 if (e.signature) {
169 |             ?>
170 |                 <?js= self.partial('method.tmpl', e) ?>
171 |             <?js
172 |                 }
173 |                 else {
174 |             ?>
175 |                 <?js= self.partial('members.tmpl', e) ?>
176 |             <?js
177 |                 }
178 |             }); ?>
179 |     <?js } ?>
180 | 
181 |     <?js
182 |         var events = self.find({kind: 'event', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
183 |         if (events && events.length && events.forEach) {
184 |     ?>
185 |         <h3 class="subsection-title">Events</h3>
186 | 
187 |         <?js events.forEach(function(e) { ?>
188 |             <?js= self.partial('method.tmpl', e) ?>
189 |         <?js }); ?>
190 |     <?js } ?>
191 | </article>
192 | 
193 | </section>
194 | <?js } ?>
195 | 
196 | <?js }); ?>
197 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/details.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 | var data = obj;
  3 | var self = this;
  4 | var defaultObjectClass = '';
  5 | 
  6 | // Check if the default value is an object or array; if so, apply code highlighting
  7 | if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) {
  8 |     data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
  9 |     defaultObjectClass = ' class="object-value"';
 10 | }
 11 | ?>
 12 | <?js
 13 |     var properties = data.properties;
 14 |     if (properties && properties.length && properties.forEach && !data.hideconstructor) {
 15 | ?>
 16 | 
 17 |     <h5 class="subsection-title">Properties:</h5>
 18 | 
 19 |     <?js= this.partial('properties.tmpl', data) ?>
 20 | 
 21 | <?js } ?>
 22 | 
 23 | <dl class="details">
 24 | 
 25 |     <?js if (data.version) {?>
 26 |     <dt class="tag-version">Version:</dt>
 27 |     <dd class="tag-version"><ul class="dummy"><li><?js= version ?></li></ul></dd>
 28 |     <?js } ?>
 29 | 
 30 |     <?js if (data.since) {?>
 31 |     <dt class="tag-since">Since:</dt>
 32 |     <dd class="tag-since"><ul class="dummy"><li><?js= since ?></li></ul></dd>
 33 |     <?js } ?>
 34 | 
 35 |     <?js if (data.inherited && data.inherits && !data.overrides) { ?>
 36 |     <dt class="inherited-from">Inherited From:</dt>
 37 |     <dd class="inherited-from"><ul class="dummy"><li>
 38 |         <?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
 39 |     </li></ul></dd>
 40 |     <?js } ?>
 41 | 
 42 |     <?js if (data.overrides) { ?>
 43 |     <dt class="tag-overrides">Overrides:</dt>
 44 |     <dd class="tag-overrides"><ul class="dummy"><li>
 45 |         <?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?>
 46 |     </li></ul></dd>
 47 |     <?js } ?>
 48 | 
 49 |     <?js if (data.implementations && data.implementations.length) { ?>
 50 |     <dt class="implementations">Implementations:</dt>
 51 |     <dd class="implementations"><ul>
 52 |         <?js data.implementations.forEach(function(impl) { ?>
 53 |             <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
 54 |         <?js }); ?>
 55 |     </ul></dd>
 56 |     <?js } ?>
 57 | 
 58 |     <?js if (data.implements && data.implements.length) { ?>
 59 |     <dt class="implements">Implements:</dt>
 60 |     <dd class="implements"><ul>
 61 |         <?js data.implements.forEach(function(impl) { ?>
 62 |             <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
 63 |         <?js }); ?>
 64 |     </ul></dd>
 65 |     <?js } ?>
 66 | 
 67 |     <?js if (data.mixes && data.mixes.length) { ?>
 68 |         <dt class="mixes">Mixes In:</dt>
 69 | 
 70 |         <dd class="mixes"><ul>
 71 |         <?js data.mixes.forEach(function(a) { ?>
 72 |             <li><?js= self.linkto(a, a) ?></li>
 73 |         <?js }); ?>
 74 |         </ul></dd>
 75 |     <?js } ?>
 76 | 
 77 |     <?js if (data.deprecated) { ?>
 78 |         <dt class="important tag-deprecated">Deprecated:</dt><?js
 79 |             if (data.deprecated === true) { ?><dd class="yes-def tag-deprecated"><ul class="dummy"><li>Yes</li></ul></dd><?js }
 80 |             else { ?><dd><ul class="dummy"><li><?js= data.deprecated ?></li></ul></dd><?js }
 81 |         ?>
 82 |     <?js } ?>
 83 | 
 84 |     <?js if (data.author && author.length) {?>
 85 |     <dt class="tag-author">Author:</dt>
 86 |     <dd class="tag-author">
 87 |         <ul><?js author.forEach(function(a) { ?>
 88 |             <li><?js= self.resolveAuthorLinks(a) ?></li>
 89 |         <?js }); ?></ul>
 90 |     </dd>
 91 |     <?js } ?>
 92 | 
 93 |     <?js if (data.copyright) {?>
 94 |     <dt class="tag-copyright">Copyright:</dt>
 95 |     <dd class="tag-copyright"><ul class="dummy"><li><?js= copyright ?></li></ul></dd>
 96 |     <?js } ?>
 97 | 
 98 |     <?js if (data.license) {?>
 99 |     <dt class="tag-license">License:</dt>
100 |     <dd class="tag-license"><ul class="dummy"><li><?js= license ?></li></ul></dd>
101 |     <?js } ?>
102 | 
103 |     <?js if (data.defaultvalue) {?>
104 |     <dt class="tag-default">Default Value:</dt>
105 |     <dd class="tag-default"><ul class="dummy">
106 |             <li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
107 |         </ul></dd>
108 |     <?js } ?>
109 | 
110 |     <?js if (data.meta && self.outputSourceFiles) {?>
111 |     <dt class="tag-source">Source:</dt>
112 |     <dd class="tag-source"><ul class="dummy"><li>
113 |         <?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
114 |     </li></ul></dd>
115 |     <?js } ?>
116 | 
117 |     <?js if (data.tutorials && tutorials.length) {?>
118 |     <dt class="tag-tutorial">Tutorials:</dt>
119 |     <dd class="tag-tutorial">
120 |         <ul><?js tutorials.forEach(function(t) { ?>
121 |             <li><?js= self.tutoriallink(t) ?></li>
122 |         <?js }); ?></ul>
123 |     </dd>
124 |     <?js } ?>
125 | 
126 |     <?js if (data.see && see.length) {?>
127 |     <dt class="tag-see">See:</dt>
128 |     <dd class="tag-see">
129 |         <ul><?js see.forEach(function(s) { ?>
130 |             <li><?js= self.linkto(s) ?></li>
131 |         <?js }); ?></ul>
132 |     </dd>
133 |     <?js } ?>
134 | 
135 |     <?js if (data.todo && todo.length) {?>
136 |     <dt class="tag-todo">To Do:</dt>
137 |     <dd class="tag-todo">
138 |         <ul><?js todo.forEach(function(t) { ?>
139 |             <li><?js= t ?></li>
140 |         <?js }); ?></ul>
141 |     </dd>
142 |     <?js } ?>
143 | </dl>
144 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/example.tmpl:
--------------------------------------------------------------------------------
1 | <?js var data = obj; ?>
2 | <pre><code><?js= data ?></code></pre>
3 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/examples.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 |     var data = obj;
 3 |     var self = this;
 4 | 
 5 |     data.forEach(function(example) {
 6 |         if (example.caption) {
 7 |     ?>
 8 |         <p class="code-caption"><?js= example.caption ?></p>
 9 |     <?js } ?>
10 |     <pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre>
11 | <?js
12 |     });
13 | ?>


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/exceptions.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 |     var data = obj;
 3 | ?>
 4 | <?js if (data.description && data.type && data.type.names) { ?>
 5 | <dl>
 6 |     <dt>
 7 |         <div class="param-desc">
 8 |         <?js= data.description ?>
 9 |         </div>
10 |     </dt>
11 |     <dd></dd>
12 |     <dt>
13 |         <dl>
14 |             <dt>
15 |                 Type
16 |             </dt>
17 |             <dd>
18 |                 <?js= this.partial('type.tmpl', data.type.names) ?>
19 |             </dd>
20 |         </dl>
21 |     </dt>
22 |     <dd></dd>
23 | </dl>
24 | <?js } else { ?>
25 |     <div class="param-desc">
26 |     <?js if (data.description) { ?>
27 |         <?js= data.description ?>
28 |     <?js } else if (data.type && data.type.names) { ?>
29 |         <?js= this.partial('type.tmpl', data.type.names) ?>
30 |     <?js } ?>
31 |     </div>
32 | <?js } ?>
33 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/layout.tmpl:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |     <meta charset="utf-8">
 5 |     <title>JSDoc: <?js= title ?></title>
 6 | 
 7 |     <script src="scripts/prettify/prettify.js"> </script>
 8 |     <script src="scripts/prettify/lang-css.js"> </script>
 9 |     <!--[if lt IE 9]>
10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 |     <![endif]-->
12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14 | </head>
15 | 
16 | <body>
17 | 
18 | <div id="main">
19 | 
20 |     <h1 class="page-title"><?js= title ?></h1>
21 | 
22 |     <?js= content ?>
23 | </div>
24 | 
25 | <nav>
26 |     <?js= this.nav ?>
27 | </nav>
28 | 
29 | <br class="clear">
30 | 
31 | <footer>
32 |     Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc <?js= env.version.number ?></a><?js if(env.conf.templates && env.conf.templates.default && env.conf.templates.default.includeDate !== false) { ?> on <?js= (new Date()) ?><?js } ?>
33 | </footer>
34 | 
35 | <script> prettyPrint(); </script>
36 | <script src="scripts/linenumber.js"> </script>
37 | </body>
38 | </html>
39 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/mainpage.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj;
 3 | var self = this;
 4 | ?>
 5 | 
 6 | <?js if (data.kind === 'package') { ?>
 7 |     <h3><?js= data.name ?> <?js= data.version ?></h3>
 8 | <?js } ?>
 9 | 
10 | <?js if (data.readme) { ?>
11 |     <section>
12 |         <article><?js= data.readme ?></article>
13 |     </section>
14 | <?js } ?>
15 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/members.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj;
 3 | var self = this;
 4 | ?>
 5 | <h4 class="name" id="<?js= id ?>"><?js= data.attribs + name + (data.signature ? data.signature : '') ?></h4>
 6 | 
 7 | <?js if (data.summary) { ?>
 8 | <p class="summary"><?js= summary ?></p>
 9 | <?js } ?>
10 | 
11 | <?js if (data.description) { ?>
12 | <div class="description">
13 |     <?js= data.description ?>
14 | </div>
15 | <?js } ?>
16 | 
17 | <?js if (data.type && data.type.names) {?>
18 |     <h5>Type:</h5>
19 |     <ul>
20 |         <li>
21 |             <?js= self.partial('type.tmpl', data.type.names) ?>
22 |         </li>
23 |     </ul>
24 | <?js } ?>
25 | 
26 | <?js= this.partial('details.tmpl', data) ?>
27 | 
28 | <?js if (data.fires && fires.length) { ?>
29 |     <h5>Fires:</h5>
30 |     <ul><?js fires.forEach(function(f) { ?>
31 |         <li><?js= self.linkto(f) ?></li>
32 |     <?js }); ?></ul>
33 | <?js } ?>
34 | 
35 | <?js if (data.examples && examples.length) { ?>
36 |     <h5>Example<?js= examples.length > 1? 's':'' ?></h5>
37 |     <?js= this.partial('examples.tmpl', examples) ?>
38 | <?js } ?>
39 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/method.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 | var data = obj;
  3 | var self = this;
  4 | ?>
  5 | <?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
  6 |     <?js if (data.kind === 'class' && data.classdesc) { ?>
  7 |     <h2>Constructor</h2>
  8 |     <?js } ?>
  9 | 
 10 |     <?js if (data.kind !== 'namespace') { ?>
 11 |     <h4 class="name" id="<?js= id ?>"><?js= data.attribs + (kind === 'class' ? 'new ' : '') +
 12 |     name + (data.signature || '') ?></h4>
 13 |     <?js } ?>
 14 | 
 15 |     <?js if (data.summary) { ?>
 16 |     <p class="summary"><?js= summary ?></p>
 17 |     <?js } ?>
 18 | <?js } ?>
 19 | 
 20 | <?js if (data.kind !== 'module' && data.description && !data.hideconstructor) { ?>
 21 | <div class="description">
 22 |     <?js= data.description ?>
 23 | </div>
 24 | <?js } ?>
 25 | 
 26 | <?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
 27 |     <h5>Extends:</h5>
 28 |     <?js= self.partial('augments.tmpl', data) ?>
 29 | <?js } ?>
 30 | 
 31 | <?js if (kind === 'event' && data.type && data.type.names) {?>
 32 |     <h5>Type:</h5>
 33 |     <ul>
 34 |         <li>
 35 |             <?js= self.partial('type.tmpl', data.type.names) ?>
 36 |         </li>
 37 |     </ul>
 38 | <?js } ?>
 39 | 
 40 | <?js if (data['this']) { ?>
 41 |     <h5>This:</h5>
 42 |     <ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
 43 | <?js } ?>
 44 | 
 45 | <?js if (data.params && params.length && !data.hideconstructor) { ?>
 46 |     <h5>Parameters:</h5>
 47 |     <?js= this.partial('params.tmpl', params) ?>
 48 | <?js } ?>
 49 | 
 50 | <?js= this.partial('details.tmpl', data) ?>
 51 | 
 52 | <?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
 53 | <h5>Requires:</h5>
 54 | <ul><?js data.requires.forEach(function(r) { ?>
 55 |     <li><?js= self.linkto(r) ?></li>
 56 | <?js }); ?></ul>
 57 | <?js } ?>
 58 | 
 59 | <?js if (data.fires && fires.length) { ?>
 60 | <h5>Fires:</h5>
 61 | <ul><?js fires.forEach(function(f) { ?>
 62 |     <li><?js= self.linkto(f) ?></li>
 63 | <?js }); ?></ul>
 64 | <?js } ?>
 65 | 
 66 | <?js if (data.listens && listens.length) { ?>
 67 | <h5>Listens to Events:</h5>
 68 | <ul><?js listens.forEach(function(f) { ?>
 69 |     <li><?js= self.linkto(f) ?></li>
 70 | <?js }); ?></ul>
 71 | <?js } ?>
 72 | 
 73 | <?js if (data.listeners && listeners.length) { ?>
 74 | <h5>Listeners of This Event:</h5>
 75 | <ul><?js listeners.forEach(function(f) { ?>
 76 |     <li><?js= self.linkto(f) ?></li>
 77 | <?js }); ?></ul>
 78 | <?js } ?>
 79 | 
 80 | <?js if (data.modifies && modifies.length) {?>
 81 | <h5>Modifies:</h5>
 82 | <?js if (modifies.length > 1) { ?><ul><?js
 83 |     modifies.forEach(function(m) { ?>
 84 |         <li><?js= self.partial('modifies.tmpl', m) ?></li>
 85 |     <?js });
 86 | ?></ul><?js } else {
 87 |     modifies.forEach(function(m) { ?>
 88 |         <?js= self.partial('modifies.tmpl', m) ?>
 89 |     <?js });
 90 | } } ?>
 91 | 
 92 | <?js if (data.exceptions && exceptions.length) { ?>
 93 | <h5>Throws:</h5>
 94 | <?js if (exceptions.length > 1) { ?><ul><?js
 95 |     exceptions.forEach(function(r) { ?>
 96 |         <li><?js= self.partial('exceptions.tmpl', r) ?></li>
 97 |     <?js });
 98 | ?></ul><?js } else {
 99 |     exceptions.forEach(function(r) { ?>
100 |         <?js= self.partial('exceptions.tmpl', r) ?>
101 |     <?js });
102 | } } ?>
103 | 
104 | <?js if (data.returns && returns.length) { ?>
105 | <h5>Returns:</h5>
106 | <?js if (returns.length > 1) { ?><ul><?js
107 |     returns.forEach(function(r) { ?>
108 |         <li><?js= self.partial('returns.tmpl', r) ?></li>
109 |     <?js });
110 | ?></ul><?js } else {
111 |     returns.forEach(function(r) { ?>
112 |         <?js= self.partial('returns.tmpl', r) ?>
113 |     <?js });
114 | } } ?>
115 | 
116 | <?js if (data.yields && yields.length) { ?>
117 | <h5>Yields:</h5>
118 | <?js if (yields.length > 1) { ?><ul><?js
119 |     yields.forEach(function(r) { ?>
120 |         <li><?js= self.partial('returns.tmpl', r) ?></li>
121 |     <?js });
122 | ?></ul><?js } else {
123 |     yields.forEach(function(r) { ?>
124 |         <?js= self.partial('returns.tmpl', r) ?>
125 |     <?js });
126 | } } ?>
127 | 
128 | <?js if (data.examples && examples.length) { ?>
129 |     <h5>Example<?js= examples.length > 1? 's':'' ?></h5>
130 |     <?js= this.partial('examples.tmpl', examples) ?>
131 | <?js } ?>
132 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/modifies.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj || {};
 3 | ?>
 4 | 
 5 | <?js if (data.type && data.type.names) {?>
 6 | <dl>
 7 |     <dt>
 8 |         Type
 9 |     </dt>
10 |     <dd>
11 |         <?js= this.partial('type.tmpl', data.type.names) ?>
12 |     </dd>
13 | </dl>
14 | <?js } ?>
15 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/params.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var params = obj;
  3 | 
  4 |     /* sort subparams under their parent params (like opts.classname) */
  5 |     var parentParam = null;
  6 |     params.forEach(function(param, i) {
  7 |         var paramRegExp;
  8 | 
  9 |         if (!param) {
 10 |             return;
 11 |         }
 12 | 
 13 |         if (parentParam && parentParam.name && param.name) {
 14 |             try {
 15 |                 paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)
#39;);
 16 |             }
 17 |             catch (e) {
 18 |                 // there's probably a typo in the JSDoc comment that resulted in a weird
 19 |                 // parameter name
 20 |                 return;
 21 |             }
 22 | 
 23 |             if ( paramRegExp.test(param.name) ) {
 24 |                 param.name = RegExp.$1;
 25 |                 parentParam.subparams = parentParam.subparams || [];
 26 |                 parentParam.subparams.push(param);
 27 |                 params[i] = null;
 28 |             }
 29 |             else {
 30 |                 parentParam = param;
 31 |             }
 32 |         }
 33 |         else {
 34 |             parentParam = param;
 35 |         }
 36 |     });
 37 | 
 38 |     /* determine if we need extra columns, "attributes" and "default" */
 39 |     params.hasAttributes = false;
 40 |     params.hasDefault = false;
 41 |     params.hasName = false;
 42 | 
 43 |     params.forEach(function(param) {
 44 |         if (!param) { return; }
 45 | 
 46 |         if (param.optional || param.nullable || param.variable) {
 47 |             params.hasAttributes = true;
 48 |         }
 49 | 
 50 |         if (param.name) {
 51 |             params.hasName = true;
 52 |         }
 53 | 
 54 |         if (typeof param.defaultvalue !== 'undefined') {
 55 |             params.hasDefault = true;
 56 |         }
 57 |     });
 58 | ?>
 59 | 
 60 | <table class="params">
 61 |     <thead>
 62 |     <tr>
 63 |         <?js if (params.hasName) {?>
 64 |         <th>Name</th>
 65 |         <?js } ?>
 66 | 
 67 |         <th>Type</th>
 68 | 
 69 |         <?js if (params.hasAttributes) {?>
 70 |         <th>Attributes</th>
 71 |         <?js } ?>
 72 | 
 73 |         <?js if (params.hasDefault) {?>
 74 |         <th>Default</th>
 75 |         <?js } ?>
 76 | 
 77 |         <th class="last">Description</th>
 78 |     </tr>
 79 |     </thead>
 80 | 
 81 |     <tbody>
 82 |     <?js
 83 |         var self = this;
 84 |         params.forEach(function(param) {
 85 |             if (!param) { return; }
 86 |     ?>
 87 | 
 88 |         <tr>
 89 |             <?js if (params.hasName) {?>
 90 |                 <td class="name"><code><?js= param.name ?></code></td>
 91 |             <?js } ?>
 92 | 
 93 |             <td class="type">
 94 |             <?js if (param.type && param.type.names) {?>
 95 |                 <?js= self.partial('type.tmpl', param.type.names) ?>
 96 |             <?js } ?>
 97 |             </td>
 98 | 
 99 |             <?js if (params.hasAttributes) {?>
100 |                 <td class="attributes">
101 |                 <?js if (param.optional) { ?>
102 |                     &lt;optional><br>
103 |                 <?js } ?>
104 | 
105 |                 <?js if (param.nullable) { ?>
106 |                     &lt;nullable><br>
107 |                 <?js } ?>
108 | 
109 |                 <?js if (param.variable) { ?>
110 |                     &lt;repeatable><br>
111 |                 <?js } ?>
112 |                 </td>
113 |             <?js } ?>
114 | 
115 |             <?js if (params.hasDefault) {?>
116 |                 <td class="default">
117 |                 <?js if (typeof param.defaultvalue !== 'undefined') { ?>
118 |                     <?js= self.htmlsafe(param.defaultvalue) ?>
119 |                 <?js } ?>
120 |                 </td>
121 |             <?js } ?>
122 | 
123 |             <td class="description last"><?js= param.description ?><?js if (param.subparams) { ?>
124 |                 <h6>Properties</h6>
125 |                 <?js= self.partial('params.tmpl', param.subparams) ?>
126 |             <?js } ?></td>
127 |         </tr>
128 | 
129 |     <?js }); ?>
130 |     </tbody>
131 | </table>
132 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/properties.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var data = obj;
  3 |     var props = data.subprops || data.properties;
  4 | 
  5 |     /* sort subprops under their parent props (like opts.classname) */
  6 |     var parentProp = null;
  7 |     props.forEach(function(prop, i) {
  8 |         if (!prop) { return; }
  9 |         if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
 10 |             prop.name = prop.name.substring(parentProp.name.length + 1);
 11 |             parentProp.subprops = parentProp.subprops || [];
 12 |             parentProp.subprops.push(prop);
 13 |             props[i] = null;
 14 |         }
 15 |         else {
 16 |             parentProp = prop;
 17 |         }
 18 |     });
 19 | 
 20 |     /* determine if we need extra columns, "attributes" and "default" */
 21 |     props.hasAttributes = false;
 22 |     props.hasDefault = false;
 23 |     props.hasName = false;
 24 | 
 25 |     props.forEach(function(prop) {
 26 |         if (!prop) { return; }
 27 | 
 28 |         if (prop.optional || prop.nullable) {
 29 |             props.hasAttributes = true;
 30 |         }
 31 | 
 32 |         if (prop.name) {
 33 |             props.hasName = true;
 34 |         }
 35 | 
 36 |         if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
 37 |             props.hasDefault = true;
 38 |         }
 39 |     });
 40 | ?>
 41 | 
 42 | <table class="props">
 43 |     <thead>
 44 |     <tr>
 45 |         <?js if (props.hasName) {?>
 46 |         <th>Name</th>
 47 |         <?js } ?>
 48 | 
 49 |         <th>Type</th>
 50 | 
 51 |         <?js if (props.hasAttributes) {?>
 52 |         <th>Attributes</th>
 53 |         <?js } ?>
 54 | 
 55 |         <?js if (props.hasDefault) {?>
 56 |         <th>Default</th>
 57 |         <?js } ?>
 58 | 
 59 |         <th class="last">Description</th>
 60 |     </tr>
 61 |     </thead>
 62 | 
 63 |     <tbody>
 64 |     <?js
 65 |         var self = this;
 66 |         props.forEach(function(prop) {
 67 |             if (!prop) { return; }
 68 |     ?>
 69 | 
 70 |         <tr>
 71 |             <?js if (props.hasName) {?>
 72 |                 <td class="name"><code><?js= prop.name ?></code></td>
 73 |             <?js } ?>
 74 | 
 75 |             <td class="type">
 76 |             <?js if (prop.type && prop.type.names) {?>
 77 |                 <?js= self.partial('type.tmpl', prop.type.names) ?>
 78 |             <?js } ?>
 79 |             </td>
 80 | 
 81 |             <?js if (props.hasAttributes) {?>
 82 |                 <td class="attributes">
 83 |                 <?js if (prop.optional) { ?>
 84 |                     &lt;optional><br>
 85 |                 <?js } ?>
 86 | 
 87 |                 <?js if (prop.nullable) { ?>
 88 |                     &lt;nullable><br>
 89 |                 <?js } ?>
 90 |                 </td>
 91 |             <?js } ?>
 92 | 
 93 |             <?js if (props.hasDefault) {?>
 94 |                 <td class="default">
 95 |                 <?js if (typeof prop.defaultvalue !== 'undefined') { ?>
 96 |                     <?js= self.htmlsafe(prop.defaultvalue) ?>
 97 |                 <?js } ?>
 98 |                 </td>
 99 |             <?js } ?>
100 | 
101 |             <td class="description last"><?js= prop.description ?><?js if (prop.subprops) { ?>
102 |                 <h6>Properties</h6><?js= self.partial('properties.tmpl', prop) ?>
103 |             <?js } ?></td>
104 |         </tr>
105 | 
106 |     <?js }); ?>
107 |     </tbody>
108 | </table>
109 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/returns.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj || {};
 3 | if (data.description) {
 4 | ?>
 5 | <div class="param-desc">
 6 |     <?js= description ?>
 7 | </div>
 8 | <?js } ?>
 9 | 
10 | <?js if (data.type && data.type.names) {?>
11 | <dl>
12 |     <dt>
13 |         Type
14 |     </dt>
15 |     <dd>
16 |         <?js= this.partial('type.tmpl', data.type.names) ?>
17 |     </dd>
18 | </dl>
19 | <?js } ?>


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/source.tmpl:
--------------------------------------------------------------------------------
1 | <?js
2 |     var data = obj;
3 | ?>
4 |     <section>
5 |         <article>
6 |             <pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre>
7 |         </article>
8 |     </section>


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/tutorial.tmpl:
--------------------------------------------------------------------------------
 1 | <section>
 2 | 
 3 | <header>
 4 |     <?js if (children.length > 0) { ?>
 5 |     <ul><?js
 6 |         var self = this;
 7 |         children.forEach(function(t) { ?>
 8 |         <li><?js= self.tutoriallink(t.name) ?></li>
 9 |     <?js }); ?></ul>
10 |     <?js } ?>
11 | 
12 |     <h2><?js= header ?></h2>
13 | </header>
14 | 
15 | <article>
16 |     <?js= content ?>
17 | </article>
18 | 
19 | </section>
20 | 


--------------------------------------------------------------------------------
/jsdoc/templates/custom/tmpl/type.tmpl:
--------------------------------------------------------------------------------
1 | <?js
2 |     var data = obj;
3 |     var self = this;
4 |     data.forEach(function(name, i) { ?>
5 | <span class="param-type"><?js= self.linkto(name, self.htmlsafe(name)) ?></span>
6 | <?js if (i < data.length-1) { ?>|<?js } ?>
7 | <?js }); ?>


--------------------------------------------------------------------------------
/lib/assert.js:
--------------------------------------------------------------------------------
 1 | const {assertOptions} = require('assert-options');
 2 | 
 3 | // this to allow override options-related errors globally (for pg-promise)
 4 | global.pgPromiseAssert = assertOptions;
 5 | 
 6 | module.exports = {
 7 |     assert() {
 8 |         return global.pgPromiseAssert.apply(null, [...arguments]);
 9 |     }
10 | };
11 | 


--------------------------------------------------------------------------------
/lib/connect.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {Events} = require('./events');
 11 | const {ColorConsole} = require('./utils/color');
 12 | 
 13 | const npm = {
 14 |     utils: require('./utils'),
 15 |     text: require('./text'),
 16 |     formatting: require('./formatting')
 17 | };
 18 | 
 19 | function poolConnect(ctx, db, config) {
 20 |     return config.promise((resolve, reject) => {
 21 |         const p = db.$pool;
 22 |         if (p.ending) {
 23 |             db.$destroy();
 24 |             const err = new Error(npm.text.poolDestroyed);
 25 |             Events.error(ctx.options, err, {
 26 |                 dc: ctx.dc
 27 |             });
 28 |             reject(err);
 29 |             return;
 30 |         }
 31 |         p.connect((err, client) => {
 32 |             if (err) {
 33 |                 Events.error(ctx.options, err, {
 34 |                     cn: npm.utils.getSafeConnection(ctx.cn),
 35 |                     dc: ctx.dc
 36 |                 });
 37 |                 reject(err);
 38 |             } else {
 39 |                 if ('$useCount' in client) {
 40 |                     // Make sure useCount drops to 1, if it ever reaches maximum integer number;
 41 |                     // We do not drop it to zero, to avoid rerun of initialization queries that
 42 |                     // usually check for useCount === 0;
 43 |                     // istanbul ignore if
 44 |                     if (client.$useCount >= Number.MAX_SAFE_INTEGER) {
 45 |                         client.$useCount = 1; // resetting; cannot auto-test this
 46 |                     } else {
 47 |                         client.$useCount = ++client.$useCount;
 48 |                     }
 49 |                 } else {
 50 |                     Object.defineProperty(client, '$useCount', {
 51 |                         value: 0,
 52 |                         configurable: false,
 53 |                         enumerable: false,
 54 |                         writable: true
 55 |                     });
 56 |                     setSchema(client, ctx);
 57 |                 }
 58 |                 setCtx(client, ctx);
 59 |                 const end = lockClientEnd(client);
 60 |                 client.on('error', onError);
 61 |                 resolve({
 62 |                     client,
 63 |                     useCount: client.$useCount,
 64 |                     release(kill) {
 65 |                         client.end = end;
 66 |                         client.release(kill || client.$connectionError);
 67 |                         Events.disconnect(ctx, client);
 68 |                         client.removeListener('error', onError);
 69 |                     }
 70 |                 });
 71 |                 Events.connect(ctx, client, client.$useCount);
 72 |             }
 73 |         });
 74 |     });
 75 | }
 76 | 
 77 | function directConnect(ctx, config) {
 78 |     return config.promise((resolve, reject) => {
 79 |         const client = new config.pgp.pg.Client(ctx.cn);
 80 |         client.connect(err => {
 81 |             if (err) {
 82 |                 Events.error(ctx.options, err, {
 83 |                     cn: npm.utils.getSafeConnection(ctx.cn),
 84 |                     dc: ctx.dc
 85 |                 });
 86 |                 reject(err);
 87 |             } else {
 88 |                 setSchema(client, ctx);
 89 |                 setCtx(client, ctx);
 90 |                 const end = lockClientEnd(client);
 91 |                 client.on('error', onError);
 92 |                 resolve({
 93 |                     client,
 94 |                     useCount: 0,
 95 |                     release() {
 96 |                         client.end = end;
 97 |                         const p = config.promise((res, rej) => client.end().then(res).catch(rej));
 98 |                         Events.disconnect(ctx, client);
 99 |                         client.removeListener('error', onError);
100 |                         return p;
101 |                     }
102 |                 });
103 |                 Events.connect(ctx, client, 0);
104 |             }
105 |         });
106 |     });
107 | }
108 | 
109 | // this event only happens when the connection is lost physically,
110 | // which cannot be tested automatically; removing from coverage:
111 | // istanbul ignore next
112 | function onError(err) {
113 |     const ctx = this.$ctx;
114 |     const cn = npm.utils.getSafeConnection(ctx.cn);
115 |     Events.error(ctx.options, err, {cn, dc: ctx.dc});
116 |     if (ctx.cnOptions && typeof ctx.cnOptions.onLost === 'function' && !ctx.notified) {
117 |         try {
118 |             ctx.cnOptions.onLost.call(this, err, {
119 |                 cn,
120 |                 dc: ctx.dc,
121 |                 start: ctx.start,
122 |                 client: this
123 |             });
124 |         } catch (e) {
125 |             ColorConsole.error(e && e.stack || e);
126 |         }
127 |         ctx.notified = true;
128 |     }
129 | }
130 | 
131 | function lockClientEnd(client) {
132 |     const end = client.end;
133 |     client.end = doNotCall => {
134 |         // This call can happen only in the following two cases:
135 |         // 1. the client made the call directly, against the library's documentation (invalid code)
136 |         // 2. connection with the server broke, and the pool is terminating all clients forcefully.
137 |         ColorConsole.error(`${npm.text.clientEnd}\n${npm.utils.getLocalStack(1, 3)}\n`);
138 |         if (!doNotCall) {
139 |             end.call(client);
140 |         }
141 |     };
142 |     return end;
143 | }
144 | 
145 | function setCtx(client, ctx) {
146 |     Object.defineProperty(client, '$ctx', {
147 |         value: ctx,
148 |         writable: true
149 |     });
150 | }
151 | 
152 | function setSchema(client, ctx) {
153 |     let s = ctx.options.schema;
154 |     if (!s) {
155 |         return;
156 |     }
157 |     if (typeof s === 'function') {
158 |         s = s.call(ctx.dc, ctx.dc);
159 |     }
160 |     if (Array.isArray(s)) {
161 |         s = s.filter(a => a && typeof a === 'string');
162 |     }
163 |     if (typeof s === 'string' || (Array.isArray(s) && s.length)) {
164 |         client.query(npm.formatting.as.format('SET search_path TO $1:name', [s]), err => {
165 |             // istanbul ignore if;
166 |             if (err) {
167 |                 // This is unlikely to ever happen, unless the connection is created faulty,
168 |                 // and fails on the very first query, which is impossible to test automatically.
169 |                 throw err;
170 |             }
171 |         });
172 |     }
173 | }
174 | 
175 | module.exports = config => ({
176 |     pool: (ctx, db) => poolConnect(ctx, db, config),
177 |     direct: ctx => directConnect(ctx, config)
178 | });
179 | 


--------------------------------------------------------------------------------
/lib/context.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | /**
11 |  * @class ConnectionContext
12 |  * @private
13 |  * @summary Internal connection context.
14 |  *
15 |  * @param {object} cc
16 |  * Connection Context.
17 |  *
18 |  * @param {object} cc.cn
19 |  * Connection details
20 |  *
21 |  * @param {*} cc.dc
22 |  * Database Context
23 |  *
24 |  * @param {object} cc.options
25 |  * Library's Initialization Options
26 |  *
27 |  * @param {object} cc.db
28 |  * Database Session we're attached to, if any.
29 |  *
30 |  * @param {number} cc.level
31 |  * Task Level
32 |  *
33 |  * @param {number} cc.txLevel
34 |  * Transaction Level
35 |  *
36 |  * @param {object} cc.parentCtx
37 |  * Connection Context of the parent operation, if any.
38 |  *
39 |  */
40 | class ConnectionContext {
41 | 
42 |     constructor(cc) {
43 |         this.cn = cc.cn; // connection details;
44 |         this.dc = cc.dc; // database context;
45 |         this.options = cc.options; // library options;
46 |         this.db = cc.db; // database session;
47 |         this.level = cc.level; // task level;
48 |         this.txLevel = cc.txLevel; // transaction level;
49 |         this.parentCtx = null; // parent context
50 |         this.taskCtx = null; // task context
51 |         this.start = null; // Date/Time when connected
52 |         this.txCount = 0;
53 |     }
54 | 
55 |     connect(db) {
56 |         this.db = db;
57 |         this.start = new Date();
58 |     }
59 | 
60 |     disconnect(kill) {
61 |         if (this.db) {
62 |             const p = this.db.release(kill);
63 |             this.db = null;
64 |             return p;
65 |         }
66 |     }
67 | 
68 |     clone() {
69 |         const obj = new ConnectionContext(this);
70 |         obj.parent = this;
71 |         obj.parentCtx = this.taskCtx;
72 |         return obj;
73 |     }
74 | 
75 |     get nextTxCount() {
76 |         let txCurrent = this, txTop = this;
77 |         while (txCurrent.parent) {
78 |             txCurrent = txCurrent.parent;
79 |             if (txCurrent.taskCtx && txCurrent.taskCtx.isTX) {
80 |                 txTop = txCurrent;
81 |             }
82 |         }
83 |         return txTop.txCount++;
84 |     }
85 | }
86 | 
87 | /**
88 |  * Connection Context
89 |  * @module context
90 |  * @author Vitaly Tomilov
91 |  * @private
92 |  */
93 | module.exports = {ConnectionContext};
94 | 


--------------------------------------------------------------------------------
/lib/database-pool.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {ColorConsole} = require('./utils/color');
 11 | 
 12 | const npm = {
 13 |     utils: require('./utils')
 14 | };
 15 | 
 16 | /**
 17 |  * @class DatabasePool
 18 |  * @static
 19 |  * @private
 20 |  */
 21 | class DatabasePool {
 22 | 
 23 |     /**
 24 |      * Global instance of the database pool repository.
 25 |      *
 26 |      * @returns {{dbMap: {}, dbs: Array}}
 27 |      */
 28 |     static get instance() {
 29 |         const s = Symbol.for('pgPromiseDatabasePool');
 30 |         let scope = global[s];
 31 |         if (!scope) {
 32 |             scope = {
 33 |                 dbMap: {}, // map of used database context keys (connection + dc)
 34 |                 dbs: [] // all database objects
 35 |             };
 36 |             global[s] = scope;
 37 |         }
 38 |         return scope;
 39 |     }
 40 | 
 41 |     /**
 42 |      * @method DatabasePool.register
 43 |      * @static
 44 |      * @description
 45 |      *  - Registers each database object, to make sure no duplicates connections are used,
 46 |      *    and if they are, produce a warning;
 47 |      *  - Registers each Pool object, to be able to release them all when requested.
 48 |      *
 49 |      * @param {Database} db - The new Database object being registered.
 50 |      */
 51 |     static register(db) {
 52 |         const cnKey = DatabasePool.createContextKey(db);
 53 |         npm.utils.addReadProp(db, '$cnKey', cnKey, true);
 54 |         const {dbMap, dbs} = DatabasePool.instance;
 55 |         if (cnKey in dbMap) {
 56 |             dbMap[cnKey]++;
 57 |             /* istanbul ignore if */
 58 |             if (!db.$config.options.noWarnings) {
 59 |                 ColorConsole.warn(`WARNING: Creating a duplicate database object for the same connection.\n${npm.utils.getLocalStack(4, 3)}\n`);
 60 |             }
 61 |         } else {
 62 |             dbMap[cnKey] = 1;
 63 |         }
 64 |         dbs.push(db);
 65 |     }
 66 | 
 67 |     /**
 68 |      * @method DatabasePool.unregister
 69 |      * @static
 70 |      * @param db
 71 |      */
 72 |     static unregister(db) {
 73 |         const cnKey = db.$cnKey;
 74 |         const {dbMap} = DatabasePool.instance;
 75 |         if (!--dbMap[cnKey]) {
 76 |             delete dbMap[cnKey];
 77 |         }
 78 |     }
 79 | 
 80 |     /**
 81 |      * @method DatabasePool.shutDown
 82 |      * @static
 83 |      */
 84 |     static shutDown() {
 85 |         const {instance} = DatabasePool;
 86 |         instance.dbs.forEach(db => {
 87 |             db.$destroy();
 88 |         });
 89 |         instance.dbs.length = 0;
 90 |         instance.dbMap = {};
 91 |     }
 92 | 
 93 |     /**
 94 |      * @method DatabasePool.createContextKey
 95 |      * @static
 96 |      * @description
 97 |      * For connections that are objects it reorders the keys alphabetically,
 98 |      * and then serializes the result into a JSON string.
 99 |      *
100 |      * @param {Database} db - Database instance.
101 |      */
102 |     static createContextKey(db) {
103 |         let cn = db.$cn;
104 |         if (typeof cn === 'object') {
105 |             const obj = {}, keys = Object.keys(cn).sort();
106 |             keys.forEach(name => {
107 |                 obj[name] = cn[name];
108 |             });
109 |             cn = obj;
110 |         }
111 |         return npm.utils.toJson(npm.utils.getSafeConnection(cn)) + npm.utils.toJson(db.$dc);
112 |     }
113 | }
114 | 
115 | module.exports = {DatabasePool};
116 | 


--------------------------------------------------------------------------------
/lib/errors/README.md:
--------------------------------------------------------------------------------
 1 | ### `errors` namespace
 2 | 
 3 | This folder contains everything that's available via the [errors] namespace, before and after initialization:
 4 | 
 5 | ```js
 6 | const pgpLib = require('pg-promise');
 7 | const pgp = pgpLib(/*initialization options*/);
 8 | 
 9 | pgpLib.errors; // `errors` namespace
10 | pgp.errors; // `errors` namespace
11 | ```
12 | 
13 | [errors]:http://vitaly-t.github.io/pg-promise/errors.html 
14 | 


--------------------------------------------------------------------------------
/lib/errors/index.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {QueryResultError, queryResultErrorCode} = require('./query-result-error');
11 | const {PreparedStatementError} = require('./prepared-statement-error');
12 | const {ParameterizedQueryError} = require('./parameterized-query-error');
13 | const {QueryFileError} = require('./query-file-error');
14 | 
15 | /**
16 |  * @namespace errors
17 |  * @description
18 |  * Error types namespace, available as `pgp.errors`, before and after initializing the library.
19 |  *
20 |  * @property {function} PreparedStatementError
21 |  * {@link errors.PreparedStatementError PreparedStatementError} class constructor.
22 |  *
23 |  * Represents all errors that can be reported by class {@link PreparedStatement}.
24 |  *
25 |  * @property {function} ParameterizedQueryError
26 |  * {@link errors.ParameterizedQueryError ParameterizedQueryError} class constructor.
27 |  *
28 |  * Represents all errors that can be reported by class {@link ParameterizedQuery}.
29 |  *
30 |  * @property {function} QueryFileError
31 |  * {@link errors.QueryFileError QueryFileError} class constructor.
32 |  *
33 |  * Represents all errors that can be reported by class {@link QueryFile}.
34 |  *
35 |  * @property {function} QueryResultError
36 |  * {@link errors.QueryResultError QueryResultError} class constructor.
37 |  *
38 |  * Represents all result-specific errors from query methods.
39 |  *
40 |  * @property {errors.queryResultErrorCode} queryResultErrorCode
41 |  * Error codes `enum` used by class {@link errors.QueryResultError QueryResultError}.
42 |  *
43 |  */
44 | 
45 | module.exports = {
46 |     QueryResultError,
47 |     queryResultErrorCode,
48 |     PreparedStatementError,
49 |     ParameterizedQueryError,
50 |     QueryFileError
51 | };
52 | 


--------------------------------------------------------------------------------
/lib/errors/parameterized-query-error.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {QueryFileError} = require('./query-file-error');
11 | 
12 | const npm = {
13 |     os: require('os'),
14 |     utils: require('../utils')
15 | };
16 | 
17 | /**
18 |  * @class errors.ParameterizedQueryError
19 |  * @augments external:Error
20 |  * @description
21 |  * {@link errors.ParameterizedQueryError ParameterizedQueryError} class, available from the {@link errors} namespace.
22 |  *
23 |  * This type represents all errors that can be reported by class {@link ParameterizedQuery}, whether it is used
24 |  * explicitly or implicitly (via a simple `{text, values}` object).
25 |  *
26 |  * @property {string} name
27 |  * Standard {@link external:Error Error} property - error type name = `ParameterizedQueryError`.
28 |  *
29 |  * @property {string} message
30 |  * Standard {@link external:Error Error} property - the error message.
31 |  *
32 |  * @property {string} stack
33 |  * Standard {@link external:Error Error} property - the stack trace.
34 |  *
35 |  * @property {errors.QueryFileError} error
36 |  * Internal {@link errors.QueryFileError} object.
37 |  *
38 |  * It is set only when the source {@link ParameterizedQuery} used a {@link QueryFile} which threw the error.
39 |  *
40 |  * @property {object} result
41 |  * Resulting Parameterized Query object.
42 |  *
43 |  * @see ParameterizedQuery
44 |  */
45 | class ParameterizedQueryError extends Error {
46 |     constructor(error, pq) {
47 |         const isQueryFileError = error instanceof QueryFileError;
48 |         const message = isQueryFileError ? 'Failed to initialize \'text\' from a QueryFile.' : error;
49 |         super(message);
50 |         this.name = this.constructor.name;
51 |         if (isQueryFileError) {
52 |             this.error = error;
53 |         }
54 |         this.result = pq;
55 |         Error.captureStackTrace(this, this.constructor);
56 |     }
57 | }
58 | 
59 | /**
60 |  * @method errors.ParameterizedQueryError#toString
61 |  * @description
62 |  * Creates a well-formatted multi-line string that represents the error.
63 |  *
64 |  * It is called automatically when writing the object into the console.
65 |  *
66 |  * @param {number} [level=0]
67 |  * Nested output level, to provide visual offset.
68 |  *
69 |  * @returns {string}
70 |  */
71 | ParameterizedQueryError.prototype.toString = function (level) {
72 |     level = level > 0 ? parseInt(level) : 0;
73 |     const gap0 = npm.utils.messageGap(level),
74 |         gap1 = npm.utils.messageGap(level + 1),
75 |         gap2 = npm.utils.messageGap(level + 2),
76 |         lines = [
77 |             'ParameterizedQueryError {',
78 |             gap1 + 'message: "' + this.message + '"',
79 |             gap1 + 'result: {',
80 |             gap2 + 'text: ' + npm.utils.toJson(this.result.text),
81 |             gap2 + 'values: ' + npm.utils.toJson(this.result.values),
82 |             gap1 + '}'
83 |         ];
84 |     if (this.error) {
85 |         lines.push(gap1 + 'error: ' + this.error.toString(level + 1));
86 |     }
87 |     lines.push(gap0 + '}');
88 |     return lines.join(npm.os.EOL);
89 | };
90 | 
91 | npm.utils.addInspection(ParameterizedQueryError, function () {
92 |     return this.toString();
93 | });
94 | 
95 | module.exports = {ParameterizedQueryError};
96 | 


--------------------------------------------------------------------------------
/lib/errors/prepared-statement-error.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {QueryFileError} = require('./query-file-error');
11 | 
12 | const npm = {
13 |     os: require('os'),
14 |     utils: require('../utils')
15 | };
16 | 
17 | /**
18 |  * @class errors.PreparedStatementError
19 |  * @augments external:Error
20 |  * @description
21 |  * {@link errors.PreparedStatementError PreparedStatementError} class, available from the {@link errors} namespace.
22 |  *
23 |  * This type represents all errors that can be reported by class {@link PreparedStatement}, whether it is used
24 |  * explicitly or implicitly (via a simple `{name, text, values}` object).
25 |  *
26 |  * @property {string} name
27 |  * Standard {@link external:Error Error} property - error type name = `PreparedStatementError`.
28 |  *
29 |  * @property {string} message
30 |  * Standard {@link external:Error Error} property - the error message.
31 |  *
32 |  * @property {string} stack
33 |  * Standard {@link external:Error Error} property - the stack trace.
34 |  *
35 |  * @property {errors.QueryFileError} error
36 |  * Internal {@link errors.QueryFileError} object.
37 |  *
38 |  * It is set only when the source {@link PreparedStatement} used a {@link QueryFile} which threw the error.
39 |  *
40 |  * @property {object} result
41 |  * Resulting Prepared Statement object.
42 |  *
43 |  * @see PreparedStatement
44 |  */
45 | class PreparedStatementError extends Error {
46 |     constructor(error, ps) {
47 |         const isQueryFileError = error instanceof QueryFileError;
48 |         const message = isQueryFileError ? 'Failed to initialize \'text\' from a QueryFile.' : error;
49 |         super(message);
50 |         this.name = this.constructor.name;
51 |         if (isQueryFileError) {
52 |             this.error = error;
53 |         }
54 |         this.result = ps;
55 |         Error.captureStackTrace(this, this.constructor);
56 |     }
57 | }
58 | 
59 | /**
60 |  * @method errors.PreparedStatementError#toString
61 |  * @description
62 |  * Creates a well-formatted multi-line string that represents the error.
63 |  *
64 |  * It is called automatically when writing the object into the console.
65 |  *
66 |  * @param {number} [level=0]
67 |  * Nested output level, to provide visual offset.
68 |  *
69 |  * @returns {string}
70 |  */
71 | PreparedStatementError.prototype.toString = function (level) {
72 |     level = level > 0 ? parseInt(level) : 0;
73 |     const gap0 = npm.utils.messageGap(level),
74 |         gap1 = npm.utils.messageGap(level + 1),
75 |         gap2 = npm.utils.messageGap(level + 2),
76 |         lines = [
77 |             'PreparedStatementError {',
78 |             gap1 + 'message: "' + this.message + '"',
79 |             gap1 + 'result: {',
80 |             gap2 + 'name: ' + npm.utils.toJson(this.result.name),
81 |             gap2 + 'text: ' + npm.utils.toJson(this.result.text),
82 |             gap2 + 'values: ' + npm.utils.toJson(this.result.values),
83 |             gap1 + '}'
84 |         ];
85 |     if (this.error) {
86 |         lines.push(gap1 + 'error: ' + this.error.toString(level + 1));
87 |     }
88 |     lines.push(gap0 + '}');
89 |     return lines.join(npm.os.EOL);
90 | };
91 | 
92 | npm.utils.addInspection(PreparedStatementError, function () {
93 |     return this.toString();
94 | });
95 | 
96 | module.exports = {PreparedStatementError};
97 | 


--------------------------------------------------------------------------------
/lib/errors/query-file-error.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const npm = {
11 |     os: require('os'),
12 |     utils: require('../utils'),
13 |     minify: require('pg-minify')
14 | };
15 | 
16 | /**
17 |  * @class errors.QueryFileError
18 |  * @augments external:Error
19 |  * @description
20 |  * {@link errors.QueryFileError QueryFileError} class, available from the {@link errors} namespace.
21 |  *
22 |  * This type represents all errors related to {@link QueryFile}.
23 |  *
24 |  * @property {string} name
25 |  * Standard {@link external:Error Error} property - error type name = `QueryFileError`.
26 |  *
27 |  * @property {string} message
28 |  * Standard {@link external:Error Error} property - the error message.
29 |  *
30 |  * @property {string} stack
31 |  * Standard {@link external:Error Error} property - the stack trace.
32 |  *
33 |  * @property {string} file
34 |  * File path/name that was passed into the {@link QueryFile} constructor.
35 |  *
36 |  * @property {object} options
37 |  * Set of options that was used by the {@link QueryFile} object.
38 |  *
39 |  * @property {SQLParsingError} error
40 |  * Internal $[SQLParsingError] object.
41 |  *
42 |  * It is set only when the error was thrown by $[pg-minify] while parsing the SQL file.
43 |  *
44 |  * @see QueryFile
45 |  *
46 |  */
47 | class QueryFileError extends Error {
48 |     constructor(error, qf) {
49 |         const isSqlError = error instanceof npm.minify.SQLParsingError;
50 |         const message = isSqlError ? 'Failed to parse the SQL.' : error.message;
51 |         super(message);
52 |         this.name = this.constructor.name;
53 |         if (isSqlError) {
54 |             this.error = error;
55 |         }
56 |         this.file = qf.file;
57 |         this.options = qf.options;
58 |         Error.captureStackTrace(this, this.constructor);
59 |     }
60 | }
61 | 
62 | /**
63 |  * @method errors.QueryFileError#toString
64 |  * @description
65 |  * Creates a well-formatted multi-line string that represents the error.
66 |  *
67 |  * It is called automatically when writing the object into the console.
68 |  *
69 |  * @param {number} [level=0]
70 |  * Nested output level, to provide visual offset.
71 |  *
72 |  * @returns {string}
73 |  */
74 | QueryFileError.prototype.toString = function (level) {
75 |     level = level > 0 ? parseInt(level) : 0;
76 |     const gap0 = npm.utils.messageGap(level),
77 |         gap1 = npm.utils.messageGap(level + 1),
78 |         lines = [
79 |             'QueryFileError {',
80 |             gap1 + 'message: "' + this.message + '"',
81 |             gap1 + 'options: ' + npm.utils.toJson(this.options),
82 |             gap1 + 'file: "' + this.file + '"'
83 |         ];
84 |     if (this.error) {
85 |         lines.push(gap1 + 'error: ' + this.error.toString(level + 1));
86 |     }
87 |     lines.push(gap0 + '}');
88 |     return lines.join(npm.os.EOL);
89 | };
90 | 
91 | npm.utils.addInspection(QueryFileError, function () {
92 |     return this.toString();
93 | });
94 | 
95 | module.exports = {QueryFileError};
96 | 


--------------------------------------------------------------------------------
/lib/errors/query-result-error.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const npm = {
 11 |     os: require('os'),
 12 |     utils: require('../utils'),
 13 |     text: require('../text')
 14 | };
 15 | 
 16 | /**
 17 |  * @enum {number}
 18 |  * @alias errors.queryResultErrorCode
 19 |  * @readonly
 20 |  * @description
 21 |  * `queryResultErrorCode` enumerator, available from the {@link errors} namespace.
 22 |  *
 23 |  * Represents an integer code for each type of error supported by type {@link errors.QueryResultError}.
 24 |  *
 25 |  * @see {@link errors.QueryResultError}
 26 |  */
 27 | const queryResultErrorCode = {
 28 |     /** No data returned from the query. */
 29 |     noData: 0,
 30 | 
 31 |     /** No return data was expected. */
 32 |     notEmpty: 1,
 33 | 
 34 |     /** Multiple rows were not expected. */
 35 |     multiple: 2
 36 | };
 37 | 
 38 | const errorMessages = [
 39 |     {name: 'noData', message: npm.text.noData},
 40 |     {name: 'notEmpty', message: npm.text.notEmpty},
 41 |     {name: 'multiple', message: npm.text.multiple}
 42 | ];
 43 | 
 44 | /**
 45 |  * @class errors.QueryResultError
 46 |  * @augments external:Error
 47 |  * @description
 48 |  *
 49 |  * This error is specified as the rejection reason for all result-specific methods when the result doesn't match
 50 |  * the expectation, i.e. when a query result doesn't match its Query Result Mask - the value of {@link queryResult}.
 51 |  *
 52 |  * The error applies to the result from the following methods: {@link Database#none none},
 53 |  * {@link Database#one one}, {@link Database#oneOrNone oneOrNone} and {@link Database#many many}.
 54 |  *
 55 |  * Supported errors:
 56 |  *
 57 |  * - `No return data was expected.`, method {@link Database#none none}
 58 |  * - `No data returned from the query.`, methods {@link Database#one one} and {@link Database#many many}
 59 |  * - `Multiple rows were not expected.`, methods {@link Database#one one} and {@link Database#oneOrNone oneOrNone}
 60 |  *
 61 |  * Like any other error, this one is notified with through the global event {@link event:error error}.
 62 |  *
 63 |  * The type is available from the {@link errors} namespace.
 64 |  *
 65 |  * @property {string} name
 66 |  * Standard {@link external:Error Error} property - error type name = `QueryResultError`.
 67 |  *
 68 |  * @property {string} message
 69 |  * Standard {@link external:Error Error} property - the error message.
 70 |  *
 71 |  * @property {string} stack
 72 |  * Standard {@link external:Error Error} property - the stack trace.
 73 |  *
 74 |  * @property {object} result
 75 |  * The original $[Result] object that was received.
 76 |  *
 77 |  * @property {number} received
 78 |  * Total number of rows received. It is simply the value of `result.rows.length`.
 79 |  *
 80 |  * @property {number} code
 81 |  * Error code - {@link errors.queryResultErrorCode queryResultErrorCode} value.
 82 |  *
 83 |  * @property {string} query
 84 |  * Query that was executed.
 85 |  *
 86 |  * Normally, it is the query already formatted with values, if there were any.
 87 |  * But if you are using initialization option `pgFormatting`, then the query string is before formatting.
 88 |  *
 89 |  * @property {*} values
 90 |  * Values passed in as query parameters. Available only when initialization option `pgFormatting` is used.
 91 |  * Otherwise, the values are within the pre-formatted `query` string.
 92 |  *
 93 |  * @example
 94 |  *
 95 |  * const QueryResultError = pgp.errors.QueryResultError;
 96 |  * const qrec = pgp.errors.queryResultErrorCode;
 97 |  *
 98 |  * const initOptions = {
 99 |  *
100 |  *   // pg-promise initialization options...
101 |  *
102 |  *   error(err, e) {
103 |  *       if (err instanceof QueryResultError) {
104 |  *           // A query returned unexpected number of records, and thus rejected;
105 |  *           
106 |  *           // we can check the error code, if we want specifics:
107 |  *           if(err.code === qrec.noData) {
108 |  *               // expected some data, but received none;
109 |  *           }
110 |  *
111 |  *           // If you write QueryResultError into the console,
112 |  *           // you will get a nicely formatted output.
113 |  *
114 |  *           console.log(err);
115 |  *           
116 |  *           // See also: err, e.query, e.params, etc.
117 |  *       }
118 |  *   }
119 |  * };
120 |  *
121 |  * @see
122 |  * {@link queryResult}, {@link Database#none none}, {@link Database#one one},
123 |  * {@link Database#oneOrNone oneOrNone}, {@link Database#many many}
124 |  *
125 |  */
126 | class QueryResultError extends Error {
127 |     constructor(code, result, query, values) {
128 |         const message = errorMessages[code].message;
129 |         super(message);
130 |         this.name = this.constructor.name;
131 |         this.code = code;
132 |         this.result = result;
133 |         this.query = query;
134 |         this.values = values;
135 |         this.received = result.rows.length;
136 |         Error.captureStackTrace(this, this.constructor);
137 |     }
138 | }
139 | 
140 | /**
141 |  * @method errors.QueryResultError#toString
142 |  * @description
143 |  * Creates a well-formatted multi-line string that represents the error.
144 |  *
145 |  * It is called automatically when writing the object into the console.
146 |  *
147 |  * @param {number} [level=0]
148 |  * Nested output level, to provide visual offset.
149 |  *
150 |  * @returns {string}
151 |  */
152 | QueryResultError.prototype.toString = function (level) {
153 |     level = level > 0 ? parseInt(level) : 0;
154 |     const gap0 = npm.utils.messageGap(level),
155 |         gap1 = npm.utils.messageGap(level + 1),
156 |         lines = [
157 |             'QueryResultError {',
158 |             gap1 + 'code: queryResultErrorCode.' + errorMessages[this.code].name,
159 |             gap1 + 'message: "' + this.message + '"',
160 |             gap1 + 'received: ' + this.received,
161 |             gap1 + 'query: ' + (typeof this.query === 'string' ? '"' + this.query + '"' : npm.utils.toJson(this.query))
162 |         ];
163 |     if (this.values !== undefined) {
164 |         lines.push(gap1 + 'values: ' + npm.utils.toJson(this.values));
165 |     }
166 |     lines.push(gap0 + '}');
167 |     return lines.join(npm.os.EOL);
168 | };
169 | 
170 | npm.utils.addInspection(QueryResultError, function () {
171 |     return this.toString();
172 | });
173 | 
174 | module.exports = {
175 |     QueryResultError,
176 |     queryResultErrorCode
177 | };
178 | 


--------------------------------------------------------------------------------
/lib/helpers/README.md:
--------------------------------------------------------------------------------
 1 | ### `helpers` namespace
 2 | 
 3 | This folder contains everything that's available via the [helpers] namespace, after initializing the library:
 4 | 
 5 | ```js
 6 | const pgp = require('pg-promise')(/*initialization options*/);
 7 | const helpers = pgp.helpers; // `helpers` namespace
 8 | ```
 9 | 
10 | [helpers]:http://vitaly-t.github.io/pg-promise/helpers.html
11 | 


--------------------------------------------------------------------------------
/lib/helpers/index.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {Column} = require('./column');
11 | const {ColumnSet} = require('./column-set');
12 | const {TableName, _TN} = require('./table-name');
13 | const method = require('./methods');
14 | 
15 | /**
16 |  * @namespace helpers
17 |  * @description
18 |  * Namespace for query-formatting generators, available as {@link module:pg-promise~helpers pgp.helpers}, after initializing the library.
19 |  *
20 |  * It unifies the approach to generating multi-row `INSERT` / `UPDATE` queries with the single-row ones.
21 |  *
22 |  * See also: $[Performance Boost].
23 |  *
24 |  * @property {function} TableName
25 |  * {@link helpers.TableName TableName} class constructor.
26 |  *
27 |  * @property {function} _TN
28 |  * {@link helpers._TN _TN} Table-Name conversion function.
29 |  *
30 |  * @property {function} ColumnSet
31 |  * {@link helpers.ColumnSet ColumnSet} class constructor.
32 |  *
33 |  * @property {function} Column
34 |  * {@link helpers.Column Column} class constructor.
35 |  *
36 |  * @property {function} insert
37 |  * {@link helpers.insert insert} static method.
38 |  *
39 |  * @property {function} update
40 |  * {@link helpers.update update} static method.
41 |  *
42 |  * @property {function} values
43 |  * {@link helpers.values values} static method.
44 |  *
45 |  * @property {function} sets
46 |  * {@link helpers.sets sets} static method.
47 |  *
48 |  * @property {function} concat
49 |  * {@link helpers.concat concat} static method.
50 |  */
51 | module.exports = config => {
52 |     const capSQL = () => config.options && config.options.capSQL;
53 |     const res = {
54 |         insert(data, columns, table) {
55 |             return method.insert(data, columns, table, capSQL());
56 |         },
57 |         update(data, columns, table, options) {
58 |             return method.update(data, columns, table, options, capSQL());
59 |         },
60 |         concat(queries) {
61 |             return method.concat(queries, capSQL());
62 |         },
63 |         values(data, columns) {
64 |             return method.values(data, columns, capSQL());
65 |         },
66 |         sets(data, columns) {
67 |             return method.sets(data, columns, capSQL());
68 |         },
69 |         TableName,
70 |         _TN,
71 |         ColumnSet,
72 |         Column
73 |     };
74 |     return res;
75 | };
76 | 


--------------------------------------------------------------------------------
/lib/helpers/methods/concat.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {QueryFile} = require('../../query-file');
 11 | 
 12 | const npm = {
 13 |     formatting: require('../../formatting')
 14 | };
 15 | 
 16 | /**
 17 |  * @method helpers.concat
 18 |  * @description
 19 |  * Formats and concatenates multiple queries into a single query string.
 20 |  *
 21 |  * Before joining the queries, the method does the following:
 22 |  *  - Formats each query, if `values` are provided;
 23 |  *  - Removes all leading and trailing spaces, tabs and semi-colons;
 24 |  *  - Automatically skips all empty queries.
 25 |  *
 26 |  * @param {array<string|helpers.QueryFormat|QueryFile>} queries
 27 |  * Array of mixed-type elements:
 28 |  * - a simple query string, to be used as is
 29 |  * - a {@link helpers.QueryFormat QueryFormat}-like object = `{query, [values], [options]}`
 30 |  * - a {@link QueryFile} object
 31 |  *
 32 |  * @returns {string}
 33 |  * Concatenated string with all queries.
 34 |  *
 35 |  * @example
 36 |  *
 37 |  * const pgp = require('pg-promise')();
 38 |  *
 39 |  * const qf1 = new pgp.QueryFile('./query1.sql', {minify: true});
 40 |  * const qf2 = new pgp.QueryFile('./query2.sql', {minify: true});
 41 |  *
 42 |  * const query = pgp.helpers.concat([
 43 |  *     {query: 'INSERT INTO Users(name, age) VALUES($1, $2)', values: ['John', 23]}, // QueryFormat-like object
 44 |  *     {query: qf1, values: [1, 'Name']}, // QueryFile with formatting parameters
 45 |  *     'SELECT count(*) FROM Users', // a simple-string query,
 46 |  *     qf2 // direct QueryFile object
 47 |  * ]);
 48 |  *
 49 |  * // query = concatenated string with all the queries
 50 |  */
 51 | function concat(queries, capSQL) {
 52 |     if (!Array.isArray(queries)) {
 53 |         throw new TypeError('Parameter \'queries\' must be an array.');
 54 |     }
 55 |     const fmOptions = {capSQL};
 56 |     const all = queries.map((q, index) => {
 57 |         if (typeof q === 'string') {
 58 |             // a simple query string without parameters:
 59 |             return clean(q);
 60 |         }
 61 |         if (q && typeof q === 'object') {
 62 |             if (q instanceof QueryFile) {
 63 |                 // QueryFile object:
 64 |                 return clean(q[npm.formatting.as.ctf.toPostgres]());
 65 |             }
 66 |             if ('query' in q) {
 67 |                 // object {query, values, options}:
 68 |                 let opt = q.options && typeof q.options === 'object' ? q.options : {};
 69 |                 opt = opt.capSQL === undefined ? Object.assign(opt, fmOptions) : opt;
 70 |                 return clean(npm.formatting.as.format(q.query, q.values, opt));
 71 |             }
 72 |         }
 73 |         throw new Error(`Invalid query element at index ${index}.`);
 74 |     });
 75 | 
 76 |     return all.filter(q => q).join(';');
 77 | }
 78 | 
 79 | function clean(q) {
 80 |     // removes from the query all leading and trailing symbols ' ', '\t' and ';'
 81 |     return q.replace(/^[\s;]*|[\s;]*$/g, '');
 82 | }
 83 | 
 84 | module.exports = {concat};
 85 | 
 86 | /**
 87 |  * @typedef helpers.QueryFormat
 88 |  * @description
 89 |  * A simple structure of parameters to be passed into method {@link formatting.format as.format} exactly as they are,
 90 |  * used by {@link helpers.concat}.
 91 |  *
 92 |  * @property {string|value|object} query
 93 |  * A query string or a value/object that implements $[Custom Type Formatting], to be formatted according to `values`.
 94 |  *
 95 |  * @property {array|object|value} [values]
 96 |  * Query-formatting values.
 97 |  *
 98 |  * @property {object} [options]
 99 |  * Query-formatting options, as supported by method {@link formatting.format as.format}.
100 |  *
101 |  * @see
102 |  * {@link formatting.format as.format}
103 |  */
104 | 


--------------------------------------------------------------------------------
/lib/helpers/methods/index.js:
--------------------------------------------------------------------------------
 1 | const {concat} = require('./concat');
 2 | const {insert} = require('./insert');
 3 | const {update} = require('./update');
 4 | const {values} = require('./values');
 5 | const {sets} = require('./sets');
 6 | 
 7 | module.exports = {
 8 |     concat,
 9 |     insert,
10 |     update,
11 |     values,
12 |     sets
13 | };
14 | 


--------------------------------------------------------------------------------
/lib/helpers/methods/insert.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {TableName} = require('../table-name');
 11 | const {ColumnSet} = require('../column-set');
 12 | 
 13 | const npm = {
 14 |     formatting: require('../../formatting'),
 15 |     utils: require('../../utils')
 16 | };
 17 | 
 18 | /**
 19 |  * @method helpers.insert
 20 |  * @description
 21 |  * Generates an `INSERT` query for either one object or an array of objects.
 22 |  *
 23 |  * @param {object|object[]} data
 24 |  * An insert object with properties for insert values, or an array of such objects.
 25 |  *
 26 |  * When `data` is not a non-null object and not an array, it will throw {@link external:TypeError TypeError} = `Invalid parameter 'data' specified.`
 27 |  *
 28 |  * When `data` is an empty array, it will throw {@link external:TypeError TypeError} = `Cannot generate an INSERT from an empty array.`
 29 |  *
 30 |  * When `data` is an array that contains a non-object value, the method will throw {@link external:Error Error} =
 31 |  * `Invalid insert object at index N.`
 32 |  *
 33 |  * @param {array|helpers.Column|helpers.ColumnSet} [columns]
 34 |  * Set of columns to be inserted.
 35 |  *
 36 |  * It is optional when `data` is a single object, and required when `data` is an array of objects. If not specified for an array
 37 |  * of objects, the method will throw {@link external:TypeError TypeError} = `Parameter 'columns' is required when inserting multiple records.`
 38 |  *
 39 |  * When `columns` is not a {@link helpers.ColumnSet ColumnSet} object, a temporary {@link helpers.ColumnSet ColumnSet}
 40 |  * is created - from the value of `columns` (if it was specified), or from the value of `data` (if it is not an array).
 41 |  *
 42 |  * When the final {@link helpers.ColumnSet ColumnSet} is empty (no columns in it), the method will throw
 43 |  * {@link external:Error Error} = `Cannot generate an INSERT without any columns.`
 44 |  *
 45 |  * @param {helpers.TableName|Table|string} [table]
 46 |  * Destination table.
 47 |  *
 48 |  * It is normally a required parameter. But when `columns` is passed in as a {@link helpers.ColumnSet ColumnSet} object
 49 |  * with `table` set in it, that will be used when this parameter isn't specified. When neither is available, the method
 50 |  * will throw {@link external:Error Error} = `Table name is unknown.`
 51 |  *
 52 |  * @returns {string}
 53 |  * An `INSERT` query string.
 54 |  *
 55 |  * @see
 56 |  *  {@link helpers.Column Column},
 57 |  *  {@link helpers.ColumnSet ColumnSet},
 58 |  *  {@link helpers.TableName TableName}
 59 |  *
 60 |  * @example
 61 |  *
 62 |  * const pgp = require('pg-promise')({
 63 |  *    capSQL: true // if you want all generated SQL capitalized
 64 |  * });
 65 |  * const {insert} = pgp.helpers;
 66 |  *
 67 |  * const dataSingle = {val: 123, msg: 'hello'};
 68 |  * const dataMulti = [{val: 123, msg: 'hello'}, {val: 456, msg: 'world!'}];
 69 |  *
 70 |  * // Column details can be taken from the data object:
 71 |  *
 72 |  * insert(dataSingle, null, 'my-table');
 73 |  * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello')
 74 |  *
 75 |  * @example
 76 |  *
 77 |  * // Column details are required for a multi-row `INSERT`:
 78 |  * const {insert} = pgp.helpers;
 79 |  *
 80 |  * insert(dataMulti, ['val', 'msg'], 'my-table');
 81 |  * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello'),(456,'world!')
 82 |  *
 83 |  * @example
 84 |  *
 85 |  * // Column details from a reusable ColumnSet (recommended for performance):
 86 |  * const {ColumnSet, insert} = pgp.helpers;
 87 |  *
 88 |  * const cs = new ColumnSet(['val', 'msg'], {table: 'my-table'});
 89 |  *
 90 |  * insert(dataMulti, cs);
 91 |  * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello'),(456,'world!')
 92 |  *
 93 |  */
 94 | function insert(data, columns, table, capSQL) {
 95 | 
 96 |     if (!data || typeof data !== 'object') {
 97 |         throw new TypeError('Invalid parameter \'data\' specified.');
 98 |     }
 99 | 
100 |     const isArray = Array.isArray(data);
101 | 
102 |     if (isArray && !data.length) {
103 |         throw new TypeError('Cannot generate an INSERT from an empty array.');
104 |     }
105 | 
106 |     if (columns instanceof ColumnSet) {
107 |         if (npm.utils.isNull(table)) {
108 |             table = columns.table;
109 |         }
110 |     } else {
111 |         if (isArray && npm.utils.isNull(columns)) {
112 |             throw new TypeError('Parameter \'columns\' is required when inserting multiple records.');
113 |         }
114 |         columns = new ColumnSet(columns || data);
115 |     }
116 | 
117 |     if (!columns.columns.length) {
118 |         throw new Error('Cannot generate an INSERT without any columns.');
119 |     }
120 | 
121 |     if (!table) {
122 |         throw new Error('Table name is unknown.');
123 |     }
124 | 
125 |     if (!(table instanceof TableName)) {
126 |         table = new TableName(table);
127 |     }
128 | 
129 |     let query = capSQL ? sql.capCase : sql.lowCase;
130 |     const fmOptions = {capSQL};
131 | 
132 |     const format = npm.formatting.as.format;
133 |     query = format(query, [table.name, columns.names], fmOptions);
134 | 
135 |     if (isArray) {
136 |         return query + data.map((d, index) => {
137 |             if (!d || typeof d !== 'object') {
138 |                 throw new Error(`Invalid insert object at index ${index}.`);
139 |             }
140 |             return '(' + format(columns.variables, columns.prepare(d), fmOptions) + ')';
141 |         }).join();
142 |     }
143 |     return query + '(' + format(columns.variables, columns.prepare(data), fmOptions) + ')';
144 | }
145 | 
146 | const sql = {
147 |     lowCase: 'insert into $1^($2^) values',
148 |     capCase: 'INSERT INTO $1^($2^) VALUES'
149 | };
150 | 
151 | module.exports = {insert};
152 | 


--------------------------------------------------------------------------------
/lib/helpers/methods/sets.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {ColumnSet} = require('../column-set');
11 | 
12 | const npm = {
13 |     format: require('../../formatting').as.format,
14 |     utils: require('../../utils')
15 | };
16 | 
17 | /**
18 |  * @method helpers.sets
19 |  * @description
20 |  * Generates a string of comma-separated value-set statements from a single object: `col1=val1, col2=val2, ...`,
21 |  * to be used as part of a query.
22 |  *
23 |  * Since it is to be used as part of `UPDATE` queries, {@link helpers.Column Column} properties `cnd` and `skip` apply.
24 |  *
25 |  * @param {object} data
26 |  * A simple, non-null and non-array source object.
27 |  *
28 |  * If it is anything else, the method will throw {@link external:TypeError TypeError} = `Invalid parameter 'data' specified.`
29 |  *
30 |  * @param {array|helpers.Column|helpers.ColumnSet} [columns]
31 |  * Columns for which to set values.
32 |  *
33 |  * When not specified, properties of the `data` object are used.
34 |  *
35 |  * When no effective columns are found, an empty string is returned.
36 |  *
37 |  * @returns {string}
38 |  * - comma-separated value-set statements for the `data` object
39 |  * - an empty string, if no effective columns found
40 |  *
41 |  * @see
42 |  *  {@link helpers.Column Column},
43 |  *  {@link helpers.ColumnSet ColumnSet}
44 |  *
45 |  * @example
46 |  *
47 |  * const pgp = require('pg-promise')();
48 |  *
49 |  * const data = {id: 1, val: 123, msg: 'hello'};
50 |  *
51 |  * // Properties can be pulled automatically from the object:
52 |  *
53 |  * pgp.helpers.sets(data);
54 |  * //=> "id"=1,"val"=123,"msg"='hello'
55 |  *
56 |  * @example
57 |  *
58 |  * // Column details from a reusable ColumnSet (recommended for performance);
59 |  * // NOTE: Conditional columns (start with '?') are skipped:
60 |  * const {ColumnSet, sets} = pgp.helpers;
61 |  *
62 |  * const cs = new ColumnSet(['?id','val', 'msg']);
63 |  *
64 |  * sets(data, cs);
65 |  * //=> "val"=123,"msg"='hello'
66 |  *
67 |  */
68 | function sets(data, columns, capSQL) {
69 | 
70 |     if (!data || typeof data !== 'object' || Array.isArray(data)) {
71 |         throw new TypeError('Invalid parameter \'data\' specified.');
72 |     }
73 | 
74 |     if (!(columns instanceof ColumnSet)) {
75 |         columns = new ColumnSet(columns || data);
76 |     }
77 | 
78 |     return npm.format(columns.assign({source: data}), columns.prepare(data), {capSQL});
79 | }
80 | 
81 | module.exports = {sets};
82 | 


--------------------------------------------------------------------------------
/lib/helpers/methods/values.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {ColumnSet} = require('../column-set');
 11 | 
 12 | const npm = {
 13 |     formatting: require('../../formatting'),
 14 |     utils: require('../../utils')
 15 | };
 16 | 
 17 | /**
 18 |  * @method helpers.values
 19 |  * @description
 20 |  * Generates a string of comma-separated value groups from either one object or an array of objects,
 21 |  * to be used as part of a query:
 22 |  *
 23 |  * - from a single object: `(val_1, val_2, ...)`
 24 |  * - from an array of objects: `(val_11, val_12, ...), (val_21, val_22, ...)`
 25 |  *
 26 |  * @param {object|object[]} data
 27 |  * A source object with properties as values, or an array of such objects.
 28 |  *
 29 |  * If it is anything else, the method will throw {@link external:TypeError TypeError} = `Invalid parameter 'data' specified.`
 30 |  *
 31 |  * When `data` is an array that contains a non-object value, the method will throw {@link external:Error Error} =
 32 |  * `Invalid object at index N.`
 33 |  *
 34 |  * When `data` is an empty array, an empty string is returned.
 35 |  *
 36 |  * @param {array|helpers.Column|helpers.ColumnSet} [columns]
 37 |  * Columns for which to return values.
 38 |  *
 39 |  * It is optional when `data` is a single object, and required when `data` is an array of objects. If not specified for an array
 40 |  * of objects, the method will throw {@link external:TypeError TypeError} = `Parameter 'columns' is required when generating multi-row values.`
 41 |  *
 42 |  * When the final {@link helpers.ColumnSet ColumnSet} is empty (no columns in it), the method will throw
 43 |  * {@link external:Error Error} = `Cannot generate values without any columns.`
 44 |  *
 45 |  * @returns {string}
 46 |  * - comma-separated value groups, according to `data`
 47 |  * - an empty string, if `data` is an empty array
 48 |  *
 49 |  * @see
 50 |  *  {@link helpers.Column Column},
 51 |  *  {@link helpers.ColumnSet ColumnSet}
 52 |  *
 53 |  * @example
 54 |  *
 55 |  * const pgp = require('pg-promise')();
 56 |  *
 57 |  * const dataSingle = {val: 123, msg: 'hello'};
 58 |  * const dataMulti = [{val: 123, msg: 'hello'}, {val: 456, msg: 'world!'}];
 59 |  *
 60 |  * // Properties can be pulled automatically from a single object:
 61 |  *
 62 |  * pgp.helpers.values(dataSingle);
 63 |  * //=> (123,'hello')
 64 |  *
 65 |  * @example
 66 |  *
 67 |  * // Column details are required when using an array of objects:
 68 |  *
 69 |  * pgp.helpers.values(dataMulti, ['val', 'msg']);
 70 |  * //=> (123,'hello'),(456,'world!')
 71 |  *
 72 |  * @example
 73 |  *
 74 |  * // Column details from a reusable ColumnSet (recommended for performance):
 75 |  * const {ColumnSet, values} = pgp.helpers;
 76 |  *
 77 |  * const cs = new ColumnSet(['val', 'msg']);
 78 |  *
 79 |  * values(dataMulti, cs);
 80 |  * //=> (123,'hello'),(456,'world!')
 81 |  *
 82 |  */
 83 | function values(data, columns, capSQL) {
 84 | 
 85 |     if (!data || typeof data !== 'object') {
 86 |         throw new TypeError('Invalid parameter \'data\' specified.');
 87 |     }
 88 | 
 89 |     const isArray = Array.isArray(data);
 90 | 
 91 |     if (!(columns instanceof ColumnSet)) {
 92 |         if (isArray && npm.utils.isNull(columns)) {
 93 |             throw new TypeError('Parameter \'columns\' is required when generating multi-row values.');
 94 |         }
 95 |         columns = new ColumnSet(columns || data);
 96 |     }
 97 | 
 98 |     if (!columns.columns.length) {
 99 |         throw new Error('Cannot generate values without any columns.');
100 |     }
101 | 
102 |     const format = npm.formatting.as.format,
103 |         fmOptions = {capSQL};
104 | 
105 |     if (isArray) {
106 |         return data.map((d, index) => {
107 |             if (!d || typeof d !== 'object') {
108 |                 throw new Error(`Invalid object at index ${index}.`);
109 |             }
110 |             return '(' + format(columns.variables, columns.prepare(d), fmOptions) + ')';
111 |         }).join();
112 |     }
113 |     return '(' + format(columns.variables, columns.prepare(data), fmOptions) + ')';
114 | }
115 | 
116 | module.exports = {values};
117 | 


--------------------------------------------------------------------------------
/lib/helpers/table-name.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {assert} = require('../assert');
 11 | 
 12 | const npm = {
 13 |     utils: require('../utils'),
 14 |     format: require('../formatting').as // formatting namespace
 15 | };
 16 | 
 17 | /**
 18 |  * @class helpers.TableName
 19 |  * @description
 20 |  * Represents a full table name that can be injected into queries directly.
 21 |  *
 22 |  * This is a read-only type that can be used wherever parameter `table` is supported.
 23 |  *
 24 |  * It supports $[Custom Type Formatting], which means you can use the type directly as a formatting
 25 |  * parameter, without specifying any escaping.
 26 |  *
 27 |  * Filter `:alias` is an alternative approach to splitting an SQL name into multiple ones.
 28 |  *
 29 |  * @param {string|Table} table
 30 |  * Table name details, depending on the type:
 31 |  *
 32 |  * - table name, if `table` is a string
 33 |  * - {@link Table} object
 34 |  *
 35 |  * @property {string} name
 36 |  * Formatted/escaped full table name, combining `schema` + `table`.
 37 |  *
 38 |  * @property {string} table
 39 |  * Table name.
 40 |  *
 41 |  * @property {string} schema
 42 |  * Database schema name.
 43 |  *
 44 |  * It is `undefined` when no valid schema was specified.
 45 |  *
 46 |  * @returns {helpers.TableName}
 47 |  *
 48 |  * @see
 49 |  * {@link helpers._TN _TN},
 50 |  * {@link helpers.TableName#toPostgres toPostgres}
 51 |  *
 52 |  * @example
 53 |  *
 54 |  * const table = new pgp.helpers.TableName({table: 'my-table', schema: 'my-schema'});
 55 |  * console.log(table);
 56 |  * //=> "my-schema"."my-table"
 57 |  *
 58 |  * // Formatting the type directly:
 59 |  * pgp.as.format('SELECT * FROM $1', table);
 60 |  * //=> SELECT * FROM "my-schema"."my-table"
 61 |  *
 62 |  */
 63 | class TableName {
 64 | 
 65 |     constructor(table) {
 66 |         if (typeof table === 'string') {
 67 |             this.table = table;
 68 |         } else {
 69 |             const config = assert(table, ['table', 'schema']);
 70 |             this.table = config.table;
 71 |             if (npm.utils.isText(config.schema)) {
 72 |                 this.schema = config.schema;
 73 |             }
 74 |         }
 75 |         if (!npm.utils.isText(this.table)) {
 76 |             throw new TypeError('Table name must be a non-empty text string.');
 77 |         }
 78 |         this.name = npm.format.name(this.table);
 79 |         if (this.schema) {
 80 |             this.name = npm.format.name(this.schema) + '.' + this.name;
 81 |         }
 82 |         Object.freeze(this);
 83 |     }
 84 | }
 85 | 
 86 | /**
 87 |  * @method helpers.TableName#toPostgres
 88 |  * @description
 89 |  * $[Custom Type Formatting], based on $[Symbolic CTF], i.e. the actual method is available only via {@link external:Symbol Symbol}:
 90 |  *
 91 |  * ```js
 92 |  * const {toPostgres} = pgp.as.ctf; // Custom Type Formatting symbols namespace
 93 |  * const fullName = tn[toPostgres]; // tn = an object of type TableName
 94 |  * ```
 95 |  *
 96 |  * This is a raw formatting type (`rawType = true`), i.e. when used as a query-formatting parameter, type `TableName`
 97 |  * injects full table name as raw text.
 98 |  *
 99 |  * @param {helpers.TableName} [self]
100 |  * Optional self-reference, for ES6 arrow functions.
101 |  *
102 |  * @returns {string}
103 |  * Escaped full table name that includes optional schema name, if specified.
104 |  */
105 | TableName.prototype[npm.format.ctf.toPostgres] = function (self) {
106 |     self = this instanceof TableName && this || self;
107 |     return self.name;
108 | };
109 | 
110 | TableName.prototype[npm.format.ctf.rawType] = true; // use as pre-formatted
111 | 
112 | /**
113 |  * @method helpers.TableName#toString
114 |  * @description
115 |  * Creates a well-formatted string that represents the object.
116 |  *
117 |  * It is called automatically when writing the object into the console.
118 |  *
119 |  * @returns {string}
120 |  */
121 | TableName.prototype.toString = function () {
122 |     return this.name;
123 | };
124 | 
125 | npm.utils.addInspection(TableName, function () {
126 |     return this.toString();
127 | });
128 | 
129 | /**
130 |  * @interface Table
131 |  * @description
132 |  * Structure for any table name/path.
133 |  *
134 |  * Function {@link helpers._TN _TN} can help you construct it from a string.
135 |  *
136 |  * @property {string} [schema] - schema name, if specified
137 |  * @property {string} table - table name
138 |  *
139 |  * @see {@link helpers.TableName TableName}, {@link helpers._TN _TN}
140 |  */
141 | 
142 | /**
143 |  * @external TemplateStringsArray
144 |  * @see https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_es5_d_.templatestringsarray.html
145 |  */
146 | 
147 | /**
148 |  * @function helpers._TN
149 |  * @description
150 |  * Table-Name helper function, to convert any `"schema.table"` string
151 |  * into `{schema, table}` object. It also works as a template-tag function.
152 |  *
153 |  * @param {string|TemplateStringsArray} path
154 |  * Table-name path, as a simple string or a template string (with parameters).
155 |  *
156 |  * @example
157 |  * const {ColumnSet, _TN} = pgp.helpers;
158 |  *
159 |  * // Using as a regular function:
160 |  * const cs1 = new ColumnSet(['id', 'name'], {table: _TN('schema.table')});
161 |  *
162 |  * // Using as a template-tag function:
163 |  * const schema = 'schema';
164 |  * const cs2 = new ColumnSet(['id', 'name'], {table: _TN`${schema}.table`});
165 |  *
166 |  * @returns {Table}
167 |  *
168 |  * @see {@link helpers.TableName TableName}, {@link external:TemplateStringsArray TemplateStringsArray}
169 |  */
170 | function _TN(path, ...args) {
171 |     if (Array.isArray(path)) {
172 |         path = path.reduce((a, c, i) => a + c + (args[i] ?? ''), '');
173 |     } // else 'path' is a string
174 |     const [schema, table] = path.split('.');
175 |     if (table === undefined) {
176 |         return {table: schema};
177 |     }
178 |     return schema ? {schema, table} : {table};
179 | }
180 | 
181 | module.exports = {TableName, _TN};
182 | 


--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | /* eslint no-var: off */
11 | var v = process.versions.node.split('.'),
12 |     highVer = +v[0];
13 | 
14 | // istanbul ignore next
15 | if (highVer < 16) {
16 | 
17 |     // From pg-promise v11.15.0, the oldest supported Node.js is v16.0.0
18 | 
19 |     // Node.js v14.x was supported up to pg-promise v11.14.0
20 |     // Node.js v12.x was supported up to pg-promise v10.15.4
21 |     // Node.js v8.x was supported up to pg-promise v10.14.2
22 |     // Node.js v7.6.0 was supported up to pg-promise v10.3.5
23 |     // Node.js v4.5.0 was supported up to pg-promise v8.7.5
24 |     // Node.js v0.10 was supported up to pg-promise v5.5.8
25 | 
26 |     throw new Error('Minimum Node.js version supported by pg-promise is 16.0.0');
27 | }
28 | 
29 | module.exports = require('./main');
30 | 


--------------------------------------------------------------------------------
/lib/inner-state.js:
--------------------------------------------------------------------------------
 1 | const {addReadProp} = require('./utils');
 2 | 
 3 | /**
 4 |  * @private
 5 |  * @class InnerState
 6 |  * @description
 7 |  * Implements support for private/inner state object inside the class,
 8 |  * which can be accessed by a derived class via hidden read-only property _inner.
 9 |  */
10 | class InnerState {
11 | 
12 |     constructor(initialState) {
13 |         addReadProp(this, '_inner', {}, true);
14 |         if (initialState && typeof initialState === 'object') {
15 |             this.extendState(initialState);
16 |         }
17 |     }
18 | 
19 |     /**
20 |      * Extends or overrides inner state with the specified properties.
21 |      *
22 |      * Only own properties are used, i.e. inherited ones are skipped.
23 |      */
24 |     extendState(state) {
25 |         for (const a in state) {
26 |             // istanbul ignore else
27 |             if (Object.prototype.hasOwnProperty.call(state, a)) {
28 |                 this._inner[a] = state[a];
29 |             }
30 |         }
31 |     }
32 | }
33 | 
34 | /**
35 |  * @member InnerState#_inner
36 |  * Private/Inner object state.
37 |  */
38 | 
39 | module.exports = {InnerState};
40 | 


--------------------------------------------------------------------------------
/lib/patterns.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | /*
11 |   The most important regular expressions and data as used by the library,
12 |   isolated here to help with possible edge cases during integration.
13 | */
14 | 
15 | module.exports = {
16 |     // Searches for all Named Parameters, supporting any of the following syntax:
17 |     // ${propName}, $(propName), $[propName], $/propName/, 
lt;propName>
18 |     // Nested property names are also supported: ${propName.abc}
19 |     namedParameters: /\$(?:({)|(\()|(<)|(\[)|(\/))\s*[a-zA-Z0-9$_.]+(\^|~|#|:raw|:alias|:name|:json|:csv|:list|:value)?\s*(?:(?=\2)(?=\3)(?=\4)(?=\5)}|(?=\1)(?=\3)(?=\4)(?=\5)\)|(?=\1)(?=\2)(?=\4)(?=\5)>|(?=\1)(?=\2)(?=\3)(?=\5)]|(?=\1)(?=\2)(?=\3)(?=\4)\/)/g,
20 | 
21 |     // Searches for all variables $1, $2, ...$100000, and while it will find greater than $100000
22 |     // variables, the formatting engine is expected to throw an error for those.
23 |     multipleValues: /\$([1-9][0-9]{0,16}(?![0-9])(\^|~|#|:raw|:alias|:name|:json|:csv|:list|:value)?)/g,
24 | 
25 |     // Searches for all occurrences of variable $1
26 |     singleValue: /\$1(?![0-9])(\^|~|#|:raw|:alias|:name|:json|:csv|:list|:value)?/g,
27 | 
28 |     // Matches a valid column name for the Column type parser, according to the following rules:
29 |     // - can contain: any combination of a-z, A-Z, 0-9, $ or _
30 |     // - can contain ? at the start
31 |     // - can contain one of the supported filters/modifiers
32 |     validColumn: /\??[a-zA-Z0-9$_]+(\^|~|#|:raw|:alias|:name|:json|:csv|:list|:value)?/,
33 | 
34 |     // Matches a valid open-name JavaScript variable, according to the following rules:
35 |     // - can contain: any combination of a-z, A-Z, 0-9, $ or _
36 |     validVariable: /[a-zA-Z0-9$_]+/,
37 | 
38 |     // Matches a valid modifier in a column/property:
39 |     hasValidModifier: /\^|~|#|:raw|:alias|:name|:json|:csv|:list|:value/,
40 | 
41 |     // List of all supported formatting modifiers:
42 |     validModifiers: ['^', '~', '#', ':raw', ':alias', ':name', ':json', ':csv', ':list', ':value']
43 | };
44 | 


--------------------------------------------------------------------------------
/lib/promise-adapter.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {assert} = require('./assert');
11 | 
12 | /**
13 |  * @class PromiseAdapter
14 |  * @summary Adapter for the primary promise operations.
15 |  * @description
16 |  * Provides compatibility with promise libraries that cannot be recognized automatically,
17 |  * via functions that implement the primary operations with promises:
18 |  *
19 |  *  - construct a new promise with a callback function
20 |  *  - resolve a promise with some result data
21 |  *  - reject a promise with a reason
22 |  *  - resolve an array of promises
23 |  *
24 |  * The type is available from the library's root: `pgp.PromiseAdapter`.
25 |  *
26 |  * @param {object} api
27 |  * Promise API configuration object.
28 |  *
29 |  * Passing in anything other than an object will throw {@link external:TypeError TypeError} = `Adapter requires an api configuration object.`
30 |  *
31 |  * @param {function} api.create
32 |  * A function that takes a callback parameter and returns a new promise object.
33 |  * The callback parameter is expected to be `function(resolve, reject)`.
34 |  *
35 |  * Passing in anything other than a function will throw {@link external:TypeError TypeError} = `Function 'create' must be specified.`
36 |  *
37 |  * @param {function} api.resolve
38 |  * A function that takes an optional data parameter and resolves a promise with it.
39 |  *
40 |  * Passing in anything other than a function will throw {@link external:TypeError TypeError} = `Function 'resolve' must be specified.`
41 |  *
42 |  * @param {function} api.reject
43 |  * A function that takes an optional error parameter and rejects a promise with it.
44 |  *
45 |  * Passing in anything other than a function will throw {@link external:TypeError TypeError} = `Function 'reject' must be specified.`
46 |  *
47 |  * @param {function} api.all
48 |  * A function that resolves an array of promises.
49 |  *
50 |  * Passing in anything other than a function will throw {@link external:TypeError TypeError} = `Function 'all' must be specified.`
51 |  *
52 |  * @returns {PromiseAdapter}
53 |  */
54 | class PromiseAdapter {
55 |     constructor(api) {
56 | 
57 |         if (!api || typeof api !== 'object') {
58 |             throw new TypeError('Adapter requires an api configuration object.');
59 |         }
60 | 
61 |         api = assert(api, ['create', 'resolve', 'reject', 'all']);
62 | 
63 |         this.create = api.create;
64 |         this.resolve = api.resolve;
65 |         this.reject = api.reject;
66 |         this.all = api.all;
67 | 
68 |         if (typeof this.create !== 'function') {
69 |             throw new TypeError('Function \'create\' must be specified.');
70 |         }
71 | 
72 |         if (typeof this.resolve !== 'function') {
73 |             throw new TypeError('Function \'resolve\' must be specified.');
74 |         }
75 | 
76 |         if (typeof this.reject !== 'function') {
77 |             throw new TypeError('Function \'reject\' must be specified.');
78 |         }
79 | 
80 |         if (typeof this.all !== 'function') {
81 |             throw new TypeError('Function \'all\' must be specified.');
82 |         }
83 |     }
84 | }
85 | 
86 | module.exports = {PromiseAdapter};
87 | 


--------------------------------------------------------------------------------
/lib/promise-parser.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {PromiseAdapter} = require('./promise-adapter');
11 | 
12 | //////////////////////////////////////////
13 | // Parses and validates a promise library;
14 | function parse(pl) {
15 | 
16 |     let promise;
17 |     if (pl instanceof PromiseAdapter) {
18 |         promise = function (func) {
19 |             return pl.create(func);
20 |         };
21 |         promise.resolve = pl.resolve;
22 |         promise.reject = pl.reject;
23 |         promise.all = pl.all;
24 |         return promise;
25 |     }
26 |     const t = typeof pl;
27 |     if (t === 'function' || t === 'object') {
28 |         const Root = typeof pl.Promise === 'function' ? pl.Promise : pl;
29 |         promise = function (func) {
30 |             return new Root(func);
31 |         };
32 |         promise.resolve = Root.resolve;
33 |         promise.reject = Root.reject;
34 |         promise.all = Root.all;
35 |         if (typeof promise.resolve === 'function' &&
36 |             typeof promise.reject === 'function' &&
37 |             typeof promise.all === 'function') {
38 |             return promise;
39 |         }
40 |     }
41 | 
42 |     throw new TypeError('Invalid promise library specified.');
43 | }
44 | 
45 | function parsePromise(promiseLib) {
46 |     const result = {promiseLib};
47 |     if (promiseLib) {
48 |         result.promise = parse(promiseLib);
49 |     } else {
50 |         result.promise = parse(Promise);
51 |         result.promiseLib = Promise;
52 |     }
53 |     return result;
54 | }
55 | 
56 | module.exports = {parsePromise};
57 | 


--------------------------------------------------------------------------------
/lib/query-result.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | /**
11 |  * @enum {number}
12 |  * @alias queryResult
13 |  * @readonly
14 |  * @description
15 |  * **Query Result Mask**
16 |  *
17 |  * Binary mask that represents the number of rows expected from a query method,
18 |  * used by generic {@link Database#query query} method, plus {@link Database#func func}.
19 |  *
20 |  * The mask is always the last optional parameter, which defaults to `queryResult.any`.
21 |  *
22 |  * Any combination of flags is supported, except for `one + many`.
23 |  *
24 |  * The type is available from the library's root: `pgp.queryResult`.
25 |  *
26 |  * @see {@link Database#query Database.query}, {@link Database#func Database.func}
27 |  */
28 | const queryResult = {
29 |     /** Single row is expected, to be resolved as a single row-object. */
30 |     one: 1,
31 |     /** One or more rows expected, to be resolved as an array, with at least 1 row-object. */
32 |     many: 2,
33 |     /** Expecting no rows, to be resolved with `null`. */
34 |     none: 4,
35 |     /** `many|none` - any result is expected, to be resolved with an array of rows-objects. */
36 |     any: 6
37 | };
38 | 
39 | module.exports = {queryResult};
40 | 


--------------------------------------------------------------------------------
/lib/special-query.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const specialQueryType = {
11 |     result: 0,
12 |     multiResult: 1,
13 |     stream: 2
14 | };
15 | 
16 | class SpecialQuery {
17 |     constructor(type) {
18 |         this.isResult = type === specialQueryType.result; // type used implicitly
19 |         this.isStream = type === specialQueryType.stream;
20 |         this.isMultiResult = type === specialQueryType.multiResult;
21 |     }
22 | }
23 | 
24 | const cache = {
25 |     resultQuery: new SpecialQuery(specialQueryType.result),
26 |     multiResultQuery: new SpecialQuery(specialQueryType.multiResult),
27 |     streamQuery: new SpecialQuery(specialQueryType.stream)
28 | };
29 | 
30 | module.exports = Object.assign({SpecialQuery}, cache);
31 | 


--------------------------------------------------------------------------------
/lib/stream.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {Events} = require('./events');
 11 | 
 12 | const npm = {
 13 |     utils: require('./utils'),
 14 |     text: require('./text')
 15 | };
 16 | 
 17 | ////////////////////////////////////////////
 18 | // Streams query data into any destination,
 19 | // with the help of pg-query-stream library.
 20 | function $stream(ctx, qs, initCB, config) {
 21 | 
 22 |     const $p = config.promise;
 23 | 
 24 |     // istanbul ignore next:
 25 |     // we do not provide code coverage for the Native Bindings specifics
 26 |     if (ctx.options.pgNative) {
 27 |         return $p.reject(new Error(npm.text.nativeStreaming));
 28 |     }
 29 |     // Stream class was renamed again, see the following issue:
 30 |     // https://github.com/brianc/node-postgres/issues/2412
 31 |     if (!qs || !qs.constructor || qs.constructor.name !== 'QueryStream') {
 32 |         // invalid or missing stream object;
 33 |         return $p.reject(new TypeError(npm.text.invalidStream));
 34 |     }
 35 |     if (qs._reading || qs._closed) {
 36 |         // stream object is in the wrong state;
 37 |         return $p.reject(new Error(npm.text.invalidStreamState));
 38 |     }
 39 |     if (typeof initCB !== 'function') {
 40 |         // parameter `initCB` must be passed as the initialization callback;
 41 |         return $p.reject(new TypeError(npm.text.invalidStreamCB));
 42 |     }
 43 | 
 44 |     let error = Events.query(ctx.options, getContext());
 45 | 
 46 |     if (error) {
 47 |         error = getError(error);
 48 |         Events.error(ctx.options, error, getContext());
 49 |         return $p.reject(error);
 50 |     }
 51 | 
 52 |     const stream = ctx.db.client.query(qs);
 53 | 
 54 |     stream.on('data', onData);
 55 |     stream.on('error', onError);
 56 |     stream.on('end', onEnd);
 57 | 
 58 |     try {
 59 |         initCB.call(this, stream); // the stream must be initialized during the call;
 60 |     } catch (e) {
 61 |         release();
 62 |         error = getError(e);
 63 |         Events.error(ctx.options, error, getContext());
 64 |         return $p.reject(error);
 65 |     }
 66 | 
 67 |     const start = Date.now();
 68 |     let resolve, reject, nRows = 0;
 69 | 
 70 |     function onData(data) {
 71 |         nRows++;
 72 |         error = Events.receive(ctx.options, [data], undefined, getContext());
 73 |         if (error) {
 74 |             onError(error);
 75 |         }
 76 |     }
 77 | 
 78 |     function onError(e) {
 79 |         release();
 80 |         stream.destroy();
 81 |         e = getError(e);
 82 |         Events.error(ctx.options, e, getContext());
 83 |         reject(e);
 84 |     }
 85 | 
 86 |     function onEnd() {
 87 |         release();
 88 |         resolve({
 89 |             processed: nRows, // total number of rows processed;
 90 |             duration: Date.now() - start // duration, in milliseconds;
 91 |         });
 92 |     }
 93 | 
 94 |     function release() {
 95 |         stream.removeListener('data', onData);
 96 |         stream.removeListener('error', onError);
 97 |         stream.removeListener('end', onEnd);
 98 |     }
 99 | 
100 |     function getError(e) {
101 |         return e instanceof npm.utils.InternalError ? e.error : e;
102 |     }
103 | 
104 |     function getContext() {
105 |         let client;
106 |         if (ctx.db) {
107 |             client = ctx.db.client;
108 |         } else {
109 |             error = new Error(npm.text.looseQuery);
110 |         }
111 |         return {
112 |             client,
113 |             dc: ctx.dc,
114 |             query: qs.cursor.text,
115 |             params: qs.cursor.values,
116 |             ctx: ctx.ctx
117 |         };
118 |     }
119 | 
120 |     return $p((res, rej) => {
121 |         resolve = res;
122 |         reject = rej;
123 |     });
124 | 
125 | }
126 | 
127 | module.exports = $stream;
128 | 


--------------------------------------------------------------------------------
/lib/text.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | /* All error messages used in the module */
11 | 
12 | const streamVersion = require('../package.json')
13 |     .devDependencies['pg-query-stream'];
14 | 
15 | module.exports = {
16 |     nativeError: 'Failed to initialize Native Bindings.',
17 | 
18 |     /* Database errors */
19 |     queryDisconnected: 'Cannot execute a query on a disconnected client.',
20 |     invalidQuery: 'Invalid query format.',
21 |     invalidFunction: 'Invalid function name.',
22 |     invalidProc: 'Invalid procedure name.',
23 |     invalidMask: 'Invalid Query Result Mask specified.',
24 |     looseQuery: 'Querying against a released or lost connection.',
25 | 
26 |     /* result errors */
27 |     notEmpty: 'No return data was expected.',
28 |     noData: 'No data returned from the query.',
29 |     multiple: 'Multiple rows were not expected.',
30 | 
31 |     /* streaming support */
32 |     nativeStreaming: 'Streaming doesn\'t work with Native Bindings.',
33 |     invalidStream: `Invalid or missing stream object: pg-query-stream >= v${streamVersion} was expected`,
34 |     invalidStreamState: 'Invalid stream state.',
35 |     invalidStreamCB: 'Invalid or missing stream initialization callback.',
36 | 
37 |     /* connection errors */
38 |     poolDestroyed: 'Connection pool of the database object has been destroyed.',
39 |     clientEnd: 'Abnormal client.end() call, due to invalid code or failed server connection.'
40 | };
41 | 


--------------------------------------------------------------------------------
/lib/tx-mode.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2015-present, Vitaly Tomilov
  3 |  *
  4 |  * See the LICENSE file at the top-level directory of this distribution
  5 |  * for licensing information.
  6 |  *
  7 |  * Removal or modification of this copyright notice is prohibited.
  8 |  */
  9 | 
 10 | const {InnerState} = require('./inner-state');
 11 | const {addInspection} = require('./utils');
 12 | const {assert} = require('./assert');
 13 | 
 14 | /**
 15 |  * @enum {number}
 16 |  * @alias txMode.isolationLevel
 17 |  * @readonly
 18 |  * @summary Transaction Isolation Level.
 19 |  * @description
 20 |  * The type is available from the {@link txMode} namespace.
 21 |  *
 22 |  * @see $[Transaction Isolation]
 23 |  */
 24 | const isolationLevel = {
 25 |     /** Isolation level not specified. */
 26 |     none: 0,
 27 | 
 28 |     /** ISOLATION LEVEL SERIALIZABLE */
 29 |     serializable: 1,
 30 | 
 31 |     /** ISOLATION LEVEL REPEATABLE READ */
 32 |     repeatableRead: 2,
 33 | 
 34 |     /** ISOLATION LEVEL READ COMMITTED */
 35 |     readCommitted: 3
 36 | 
 37 |     // From the official documentation: http://www.postgresql.org/docs/9.5/static/sql-set-transaction.html
 38 |     // The SQL standard defines one additional level, READ UNCOMMITTED. In PostgreSQL READ UNCOMMITTED is treated as READ COMMITTED.
 39 |     // => skipping `READ UNCOMMITTED`.
 40 | };
 41 | 
 42 | /**
 43 |  * @class txMode.TransactionMode
 44 |  * @description
 45 |  * Constructs a complete transaction-opening `BEGIN` command, from these options:
 46 |  *  - isolation level
 47 |  *  - access mode
 48 |  *  - deferrable mode
 49 |  *
 50 |  * The type is available from the {@link txMode} namespace.
 51 |  *
 52 |  * @param {} [options]
 53 |  * Transaction Mode options.
 54 |  *
 55 |  * @param {txMode.isolationLevel} [options.tiLevel]
 56 |  * Transaction Isolation Level.
 57 |  *
 58 |  * @param {boolean} [options.readOnly]
 59 |  * Sets transaction access mode based on the read-only flag:
 60 |  *  - `undefined` - access mode not specified (default)
 61 |  *  - `true` - access mode is set to `READ ONLY`
 62 |  *  - `false` - access mode is set to `READ WRITE`
 63 |  *
 64 |  * @param {boolean} [options.deferrable]
 65 |  * Sets transaction deferrable mode based on the boolean value:
 66 |  *  - `undefined` - deferrable mode not specified (default)
 67 |  *  - `true` - mode is set to `DEFERRABLE`
 68 |  *  - `false` - mode is set to `NOT DEFERRABLE`
 69 |  *
 70 |  * It is used only when `tiLevel`=`isolationLevel.serializable`
 71 |  * and `readOnly`=`true`, or else it is ignored.
 72 |  *
 73 |  * @returns {txMode.TransactionMode}
 74 |  *
 75 |  * @see $[BEGIN], {@link txMode.isolationLevel}
 76 |  *
 77 |  * @example
 78 |  *
 79 |  * const {TransactionMode, isolationLevel} = pgp.txMode;
 80 |  *
 81 |  * // Create a reusable transaction mode (serializable + read-only + deferrable):
 82 |  * const mode = new TransactionMode({
 83 |  *     tiLevel: isolationLevel.serializable,
 84 |  *     readOnly: true,
 85 |  *     deferrable: true
 86 |  * });
 87 |  *
 88 |  * db.tx({mode}, t => {
 89 |  *     return t.any('SELECT * FROM table');
 90 |  * })
 91 |  *     .then(data => {
 92 |  *         // success;
 93 |  *     })
 94 |  *     .catch(error => {
 95 |  *         // error
 96 |  *     });
 97 |  *
 98 |  * // Instead of the default BEGIN, such transaction will start with:
 99 |  *
100 |  * // BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE
101 |  *
102 |  */
103 | class TransactionMode extends InnerState {
104 | 
105 |     constructor(options) {
106 |         options = assert(options, ['tiLevel', 'deferrable', 'readOnly']);
107 |         const {readOnly, deferrable} = options;
108 |         let {tiLevel} = options;
109 |         let level, accessMode, deferrableMode, begin = 'begin';
110 |         tiLevel = (tiLevel > 0) ? parseInt(tiLevel) : 0;
111 | 
112 |         if (tiLevel > 0 && tiLevel < 4) {
113 |             const values = ['serializable', 'repeatable read', 'read committed'];
114 |             level = 'isolation level ' + values[tiLevel - 1];
115 |         }
116 |         if (readOnly) {
117 |             accessMode = 'read only';
118 |         } else {
119 |             if (readOnly !== undefined) {
120 |                 accessMode = 'read write';
121 |             }
122 |         }
123 |         // From the official documentation: http://www.postgresql.org/docs/9.5/static/sql-set-transaction.html
124 |         // The DEFERRABLE transaction property has no effect unless the transaction is also SERIALIZABLE and READ ONLY
125 |         if (tiLevel === isolationLevel.serializable && readOnly) {
126 |             if (deferrable) {
127 |                 deferrableMode = 'deferrable';
128 |             } else {
129 |                 if (deferrable !== undefined) {
130 |                     deferrableMode = 'not deferrable';
131 |                 }
132 |             }
133 |         }
134 |         if (level) {
135 |             begin += ' ' + level;
136 |         }
137 |         if (accessMode) {
138 |             begin += ' ' + accessMode;
139 |         }
140 |         if (deferrableMode) {
141 |             begin += ' ' + deferrableMode;
142 |         }
143 | 
144 |         super({begin, capBegin: begin.toUpperCase()});
145 |     }
146 | 
147 |     /**
148 |      * @method txMode.TransactionMode#begin
149 |      * @description
150 |      * Returns a complete BEGIN statement, according to all the parameters passed into the class.
151 |      *
152 |      * This method is primarily for internal use by the library.
153 |      *
154 |      * @param {boolean} [cap=false]
155 |      * Indicates whether the returned SQL must be capitalized.
156 |      *
157 |      * @returns {string}
158 |      */
159 |     begin(cap) {
160 |         return cap ? this._inner.capBegin : this._inner.begin;
161 |     }
162 | }
163 | 
164 | addInspection(TransactionMode, function () {
165 |     return this.begin(true);
166 | });
167 | 
168 | /**
169 |  * @namespace txMode
170 |  * @description
171 |  * Transaction Mode namespace, available as `pgp.txMode`, before and after initializing the library.
172 |  *
173 |  * Extends the default `BEGIN` with Transaction Mode parameters:
174 |  *  - isolation level
175 |  *  - access mode
176 |  *  - deferrable mode
177 |  *
178 |  * @property {function} TransactionMode
179 |  * {@link txMode.TransactionMode TransactionMode} class constructor.
180 |  *
181 |  * @property {txMode.isolationLevel} isolationLevel
182 |  * Transaction Isolation Level enumerator
183 |  *
184 |  * @see $[BEGIN]
185 |  */
186 | module.exports = {
187 |     isolationLevel,
188 |     TransactionMode
189 | };
190 | 
191 | 


--------------------------------------------------------------------------------
/lib/types/index.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2015-present, Vitaly Tomilov
 3 |  *
 4 |  * See the LICENSE file at the top-level directory of this distribution
 5 |  * for licensing information.
 6 |  *
 7 |  * Removal or modification of this copyright notice is prohibited.
 8 |  */
 9 | 
10 | const {ServerFormatting} = require('./server-formatting');
11 | const {PreparedStatement} = require('./prepared-statement');
12 | const {ParameterizedQuery} = require('./parameterized-query');
13 | 
14 | module.exports = {
15 |     ServerFormatting,
16 |     PreparedStatement,
17 |     ParameterizedQuery
18 | };
19 | 


--------------------------------------------------------------------------------
/lib/types/server-formatting.js:
--------------------------------------------------------------------------------
 1 | const {InnerState} = require('../inner-state');
 2 | const {addInspection} = require('../utils');
 3 | const utils = require('../utils');
 4 | 
 5 | /**
 6 |  * @private
 7 |  * @class ServerFormatting
 8 |  */
 9 | class ServerFormatting extends InnerState {
10 | 
11 |     constructor(options) {
12 |         const _inner = {
13 |             options,
14 |             changed: true,
15 |             currentError: undefined,
16 |             target: {}
17 |         };
18 |         super(_inner);
19 |         setValues.call(this, options.values);
20 |     }
21 | 
22 |     get error() {
23 |         return this._inner.currentError;
24 |     }
25 | 
26 |     get text() {
27 |         return this._inner.options.text;
28 |     }
29 | 
30 |     set text(value) {
31 |         const _i = this._inner;
32 |         if (value !== _i.options.text) {
33 |             _i.options.text = value;
34 |             _i.changed = true;
35 |         }
36 |     }
37 | 
38 |     get binary() {
39 |         return this._inner.options.binary;
40 |     }
41 | 
42 |     set binary(value) {
43 |         const _i = this._inner;
44 |         if (value !== _i.options.binary) {
45 |             _i.options.binary = value;
46 |             _i.changed = true;
47 |         }
48 |     }
49 | 
50 |     get rowMode() {
51 |         return this._inner.options.rowMode;
52 |     }
53 | 
54 |     set rowMode(value) {
55 |         const _i = this._inner;
56 |         if (value !== _i.options.rowMode) {
57 |             _i.options.rowMode = value;
58 |             _i.changed = true;
59 |         }
60 |     }
61 | 
62 |     get values() {
63 |         return this._inner.target.values;
64 |     }
65 | 
66 |     set values(values) {
67 |         setValues.call(this, values);
68 |     }
69 | 
70 | }
71 | 
72 | /**
73 |  * @member ServerFormatting#parse
74 |  */
75 | 
76 | function setValues(v) {
77 |     const target = this._inner.target;
78 |     if (Array.isArray(v)) {
79 |         if (v.length) {
80 |             target.values = v;
81 |         } else {
82 |             delete target.values;
83 |         }
84 |     } else {
85 |         if (utils.isNull(v)) {
86 |             delete target.values;
87 |         } else {
88 |             target.values = [v];
89 |         }
90 |     }
91 | }
92 | 
93 | addInspection(ServerFormatting, function () {
94 |     return this.toString();
95 | });
96 | 
97 | module.exports = {ServerFormatting};
98 | 


--------------------------------------------------------------------------------
/lib/utils/README.md:
--------------------------------------------------------------------------------
 1 | ### `utils` namespace
 2 | 
 3 | This folder contains everything that's available via the [utils] namespace, before and after initialization:
 4 | 
 5 | ```js
 6 | const pgpLib = require('pg-promise');
 7 | const pgp = pgpLib(/*initialization options*/);
 8 | 
 9 | pgpLib.utils; // `utils` namespace
10 | pgp.utils; // `utils` namespace
11 | ```
12 | 
13 | [utils]:http://vitaly-t.github.io/pg-promise/utils.html
14 | 


--------------------------------------------------------------------------------
/lib/utils/color.js:
--------------------------------------------------------------------------------
 1 | const util = require('util');
 2 | 
 3 | class ColorConsole {
 4 | 
 5 |     static log() {
 6 |         ColorConsole.writeNormal([...arguments], 39); // white
 7 |     }
 8 | 
 9 |     static info() {
10 |         ColorConsole.writeNormal([...arguments], 36); // cyan
11 |     }
12 | 
13 |     static success() {
14 |         ColorConsole.writeNormal([...arguments], 32); // green
15 |     }
16 | 
17 |     static warn() {
18 |         ColorConsole.writeNormal([...arguments], 33); // yellow
19 |     }
20 | 
21 |     static error() {
22 |         ColorConsole.writeError([...arguments], 31); // red
23 |     }
24 | 
25 |     static writeNormal(params, color) {
26 |         // istanbul ignore else
27 |         if (process.stdout.isTTY) {
28 |             console.log.apply(null, ColorConsole.formatColor(params, color)); // eslint-disable-line no-console
29 |         } else {
30 |             console.log.apply(null, params); // eslint-disable-line no-console
31 |         }
32 |     }
33 | 
34 |     static writeError(params, color) {
35 |         // istanbul ignore else
36 |         if (process.stderr.isTTY) {
37 |             console.error.apply(null, ColorConsole.formatColor(params, color)); // eslint-disable-line no-console
38 |         } else {
39 |             console.error.apply(null, params); // eslint-disable-line no-console
40 |         }
41 |     }
42 | 
43 |     static formatColor(args, color) {
44 |         return args.map(a => `\x1b[${color}m${util.format(a)}\x1b[0m`);
45 |     }
46 | }
47 | 
48 | ColorConsole.log.bright = function () {
49 |     ColorConsole.writeNormal([...arguments], 97); // light white
50 | };
51 | 
52 | ColorConsole.info.bright = function () {
53 |     ColorConsole.writeNormal([...arguments], 93); // light cyan
54 | };
55 | 
56 | ColorConsole.success.bright = function () {
57 |     ColorConsole.writeNormal([...arguments], 92); // light green
58 | };
59 | 
60 | ColorConsole.warn.bright = function () {
61 |     ColorConsole.writeNormal([...arguments], 93); // light yellow
62 | };
63 | 
64 | ColorConsole.error.bright = function () {
65 |     ColorConsole.writeError([...arguments], 91); // light red
66 | };
67 | 
68 | module.exports = {ColorConsole};
69 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "pg-promise",
 3 |   "version": "11.15.0",
 4 |   "description": "PostgreSQL interface for Node.js",
 5 |   "main": "lib/index.js",
 6 |   "typings": "typescript/pg-promise.d.ts",
 7 |   "scripts": {
 8 |     "spelling": "cspell --config=.cspell.json \"**/*.{md,ts,js}\" --no-progress",
 9 |     "coverage": "istanbul cover ./node_modules/jasmine-node/bin/jasmine-node --captureExceptions test",
10 |     "doc": "jsdoc -c ./jsdoc/jsdoc.js ./jsdoc/README.md -t ./jsdoc/templates/custom",
11 |     "lint": "eslint ./lib ./test/*.js ./test/db --fix",
12 |     "test": "jasmine-node --captureExceptions test",
13 |     "test:init": "node test/db/init.js",
14 |     "test:native": "jasmine-node test --config PG_NATIVE true",
15 |     "tslint": "tslint ./typescript/*.ts"
16 |   },
17 |   "files": [
18 |     "lib",
19 |     "typescript"
20 |   ],
21 |   "homepage": "https://github.com/vitaly-t/pg-promise",
22 |   "repository": {
23 |     "type": "git",
24 |     "url": "https://github.com/vitaly-t/pg-promise.git"
25 |   },
26 |   "bugs": {
27 |     "url": "https://github.com/vitaly-t/pg-promise/issues",
28 |     "email": "vitaly.tomilov@gmail.com"
29 |   },
30 |   "keywords": [
31 |     "pg",
32 |     "promise",
33 |     "postgres"
34 |   ],
35 |   "author": {
36 |     "name": "Vitaly Tomilov",
37 |     "email": "vitaly.tomilov@gmail.com"
38 |   },
39 |   "license": "MIT",
40 |   "engines": {
41 |     "node": ">=16.0"
42 |   },
43 |   "dependencies": {
44 |     "assert-options": "0.8.3",
45 |     "pg": "8.16.3",
46 |     "pg-minify": "1.8.0",
47 |     "spex": "3.4.1"
48 |   },
49 |   "peerDependencies": {
50 |     "pg-query-stream": "4.10.3"
51 |   },
52 |   "devDependencies": {
53 |     "@eslint/js": "9.30.1",
54 |     "@types/node": "24.0.10",
55 |     "bluebird": "3.7.2",
56 |     "coveralls": "3.1.1",
57 |     "cspell": "9.1.3",
58 |     "eslint": "9.30.1",
59 |     "globals": "16.3.0",
60 |     "istanbul": "0.4.5",
61 |     "jasmine-node": "3.0.0",
62 |     "jsdoc": "4.0.4",
63 |     "JSONStream": "1.3.5",
64 |     "tslint": "6.1.3",
65 |     "typescript": "5.8.3"
66 |   }
67 | }
68 | 


--------------------------------------------------------------------------------
/test/adapter.spec.js:
--------------------------------------------------------------------------------
 1 | const pgp = require('../lib/index');
 2 | const {PromiseAdapter} = pgp;
 3 | 
 4 | const dummy = () => {
 5 | };
 6 | 
 7 | describe('Adapter', () => {
 8 | 
 9 |     describe('with invalid parameters', () => {
10 |         const error = 'Adapter requires an api configuration object.';
11 |         it('must throw an error', () => {
12 |             expect(() => {
13 |                 new PromiseAdapter();
14 |             }).toThrow(error);
15 |             expect(() => {
16 |                 new PromiseAdapter(null);
17 |             }).toThrow(error);
18 |             expect(() => {
19 |                 new PromiseAdapter(123);
20 |             }).toThrow(error);
21 |             expect(() => {
22 |                 new PromiseAdapter('test');
23 |             }).toThrow(error);
24 |         });
25 |     });
26 | 
27 |     describe('with invalid \'create\'', () => {
28 |         it('must throw an error', () => {
29 |             expect(() => {
30 |                 new PromiseAdapter({});
31 |             }).toThrow('Function \'create\' must be specified.');
32 |         });
33 |     });
34 | 
35 |     describe('with invalid \'resolve\'', () => {
36 |         it('must throw an error', () => {
37 |             expect(() => {
38 |                 new PromiseAdapter({create: dummy});
39 |             }).toThrow('Function \'resolve\' must be specified.');
40 |         });
41 |     });
42 | 
43 |     describe('with invalid \'reject\'', () => {
44 |         it('must throw an error', () => {
45 |             expect(() => {
46 |                 new PromiseAdapter({create: dummy, resolve: dummy});
47 |             }).toThrow('Function \'reject\' must be specified.');
48 |         });
49 |     });
50 | 
51 |     describe('with invalid \'all\'', () => {
52 |         it('must throw an error', () => {
53 |             expect(() => {
54 |                 new PromiseAdapter({create: dummy, resolve: dummy, reject: dummy});
55 |             }).toThrow('Function \'all\' must be specified.');
56 |         });
57 |     });
58 | 
59 |     describe('with all valid parameters', () => {
60 |         it('must be successful', () => {
61 |             const adapter = new PromiseAdapter({create: dummy, resolve: dummy, reject: dummy, all: dummy});
62 |             expect(adapter instanceof PromiseAdapter).toBe(true);
63 |         });
64 |     });
65 | 
66 | });
67 | 


--------------------------------------------------------------------------------
/test/color.spec.js:
--------------------------------------------------------------------------------
 1 | const {ColorConsole} = require('../lib/utils/color');
 2 | 
 3 | describe('protocol', () => {
 4 |     it('must have the right signature', () => {
 5 |         expect(typeof ColorConsole).toBe('function');
 6 |         expect(typeof ColorConsole.log).toBe('function');
 7 |         expect(typeof ColorConsole.log.bright).toBe('function');
 8 |         expect(typeof ColorConsole.info).toBe('function');
 9 |         expect(typeof ColorConsole.info.bright).toBe('function');
10 |         expect(typeof ColorConsole.warn).toBe('function');
11 |         expect(typeof ColorConsole.warn.bright).toBe('function');
12 |         expect(typeof ColorConsole.error).toBe('function');
13 |         expect(typeof ColorConsole.error.bright).toBe('function');
14 |         expect(typeof ColorConsole.success).toBe('function');
15 |         expect(typeof ColorConsole.success.bright).toBe('function');
16 |     });
17 | });
18 | 
19 | describe('text', () => {
20 |     it('must match', () => {
21 |         expect(invoke(ColorConsole.log, 'log')).toEqual(['log']);
22 |         expect(invoke(ColorConsole.log.bright, ['one', 'two'])).toEqual(['one', 'two']);
23 |         expect(invoke(ColorConsole.info, 'info')).toEqual(['info']);
24 |         expect(invoke(ColorConsole.info.bright, ['one', 'two'])).toEqual(['one', 'two']);
25 |         expect(invoke(ColorConsole.warn, 'warning')).toEqual(['warning']);
26 |         expect(invoke(ColorConsole.warn.bright, ['one', 'two'])).toEqual(['one', 'two']);
27 |         expect(invoke(ColorConsole.success, 'success')).toEqual(['success']);
28 |         expect(invoke(ColorConsole.success.bright, ['one', 'two'])).toEqual(['one', 'two']);
29 |         expect(invoke(ColorConsole.error, 'error', true)).toEqual(['error']);
30 |         expect(invoke(ColorConsole.error.bright, ['one', 'two'], true)).toEqual(['one', 'two']);
31 |     });
32 | 
33 |     function invoke(method, text, isErr) {
34 |         text = Array.isArray(text) ? text : [text];
35 |         const name = isErr ? 'error' : 'log';
36 |         const old = console[name]; // eslint-disable-line no-console
37 |         let res;
38 |         console[name] = function () { // eslint-disable-line no-console
39 |             res = [...arguments].map(removeColors);
40 |         };
41 |         method.apply(null, text);
42 |         console[name] = old; // eslint-disable-line no-console
43 |         return res;
44 |     }
45 | });
46 | 
47 | function removeColors(text) {
48 |     /*eslint no-control-regex: 0*/
49 |     return text.replace(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/g, '');
50 | }
51 | 


--------------------------------------------------------------------------------
/test/db/capture.js:
--------------------------------------------------------------------------------
 1 | function hookConsole(callback) {
 2 | 
 3 |     const stdout = process.stdout,
 4 |         stderr = process.stderr,
 5 |         oldOutWrite = stdout.write,
 6 |         oldErrWrite = stderr.write;
 7 | 
 8 |     stdout.write = (() => {
 9 |         return string => {
10 |             callback(string);
11 |         };
12 |     })(stdout.write);
13 | 
14 |     stderr.write = (() => {
15 |         return string => {
16 |             callback(string);
17 |         };
18 |     })(stderr.write);
19 | 
20 |     return () => {
21 |         stdout.write = oldOutWrite;
22 |         stderr.write = oldErrWrite;
23 |     };
24 | }
25 | 
26 | // removes color elements from text;
27 | function removeColors(text) {
28 |     return text.replace(/\\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/g, '');
29 | }
30 | 
31 | function capture() {
32 |     let text = '';
33 |     const hook = hookConsole(s => {
34 |         if (!text) {
35 |             text = s;
36 |         }
37 |     });
38 |     return () => {
39 |         hook();
40 |         return removeColors(text);
41 |     };
42 | }
43 | 
44 | module.exports = capture;
45 | 


--------------------------------------------------------------------------------
/test/db/header.js:
--------------------------------------------------------------------------------
 1 | //////////////////////////////////////////////////
 2 | // Database connection header used in every test;
 3 | //////////////////////////////////////////////////
 4 | 
 5 | const pgpLib = require('../../lib/index');
 6 | const defPromise = require('bluebird'); // default promise library;
 7 | 
 8 | defPromise.config({
 9 |     warnings: false
10 | });
11 | 
12 | // Either match your local database configuration according to the details below,
13 | // or the other way round - change the details to match your local configuration.
14 | const cn = {
15 |     allowExitOnIdle: true,
16 |     host: process.env.POSTGRES_HOST || 'localhost', // server name or IP address;
17 |     port: 5432, // default port;
18 |     database: process.env.POSTGRES_DB || 'pg_promise_test', // local database name for testing;
19 |     user: process.env.POSTGRES_USER || 'postgres', // username;
20 |     password: process.env.POSTGRES_PASSWORD || 'postgres' //- add password, if needed;
21 | };
22 | pgpLib.suppressErrors = true; // suppress console output for error messages;
23 | 
24 | function main(options, dc) {
25 |     const pgNative = eval(process.env.PG_NATIVE);
26 |     if (pgNative) {
27 |         if (options && typeof options === 'object') {
28 |             if (!('pgNative' in options)) {
29 |                 options.pgNative = true;
30 |             }
31 |         } else {
32 |             if (!options) {
33 |                 options = {
34 |                     pgNative: true
35 |                 };
36 |             }
37 |         }
38 |     }
39 |     const result = {
40 |         pgpLib, cn,
41 |         pgp: pgpLib(options)
42 |     };
43 | 
44 |     result.db = result.pgp(cn, dc);
45 |     return result;
46 | }
47 | 
48 | main.defPromise = defPromise;
49 | 
50 | module.exports = main;
51 | 


--------------------------------------------------------------------------------
/test/db/init.js:
--------------------------------------------------------------------------------
 1 | ////////////////////////////////////////////////
 2 | // Initialization scripts for the test database;
 3 | ////////////////////////////////////////////////
 4 | 
 5 | const dbHeader = require('./header');
 6 | const promise = dbHeader.defPromise;
 7 | const {ColorConsole} = require('../../lib/utils/color');
 8 | 
 9 | const header = dbHeader({
10 |     query(e) {
11 |         ColorConsole.info(e.query); // print all executed queries;
12 |     },
13 |     promiseLib: promise,
14 |     capSQL: true
15 | });
16 | 
17 | const {db} = header;
18 | 
19 | async function getPgVersion() {
20 |     const c = await db.connect();
21 |     c.done(); // success, release connection
22 |     return c.client.serverVersion;
23 | }
24 | 
25 | (async function () {
26 | 
27 |     const pgHighVersion = parseInt((await getPgVersion()).split('.')[0]);
28 | 
29 |     try {
30 |         await db.tx(`Init PG v${pgHighVersion}`, async t => {
31 | 
32 |             // drop all functions;
33 |             await t.none('DROP FUNCTION IF EXISTS "findUser"(int)');
34 |             await t.none('DROP FUNCTION IF EXISTS get_users()');
35 | 
36 |             // drop all tables;
37 |             await t.none('DROP TABLE IF EXISTS audit');
38 |             await t.none('DROP TABLE IF EXISTS person');
39 |             await t.none('DROP TABLE IF EXISTS users');
40 |             await t.none('DROP TABLE IF EXISTS images');
41 | 
42 |             // create all tables;
43 |             await t.none('CREATE TABLE audit(id serial, event text, created timestamptz, ref int)');
44 |             await t.none('CREATE TABLE person(id serial, name text, dob date)');
45 |             await t.none('CREATE TABLE users(id serial, login text, active boolean)');
46 |             await t.none('CREATE TABLE images(id serial, name text, data bytea)');
47 | 
48 |             // insert records into 'users';
49 |             await t.none('INSERT INTO users(login, active) VALUES($1, $2)', ['user-1', true]);
50 |             await t.none('INSERT INTO users(login, active) VALUES($1, $2)', ['user-2', true]);
51 |             await t.none('INSERT INTO users(login, active) VALUES($1, $2)', ['user-3', false]);
52 |             await t.none('INSERT INTO users(login, active) VALUES($1, $2)', ['user-4', false]);
53 | 
54 |             // insert records into 'person';
55 |             await t.none('INSERT INTO person(name, dob) VALUES($1, $2)', ['David', new Date(1995, 8, 7)]);
56 |             await t.none('INSERT INTO person(name, dob) VALUES($1, $2)', ['John', new Date(1980, 3, 20)]);
57 |             await t.none('INSERT INTO person(name, dob) VALUES($1, $2)', ['Mark', new Date(1973, 5, 12)]);
58 |             await t.none('INSERT INTO person(name, dob) VALUES($1, $2)', ['Peter', new Date(1992, 11, 3)]);
59 | 
60 |             // adding functions:
61 |             await t.none('CREATE OR REPLACE FUNCTION "findUser"(userId int) RETURNS SETOF users AS $ SELECT * FROM users WHERE id = userId $ language \'sql\'');
62 |             await t.none('CREATE OR REPLACE FUNCTION get_users() RETURNS SETOF users AS $ SELECT * FROM users $ language \'sql\'');
63 | 
64 |             // adding procedures:
65 |             if (pgHighVersion >= 11) {
66 |                 // Postgresql v10 and earlier do not support procedures
67 |                 await t.none('CREATE OR REPLACE PROCEDURE empty_proc() LANGUAGE SQL AS $ $;');
68 |                 await t.none(`CREATE OR REPLACE PROCEDURE output_proc(INOUT output1 boolean, INOUT output2 text)
69 |                             LANGUAGE plpgsql AS $
70 |                             BEGIN
71 |                                 output1 := true;
72 |                                 output2 := concat(output2, '-hello!');
73 |                             END;$;`);
74 |             }
75 |         });
76 |         ColorConsole.success.bright('*** SUCCESS ***');
77 |     } catch (err) {
78 |         ColorConsole.error.bright('FAILED:', err);
79 |     }
80 | }());
81 | 


--------------------------------------------------------------------------------
/test/db/tools.js:
--------------------------------------------------------------------------------
 1 | const util = require('util');
 2 | 
 3 | function inspect(obj) {
 4 |     return obj[util.inspect.custom]();
 5 | }
 6 | 
 7 | module.exports = {
 8 |     inspect
 9 | };
10 | 


--------------------------------------------------------------------------------
/test/entry.spec.js:
--------------------------------------------------------------------------------
  1 | const {PromiseAdapter} = require('../lib/index');
  2 | const supportsPromise = typeof Promise !== 'undefined';
  3 | 
  4 | const header = require('./db/header');
  5 | const promise = header.defPromise;
  6 | const options = {
  7 |     promiseLib: promise,
  8 |     noWarnings: true
  9 | };
 10 | const dbHeader = header(options);
 11 | const pgp = dbHeader.pgp;
 12 | const db = dbHeader.db;
 13 | 
 14 | const BatchError = pgp.spex.errors.BatchError;
 15 | 
 16 | function dummy() {
 17 | }
 18 | 
 19 | describe('Library entry function', () => {
 20 | 
 21 |     describe('without any promise override', () => {
 22 |         it('must return a valid library object', () => {
 23 |             if (supportsPromise) {
 24 |                 const lib = header({noWarnings: true});
 25 |                 expect(typeof lib.pgp).toBe('function');
 26 |             } else {
 27 |                 expect(() => {
 28 |                     header();
 29 |                 }).toThrow('Promise library must be specified.');
 30 |             }
 31 |         });
 32 |     });
 33 | 
 34 |     describe('with PromiseAdapter override', () => {
 35 |         const P = header.defPromise;
 36 | 
 37 |         function create(func) {
 38 |             return new P(func);
 39 |         }
 40 | 
 41 |         function resolve(data) {
 42 |             return P.resolve(data);
 43 |         }
 44 | 
 45 |         function reject(reason) {
 46 |             return P.reject(reason);
 47 |         }
 48 | 
 49 |         function all(data) {
 50 |             return P.all(data);
 51 |         }
 52 | 
 53 |         const adapter = new PromiseAdapter({create, resolve, reject, all});
 54 |         it('must accept custom promise', () => {
 55 |             const lib = header({
 56 |                 promiseLib: adapter,
 57 |                 noWarnings: true
 58 |             });
 59 |             expect(lib.pgp instanceof Function).toBe(true);
 60 |         });
 61 | 
 62 |         describe('using PromiseAdapter', () => {
 63 |             let result;
 64 |             beforeEach(done => {
 65 |                 const lib = header({
 66 |                     promiseLib: adapter,
 67 |                     noWarnings: true
 68 |                 });
 69 |                 lib.db.one('select 1 as value')
 70 |                     .then(data => {
 71 |                         result = data;
 72 |                     })
 73 |                     .finally(done);
 74 |             });
 75 |             it('must return successfully', () => {
 76 |                 expect(result.value).toBe(1);
 77 |             });
 78 |         });
 79 |     });
 80 | 
 81 |     if (supportsPromise) {
 82 |         describe('without any options', () => {
 83 |             let result;
 84 |             beforeEach(done => {
 85 |                 const db1 = header({noWarnings: true, promiseLib: promise}).db;
 86 |                 db1.query('select * from users')
 87 |                     .then(data => {
 88 |                         result = data;
 89 |                     })
 90 |                     .finally(done);
 91 |             });
 92 |             it('must be able to execute queries', () => {
 93 |                 expect(Array.isArray(result)).toBe(true);
 94 |             });
 95 |         });
 96 |     }
 97 | 
 98 |     describe('with a valid promise library-object override', () => {
 99 |         it('must return a valid library object', () => {
100 |             const lib = header(
101 |                 {
102 |                     promiseLib: {
103 |                         resolve: dummy,
104 |                         reject: dummy,
105 |                         all: dummy
106 |                     },
107 |                     noWarnings: true
108 |                 });
109 |             expect(typeof lib.pgp).toBe('function');
110 |         });
111 |     });
112 | 
113 |     describe('with a valid promise library-function override', () => {
114 |         it('must return a valid library object', () => {
115 |             function fakePromiseLib() {
116 |             }
117 | 
118 |             fakePromiseLib.resolve = dummy;
119 |             fakePromiseLib.reject = dummy;
120 |             fakePromiseLib.all = dummy;
121 |             const lib = header({
122 |                 promiseLib: fakePromiseLib,
123 |                 noWarnings: true
124 |             });
125 |             expect(typeof lib.pgp).toBe('function');
126 |         });
127 |     });
128 | 
129 |     describe('with invalid promise override', () => {
130 |         const error = 'Invalid promise library specified.';
131 |         it('must throw the correct error', () => {
132 |             expect(() => {
133 |                 header({
134 |                     promiseLib: 'test'
135 |                 });
136 |             })
137 |                 .toThrow(error);
138 |             expect(() => {
139 |                 header({
140 |                     promiseLib: dummy
141 |                 });
142 |             })
143 |                 .toThrow(error);
144 |         });
145 |     });
146 | 
147 |     describe('with invalid options parameter', () => {
148 |         const errBody = 'Invalid "options" parameter: ';
149 |         it('must throw an error', () => {
150 |             expect(() => {
151 |                 header(123);
152 |             }).toThrow(errBody + '123');
153 |             expect(() => {
154 |                 header('hello');
155 |             }).toThrow(errBody + '"hello"');
156 |         });
157 |     });
158 | 
159 |     describe('multi-init', () => {
160 | 
161 |         const PromiseOne = {
162 |             create: cb => new promise.Promise(cb),
163 |             resolve: data => promise.resolve(data),
164 |             reject: () => promise.reject('reject-one'),
165 |             all: data => promise.all(data)
166 |         };
167 | 
168 |         const PromiseTwo = {
169 |             create: cb => new promise.Promise(cb),
170 |             resolve: data => promise.resolve(data),
171 |             reject: () => promise.reject('reject-two'),
172 |             all: data => promise.all(data)
173 |         };
174 | 
175 |         const one = new PromiseAdapter(PromiseOne);
176 |         const two = new PromiseAdapter(PromiseTwo);
177 |         let result;
178 | 
179 |         beforeEach(done => {
180 |             const pg1 = header({promiseLib: one, noWarnings: true}), db1 = pg1.db;
181 |             const pg2 = header({promiseLib: two, noWarnings: true}), db2 = pg2.db;
182 |             db.task(t => {
183 |                 return t.batch([
184 |                     db1.query('select $1', []), db2.query('select $1', [])
185 |                 ]);
186 |             })
187 |                 .catch(error => {
188 |                     result = error;
189 |                 })
190 |                 .finally(done);
191 |         });
192 | 
193 |         it('must be supported', () => {
194 |             expect(result instanceof BatchError).toBe(true);
195 |             expect(result.data).toEqual([
196 |                 {
197 |                     success: false,
198 |                     result: 'reject-one'
199 |                 },
200 |                 {
201 |                     success: false,
202 |                     result: 'reject-two'
203 |                 }
204 |             ]);
205 |         });
206 |     });
207 | 
208 |     describe('Taking no initialization options', () => {
209 |         it('must be supported', () => {
210 |             expect(typeof dbHeader.pgpLib()).toBe('function');
211 |         });
212 |     });
213 | });
214 | 


--------------------------------------------------------------------------------
/test/generator.spec.js:
--------------------------------------------------------------------------------
 1 | const header = require('./db/header');
 2 | const promise = header.defPromise;
 3 | 
 4 | const options = {
 5 |     noWarnings: true,
 6 |     promiseLib: promise
 7 | };
 8 | 
 9 | const dbHeader = header(options);
10 | const db = dbHeader.db;
11 | 
12 | describe('ES6 Generators', () => {
13 | 
14 |     // v9.0 dropped all generators support, and now it throws an error,
15 |     // if someone still tries to use them.
16 | 
17 |     const errMsg = 'ES6 generator functions are no longer supported!';
18 | 
19 |     describe('for tasks', () => {
20 |         let error;
21 |         beforeEach(done => {
22 |             db.task(function* () {
23 |             })
24 |                 .catch(e => {
25 |                     error = e;
26 |                 })
27 |                 .finally(done);
28 |         });
29 |         it('must reject', () => {
30 |             expect(error instanceof TypeError).toBe(true);
31 |             expect(error.message).toBe(errMsg);
32 |         });
33 |     });
34 | 
35 |     describe('for transactions', () => {
36 |         let error;
37 |         beforeEach(done => {
38 |             db.tx(function* () {
39 |             })
40 |                 .catch(e => {
41 |                     error = e;
42 |                 })
43 |                 .finally(done);
44 |         });
45 |         it('must reject', () => {
46 |             expect(error instanceof TypeError).toBe(true);
47 |             expect(error.message).toBe(errMsg);
48 |         });
49 |     });
50 | 
51 | });
52 | 


--------------------------------------------------------------------------------
/test/sql-special/dup-files/1-one.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/dup-files/1-one.sql


--------------------------------------------------------------------------------
/test/sql-special/dup-files/one.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/dup-files/one.sql


--------------------------------------------------------------------------------
/test/sql-special/dup-folders/1-sub/first.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/dup-folders/1-sub/first.sql


--------------------------------------------------------------------------------
/test/sql-special/dup-folders/sub/first.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/dup-folders/sub/first.sql


--------------------------------------------------------------------------------
/test/sql-special/folders-only/one/first.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/folders-only/one/first.sql


--------------------------------------------------------------------------------
/test/sql-special/folders-only/two/first.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/folders-only/two/first.sql


--------------------------------------------------------------------------------
/test/sql-special/one.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/one.sql


--------------------------------------------------------------------------------
/test/sql-special/sql-config.json:
--------------------------------------------------------------------------------
1 | {
2 |   "dir": "./test/sql",
3 |   "output": "generated.js",
4 |   "module": {
5 |     "name": "load",
6 |     "path": "./loadSql"
7 |   }
8 | }
9 | 


--------------------------------------------------------------------------------
/test/sql-special/sql-invalid.json:
--------------------------------------------------------------------------------
1 | {
2 | }


--------------------------------------------------------------------------------
/test/sql-special/sql-simple.json:
--------------------------------------------------------------------------------
1 | {
2 |   "dir": "./test/sql",
3 |   "output": "generated.js",
4 |   "module": {
5 |   }
6 | }
7 | 


--------------------------------------------------------------------------------
/test/sql-special/two.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql-special/two.sql


--------------------------------------------------------------------------------
/test/sql/allUsers.sql:
--------------------------------------------------------------------------------
1 | /*
2 |     Multi-line comments
3 | */
4 | select * from users -- single-line comment
5 | 


--------------------------------------------------------------------------------
/test/sql/invalid.sql:
--------------------------------------------------------------------------------
1 | select '1;


--------------------------------------------------------------------------------
/test/sql/params.sql:
--------------------------------------------------------------------------------
1 | /*
2 |     This is to test static formatting parameters,
3 |     such as schema name and table name.
4 | */
5 | 
6 | -- We schema/table we should use the SQL Name syntax (with tilde):
7 | SELECT ${column~} FROM ${schema~}.${table~}
8 | 


--------------------------------------------------------------------------------
/test/sql/simple.sql:
--------------------------------------------------------------------------------
1 | select 1; --comment


--------------------------------------------------------------------------------
/test/sql/sub/one.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql/sub/one.sql


--------------------------------------------------------------------------------
/test/sql/sub/one.two.three.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql/sub/one.two.three.sql


--------------------------------------------------------------------------------
/test/sql/sub/third/notSql.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql/sub/third/notSql.txt


--------------------------------------------------------------------------------
/test/sql/sub/two.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitaly-t/pg-promise/563b7c2162ba3ce3d46f7f85ee86758af18691f2/test/sql/sub/two.sql


--------------------------------------------------------------------------------
/test/typescript.spec.js:
--------------------------------------------------------------------------------
 1 | const exec = require('child_process').exec;
 2 | const path = require('path');
 3 | const TIMEOUT = 20000; // 20 SECONDS
 4 | 
 5 | describe('Typescript', () => {
 6 |     describe('build', () => {
 7 |         it('must build without error', done => {
 8 |             exec('tsc', {cwd: path.join('test', 'typescript')}, error => {
 9 |                 expect(error).toBe(null);
10 |                 done();
11 |             });
12 |         }, TIMEOUT);
13 |     });
14 | });
15 | 


--------------------------------------------------------------------------------
/test/typescript/adapter.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const adapter = new pgPromise.PromiseAdapter({
 4 |     create(cb) {
 5 |         return new Promise(cb);
 6 |     },
 7 |     resolve() {
 8 |     },
 9 |     reject() {
10 |     },
11 |     all() {
12 |         return Promise.resolve();
13 |     }
14 | });
15 | 
16 | const pgp = pgPromise({
17 |     promiseLib: adapter
18 | });
19 | 


--------------------------------------------------------------------------------
/test/typescript/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | call tsc
3 | 


--------------------------------------------------------------------------------
/test/typescript/clean.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | 
3 | call del *.js *.map /Q
4 | 


--------------------------------------------------------------------------------
/test/typescript/config.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | import {IGenericPromise} from "../../typescript/pg-promise";
 3 | 
 4 | const pgp: pgPromise.IMain = pgPromise();
 5 | const db = pgp('connection');
 6 | 
 7 | const cfg = db.$config;
 8 | const p: IGenericPromise = cfg.promise;
 9 | 
10 | p((resolve, reject) => {
11 |     resolve(123);
12 |     reject(new Error('ops!'));
13 | })
14 |     .then(data => {
15 | 
16 |     });
17 | 
18 | cfg.options.capSQL = true;
19 | 
20 | cfg.pgp.as.format('');
21 | 
22 | const version: string = cfg.version;
23 | 


--------------------------------------------------------------------------------
/test/typescript/connection.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | import {IConnectionParameters} from '../../typescript/pg-subset';
 3 | import {ILostContext} from "../../typescript/pg-promise";
 4 | 
 5 | const pgp: pgPromise.IMain = pgPromise({
 6 |     schema: ['public', 'mine'],
 7 |     capSQL: true,
 8 |     pgNative: true,
 9 |     pgFormatting: true,
10 |     noWarnings: true
11 | });
12 | 
13 | const pgp2: pgPromise.IMain = pgPromise({
14 |     schema() {
15 |     }
16 | });
17 | 
18 | const pgp3: pgPromise.IMain = pgPromise({
19 |     schema(dc: any) {
20 |         return ['one', 'two'];
21 |     }
22 | });
23 | 
24 | const db = pgp('connection');
25 | 
26 | type t = IConnectionParameters;
27 | let r: t = {};
28 | r.application_name = 'hello';
29 | r.ssl = {
30 |     ca: ''
31 | };
32 | 
33 | r.password = () => 'pass123';
34 | 
35 | r.keepAlive = true;
36 | 
37 | const db2 = pgp({
38 |     binary: true
39 | });
40 | 
41 | db.connect()
42 |     .then(ctx => {
43 |         ctx.batch([1, 2, 3]);
44 |         ctx.sequence(index => {
45 |         });
46 |         ctx.page(a => {
47 |         });
48 |         const cn = ctx.client.connectionParameters;
49 |         ctx.done();
50 |     });
51 | 
52 | db.connect({});
53 | 
54 | db.connect({
55 |     direct: true,
56 |     onLost(err: any, e: ILostContext) {
57 |         e.client.removeListener('notification', () => {
58 |         })
59 |     }
60 | });
61 | 


--------------------------------------------------------------------------------
/test/typescript/errors.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const err1 = <pgPromise.errors.QueryResultError><unknown>null;
 4 | const query = err1.query;
 5 | 
 6 | const err2 = <pgPromise.errors.QueryFileError><unknown>null;
 7 | const line = err2.error.position.line;
 8 | 
 9 | const err3 = <pgPromise.errors.PreparedStatementError><unknown>null;
10 | const file = err3.error.file;
11 | 
12 | const qrec = pgPromise.errors.queryResultErrorCode;
13 | const t = qrec.multiple;
14 | 


--------------------------------------------------------------------------------
/test/typescript/events.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const pgp: pgPromise.IMain<{}, MyClient> = pgPromise({
 4 |     connect(e) {
 5 |         const v = e.client.version;
 6 |     },
 7 |     receive(e: any) {
 8 |         const dc = e.ctx.dc;
 9 |         const d = e.data[0].prop;
10 |         const r = e.result.fields[0].name;
11 |         const query = e.query;
12 |     },
13 |     query(e: any) {
14 |         const dc = e.dc;
15 |         const query = e.query;
16 |     },
17 |     error(err: any, e: any) {
18 |         const dc = e.dc;
19 |         const query = e.query;
20 |     },
21 |     extend(obj: any, dc: any) {
22 |         obj['method'] = (val: any) => {
23 |             return obj.one(null, val);
24 |         }
25 |     }
26 | });
27 | 
28 | class MyClient extends pgp.pg.Client {
29 |     version?: string;
30 | }
31 | 
32 | const db = pgp({
33 |     Client: MyClient
34 | });
35 | 
36 | db.task(t => {
37 |     const dc = t.ctx.dc;
38 |     const useCount = t.ctx.useCount;
39 |     return t.batch([
40 |         t.one('query'),
41 |         t.none('query')
42 |     ]);
43 | })
44 |     .then(data => {
45 |     })
46 |     .catch(error => {
47 | 
48 |     });
49 | 


--------------------------------------------------------------------------------
/test/typescript/extensions.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | interface IExtensions {
 4 |     findUser(userId: number): Promise<any>;
 5 | }
 6 | 
 7 | const pgp: pgPromise.IMain = pgPromise({
 8 |     extend(obj: any, dc: any) {
 9 |         obj['findUser'] = (userId: number) => {
10 |             return obj.one('', userId);
11 |         }
12 |     }
13 | });
14 | 
15 | const db = pgp('connection');
16 | 
17 | const pgpExt = pgPromise({
18 |     extend(obj: pgPromise.IDatabase<IExtensions> & IExtensions) {
19 |         obj.findUser = (userId: number) => {
20 |             return obj.one('', userId);
21 |         }
22 |     }
23 | });
24 | 
25 | const dbExt1 = pgp<IExtensions>('connection');
26 | const dbExt2 = pgpExt<IExtensions>('connection');
27 | const dbExt3 = pgpExt<IExtensions>('connection');
28 | 
29 | dbExt1.findUser(123).then();
30 | dbExt2.findUser(123).then();
31 | dbExt3.findUser(123).then();
32 | 
33 | dbExt1.task(function (t) {
34 |     return t.findUser(123);
35 | });
36 | 
37 | dbExt2.task(function (t) {
38 |     return t.findUser(123);
39 | });
40 | 
41 | dbExt3.task(function (t) {
42 |     return t.findUser(123);
43 | });
44 | 
45 | dbExt3.task(t => {
46 |     return [1, 2, 3];
47 | })
48 |     .then(data => {
49 |         const a: number = data[0];
50 |     });
51 | 
52 | dbExt3.tx<number>(t => {
53 |     return Promise.resolve(123);
54 | })
55 |     .then(data => {
56 |         const a: number = data;
57 |     });
58 | 
59 | dbExt1.tx(t => {
60 |     return t.findUser(123);
61 | });
62 | 
63 | dbExt2.tx(t => {
64 |     return t.findUser(123);
65 | });
66 | 
67 | dbExt3.tx(t => {
68 |     return t.findUser(123);
69 | });
70 | 


--------------------------------------------------------------------------------
/test/typescript/formatting.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const value1 = pgPromise.as.array([]);
 4 | const value2 = pgPromise.as.array(() => []);
 5 | 
 6 | const pgp: pgPromise.IMain = pgPromise();
 7 | 
 8 | const value3 = pgp.as.array([], {capSQL: true});
 9 | const value4 = pgp.as.array(() => []);
10 | const value5 = pgp.as.format('hello', []);
11 | const value6 = pgp.as.format(new pgPromise.QueryFile(''));
12 | 
13 | let alias = pgp.as.alias('a');
14 | alias = pgp.as.alias(() => 'a');
15 | 
16 | const num1 = pgp.as.number(123);
17 | const num2 = pgp.as.number(123n);
18 | const num3 = pgp.as.number(() => 123);
19 | const num4 = pgp.as.number(() => 123n);
20 | 
21 | class CTF {
22 | 
23 |     constructor() {
24 |         this.rawType = true;
25 |     }
26 | 
27 |     toPostgres(a: any) {
28 | 
29 |     }
30 | 
31 |     rawType: boolean;
32 | 
33 |     // CTF symbols support:
34 | 
35 |     [pgp.as.ctf.toPostgres](): any {
36 |         return 123;
37 |     };
38 | 
39 |     // Ops! TypeScript doesn't support it yet!
40 |     // See these issues:
41 |     // - https://github.com/Microsoft/TypeScript/issues/16432
42 |     // - https://github.com/Microsoft/TypeScript/pull/15473
43 |     //
44 |     // [pgp.as.ctf.rawType]: boolean;
45 | 
46 | }
47 | 
48 | const ctf = new CTF();
49 | 
50 | const testCTF = pgp.as.format(ctf, null, {def: 1, partial: true, capSQL: true});
51 | 
52 | const testFunc1 = pgp.as.func(() => {
53 | });
54 | 
55 | const testFunc2 = pgp.as.func(a => {
56 |     return 123;
57 | });
58 | 


--------------------------------------------------------------------------------
/test/typescript/help.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | import {Column, ColumnSet, TableName, IMain} from '../../typescript/pg-promise';
 3 | 
 4 | const pgp: IMain = pgPromise({
 5 |     capSQL: true
 6 | });
 7 | 
 8 | const col1: Column = new pgp.helpers.Column({
 9 |     name: 'third-col',
10 |     prop: 'third',
11 |     def: 888,
12 |     cast: '',
13 |     cnd: true,
14 |     init(col) {
15 |         const e = col.exists;
16 |         return this;
17 |     },
18 |     skip(col) {
19 |         const e = col.exists;
20 |         return false;
21 |     }
22 | });
23 | 
24 | const col2: Column = new pgp.helpers.Column('col');
25 | 
26 | const data = [
27 |     {
28 |         first: 1,
29 |         second: 'two'
30 |     }, {
31 |         first: 111,
32 |         second: 'hello'
33 |     }
34 | ];
35 | 
36 | const table1: TableName = new pgp.helpers.TableName('');
37 | const table2: TableName = new pgp.helpers.TableName({table: ''});
38 | const table3: TableName = new pgp.helpers.TableName({table: '', schema: ''});
39 | 
40 | const cs: ColumnSet = new pgp.helpers.ColumnSet([
41 |     'first', 'second', {
42 |         name: 'third-col',
43 |         prop: 'third',
44 |         def: 888,
45 |         cast: '',
46 |         cnd: true,
47 |         init() {
48 |         },
49 |         skip() {
50 |         }
51 |     }
52 | ], {table: 'my-table', inherit: true});
53 | 
54 | var r = cs.columns;
55 | 
56 | const insert: string = pgp.helpers.insert(data, cs, 'my-table');
57 | const update: string = pgp.helpers.update(data, cs, table1, {tableAlias: 'W'});
58 | 
59 | const values1: string = pgp.helpers.values({});
60 | const values2: string = pgp.helpers.values({}, []);
61 | const values3: string = pgp.helpers.values([{}], []);
62 | const values4: string = pgp.helpers.values([], cs);
63 | 
64 | const names: string = cs.names;
65 | const variables: string = cs.variables;
66 | 
67 | let obj = cs.prepare(Date);
68 | obj = cs.prepare({});
69 | 
70 | const sets1: string = pgp.helpers.sets({});
71 | const sets2: string = pgp.helpers.sets([]);
72 | const sets3: string = pgp.helpers.sets({}, cs);
73 | 
74 | const cs1: ColumnSet = cs.extend(['']);
75 | const cs2: ColumnSet = cs1.merge(cs);
76 | 
77 | const c1: string = pgp.helpers.concat(['first', {query: 'second'}]);
78 | const c2: string = pgp.helpers.concat(['first', new pgp.QueryFile(''), {
79 |     query: '',
80 |     values: 123,
81 |     options: {partial: true}
82 | }]);
83 | 
84 | cs1.assignColumns();
85 | cs1.assignColumns({});
86 | cs1.assignColumns({from: 'source'});
87 | cs1.assignColumns({to: 'target', skip: 'one'});
88 | cs1.assignColumns({skip: ['one', 'two']});
89 | 


--------------------------------------------------------------------------------
/test/typescript/init.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | import {IConnectionParameters} from '../../typescript/pg-subset';
 3 | 
 4 | const pgp: pgPromise.IMain = pgPromise({
 5 |     capSQL: true,
 6 |     pgFormatting: true,
 7 |     pgNative: true
 8 | });
 9 | 
10 | let c: IConnectionParameters = {};
11 | c.binary = true;
12 | 
13 | const spex = pgp.spex;
14 | 
15 | async function test() {
16 |     const [first, second] = await spex.batch<number, string>([1, 'hello']);
17 | 
18 |     const res = await spex.batch<number, string>([1, 'hello']);
19 |     const d = res.duration;
20 | }
21 | 
22 | interface Test {
23 |     hello: string;
24 | }
25 | 
26 | const db = <pgPromise.IDatabase<Test> & Test>pgp({
27 |     isDomainSocket: true,
28 |     max: 20,
29 |     application_name: 'my-app'
30 | });
31 | 
32 | const connection1: string = <string>db.$cn;
33 | const connection2: IConnectionParameters = <IConnectionParameters>db.$cn;
34 | 
35 | const context: any = db.$dc;
36 | const pool: any = db.$pool;
37 | 
38 | db.one('');
39 | 
40 | db.one(new pgPromise.QueryFile(''));
41 | 
42 | db.tx({tag: 123}, function (t) {
43 |     const w = t.one('');
44 |     const q = t.hello;
45 | });
46 | 


--------------------------------------------------------------------------------
/test/typescript/parameterized.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const pgp: pgPromise.IMain = pgPromise();
 4 | const db: pgPromise.IDatabase<any> = pgp('connection');
 5 | 
 6 | const pq0 = new pgp.ParameterizedQuery();
 7 | const pq01 = new pgp.ParameterizedQuery({});
 8 | const pq1 = new pgp.ParameterizedQuery('');
 9 | const pq2 = new pgp.ParameterizedQuery({text: ''});
10 | const pq3 = new pgp.ParameterizedQuery(pq1);
11 | 
12 | const qf = new pgPromise.QueryFile('file');
13 | const pq4 = new pgp.ParameterizedQuery({text: qf, values: [123], rowMode: 'array'});
14 | 
15 | pq4.text = 'test';
16 | pq4.text = qf;
17 | 
18 | db.one(pq1);
19 | 
20 | db.one({
21 |     name: '',
22 |     text: ''
23 | });
24 | 
25 | db.one({
26 |     name: '',
27 |     text: qf
28 | });
29 | 
30 | const test1 = <pgPromise.errors.ParameterizedQueryError>pq1.parse();
31 | const file = test1.error.file;
32 | 


--------------------------------------------------------------------------------
/test/typescript/pg.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | import {IColumn, IResult} from '../../typescript/pg-subset';
 3 | import {TypeId} from '../../typescript/pg-subset';
 4 | 
 5 | const pgp: pgPromise.IMain = pgPromise();
 6 | 
 7 | class MyClient extends pgp.pg.Client {
 8 | 
 9 |     version?: string;
10 | 
11 |     constructor(config: any) {
12 |         super(config);
13 |         this.connection.on('parameterStatus', msg => {
14 |             // See the following question:
15 |             // https://stackoverflow.com/questions/58725659/get-the-postgresql-server-version-from-connection
16 |             if (msg.parameterName === 'server_version') {
17 |                 this.version = msg.parameterValue;
18 |             }
19 |         });
20 |         this.connection.stream.on('something', () => {
21 | 
22 |         });
23 | 
24 |         // any event handlers are allowed:
25 |         this.on('whatever', (whatever1: any, whatever2: any) => {
26 | 
27 |         });
28 | 
29 |         this.query('test', [1, 2]).then();
30 |     }
31 | }
32 | 
33 | const db = pgp({
34 |     Client: MyClient
35 | });
36 | 
37 | const pg = pgp.pg;
38 | 
39 | pg.types.setTypeParser(TypeId.INT8, parseInt);
40 | pg.types.setTypeParser(pg.types.builtins.INT8, parseInt);
41 | 
42 | db.connect()
43 |     .then(t => {
44 |         const v = t.client.version;
45 |         t.client.on('notification', (message: any) => {
46 |             const s = message.anything;
47 |         });
48 |         t.client.removeAllListeners();
49 |     });
50 | 
51 | const database = pg.defaults.database;
52 | 
53 | let col: IColumn;
54 | let res: IResult;
55 | 


--------------------------------------------------------------------------------
/test/typescript/pool.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const pgp: pgPromise.IMain = pgPromise({});
 4 | 
 5 | const db = pgp('connection');
 6 | 
 7 | (async function () {
 8 |     const res: undefined = await db.$pool.end();
 9 | 
10 |     const res2: void = await db.$pool.end((err: Error) => {
11 |         console.log(err.stack);
12 |     });
13 | 
14 |     const {totalCount, idleCount, waitingCount} = db.$pool;
15 | 
16 |     db.$pool.on('error', err => {
17 |         // handle errors
18 |     })
19 | 
20 |     const database = db.$pool.options.database;
21 | })();
22 | 


--------------------------------------------------------------------------------
/test/typescript/prepared.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const pgp: pgPromise.IMain = pgPromise();
 4 | const db: pgPromise.IDatabase<any> = pgp('connection');
 5 | 
 6 | const ps1 = new pgp.PreparedStatement({name: '', text: ''});
 7 | const ps2 = new pgp.PreparedStatement(ps1);
 8 | 
 9 | const qf = new pgPromise.QueryFile('file');
10 | 
11 | ps1.text = 'some text';
12 | ps1.text = qf;
13 | 
14 | const ps11 = new pgp.PreparedStatement();
15 | const ps22 = new pgp.PreparedStatement({});
16 | const ps3 = new pgp.PreparedStatement({name: '', text: qf, values: [], rowMode: null, rows: 123});
17 | const ps4 = new pgp.PreparedStatement({name: '', text: qf, values: [], rowMode: 'array', rows: 0});
18 | 
19 | db.one(ps1);
20 | 
21 | db.one({
22 |     name: '',
23 |     text: ''
24 | });
25 | 
26 | db.one({
27 |     name: '',
28 |     text: qf
29 | });
30 | 
31 | const test1 = <pgPromise.errors.PreparedStatementError>ps1.parse();
32 | const file = test1.error.file;
33 | 


--------------------------------------------------------------------------------
/test/typescript/queries.ts:
--------------------------------------------------------------------------------
  1 | import * as pgPromise from '../../typescript/pg-promise';
  2 | 
  3 | const pgp: pgPromise.IMain = pgPromise();
  4 | 
  5 | const db: pgPromise.IDatabase<any> = pgp('connection');
  6 | 
  7 | const qrm = pgPromise.queryResult;
  8 | 
  9 | db.query('', [], qrm.one | qrm.none)
 10 |     .then(data => {
 11 |         const d1 = data.value;
 12 |         const d2 = data[0].value;
 13 |     });
 14 | 
 15 | db.any<number>('').then(data => {
 16 |     const a: number = data[0];
 17 | });
 18 | 
 19 | db.any('').then(data => {
 20 |     const a: number = data[0];
 21 | });
 22 | 
 23 | db.none('')
 24 |     .then(data => {
 25 |     });
 26 | 
 27 | db.one('', [], value => {
 28 |     return {value: 123};
 29 | }, 'this')
 30 |     .then(data => {
 31 |         const value = data.value;
 32 |     });
 33 | 
 34 | db.oneOrNone('')
 35 |     .then(data => {
 36 |         const value = data.value;
 37 |     });
 38 | 
 39 | db.many('')
 40 |     .then(data => {
 41 |         const value = data[0].ops;
 42 |     });
 43 | 
 44 | const r = db.result('', [], data => {
 45 |     for (const t of data) {
 46 |         // can iterate
 47 |     }
 48 |     return data;
 49 | }, 123);
 50 | 
 51 | db.func('func_name').then();
 52 | db.func('func_name', [123]).then();
 53 | db.func('func_name', [123]).then();
 54 | 
 55 | db.proc('proc_name').then();
 56 | db.proc('proc_name', [123]).then();
 57 | db.proc('proc_name', [123], a => a.value).then();
 58 | db.proc<number>('proc_name', [123], a => a && a.value)
 59 |     .then((value: number | null) => {
 60 |     });
 61 | 
 62 | db.multiResult('', [])
 63 |     .then(data => {
 64 |         const tableID = data[0].fields[0].tableID;
 65 |     });
 66 | 
 67 | db.multi('', [])
 68 |     .then(data => {
 69 |         const length = data[0].length;
 70 |     });
 71 | 
 72 | db.map('', null, row => {
 73 |     return row.value;
 74 | })
 75 |     .then((data: any[]) => {
 76 |         const d: number = data[0];
 77 |     });
 78 | 
 79 | db.each('', null, row => {
 80 |     const v = row.value;
 81 | })
 82 |     .then((data: any[]) => {
 83 |     });
 84 | 
 85 | db.task(t => {
 86 |     return t.batch([
 87 |         t.one('')
 88 |     ])
 89 |         .then((data: any[]) => {
 90 |             return data;
 91 |         });
 92 | })
 93 |     .then(data => {
 94 |         const d1 = data.value;
 95 |         const d2 = data[0].value;
 96 |     });
 97 | 
 98 | function getQuery() {
 99 |     return getNested;
100 | }
101 | 
102 | function getNested(): string {
103 |     return 'SELECT 123;';
104 | }
105 | 
106 | db.any(getQuery, 123);
107 | 
108 | function getOne() {
109 |     return {text: ''};
110 | }
111 | 
112 | db.one(getOne);
113 | 


--------------------------------------------------------------------------------
/test/typescript/tasks.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | import {ITaskIfOptions, ITxIfOptions} from '../../typescript/pg-promise';
 4 | 
 5 | const pgp: pgPromise.IMain = pgPromise();
 6 | const db: pgPromise.IDatabase<any> = pgp('connection');
 7 | 
 8 | db.task(t => {
 9 |     const d: Date = t.ctx.start;
10 |     const duration: number = t.ctx.duration;
11 |     const parentTag = t.ctx.parent.tag;
12 |     const connected: boolean = t.ctx.connected;
13 |     return t.batch([]);
14 | });
15 | 
16 | db.task('with a name', t => {
17 |     const d: Date = t.ctx.start;
18 |     t.sequence(() => {
19 |     });
20 | });
21 | 
22 | db.tx(t => {
23 |     const d: Date = t.ctx.start;
24 |     t.page(() => {
25 |     });
26 | });
27 | 
28 | db.tx('with a name', t => {
29 |     const d: Date = t.ctx.start;
30 | });
31 | 
32 | db.task<number>(t => {
33 |     return 123;
34 | })
35 |     .then(data => {
36 |     });
37 | 
38 | db.task<number>(t => {
39 |     return Promise.resolve(123);
40 | })
41 |     .then(data => {
42 |     });
43 | 
44 | const res = db.taskIf({cnd: true, tag: 123}, t => {
45 |     return 123;
46 | });
47 | 
48 | type TestExt = {
49 |     bla(): any;
50 | }
51 | 
52 | const txOpt: ITxIfOptions<TestExt> = {
53 |     cnd: ctx => {
54 |         return true
55 |     }, tag: 123, mode: null, reusable: true
56 | };
57 | 
58 | const res1 = db.txIf(txOpt, async t => {
59 |     const w = t.bla();
60 |     return true;
61 | });
62 | 


--------------------------------------------------------------------------------
/test/typescript/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compileOnSave": true,
 3 |   "compilerOptions": {
 4 |     "module": "commonjs",
 5 |     "target": "esnext",
 6 |     "sourceMap": true,
 7 |     "strict": true
 8 |   },
 9 |   "exclude": [
10 |     "node_modules"
11 |   ]
12 | }
13 | 


--------------------------------------------------------------------------------
/test/typescript/tx-mode.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const pgp: pgPromise.IMain = pgPromise();
 4 | const db: pgPromise.IDatabase<any> = pgp('connection');
 5 | 
 6 | const {TransactionMode} = pgPromise.txMode;
 7 | 
 8 | const mode = new TransactionMode({
 9 |     deferrable: true,
10 |     readOnly: true,
11 |     tiLevel: pgPromise.txMode.isolationLevel.readCommitted
12 | });
13 | 
14 | db.tx<number>({mode: null}, t => {
15 |     return 123;
16 | });
17 | 
18 | db.tx<number>({mode}, t => {
19 |     return 123;
20 | });
21 | 
22 | db.txIf<boolean>({cnd: true, tag: 123, mode: null, reusable: true}, t => {
23 |     return true;
24 | });
25 | 
26 | db.txIf<boolean>({cnd: true, tag: 123, mode, reusable: true}, t => {
27 |     return true;
28 | });
29 | 


--------------------------------------------------------------------------------
/test/typescript/utils.ts:
--------------------------------------------------------------------------------
 1 | import * as pgPromise from '../../typescript/pg-promise';
 2 | 
 3 | const utils = pgPromise.utils;
 4 | 
 5 | const pgp: pgPromise.IMain = pgPromise();
 6 | 
 7 | const utilsExtra = pgp.utils;
 8 | 
 9 | utils.camelize('');
10 | 
11 | utils.camelizeVar('');
12 | 
13 | const tree = utils.enumSql('', {recursive: true, ignoreErrors: true}, (file: string, name: string, path: string) => {
14 | 
15 | });
16 | 
17 | function testTaskArgs() {
18 |     const args = utils.taskArgs<{ first: string, second: boolean }>(arguments);
19 |     args.options.tag = 123;
20 |     args.options.mode = null;
21 |     args.options.cnd = new Error();
22 | 
23 |     args.options.first = '';
24 |     args.options.second = true;
25 | }
26 | 
27 | testTaskArgs();
28 | 


--------------------------------------------------------------------------------
/typescript/README.md:
--------------------------------------------------------------------------------
 1 | ## TypeScript for pg-promise
 2 | 
 3 | Complete TypeScript declarations for [pg-promise].
 4 | 
 5 | ### Inclusion
 6 | 
 7 | Typescript should be able to pick up the definitions without any manual configuration.
 8 | 
 9 | ### Simple Usage
10 | 
11 | ```ts
12 | import pgPromise from 'pg-promise';
13 | 
14 | const pgp = pgPromise({/* Initialization Options */});
15 | 
16 | const db = pgp('postgres://username:password@host:port/database');
17 | 
18 | const {value} = await db.one('SELECT 123 as value');
19 | ```
20 | 
21 | #### With Extensions
22 | 
23 | The library supports dynamic protocol extensions, via event [extend], which requires
24 | an explicit extension interface to be declared and parameterized, as shown below.
25 | 
26 | ```ts
27 | import * as pgPromise from 'pg-promise';
28 | 
29 | // your protocol extensions:
30 | interface IExtensions {
31 |     findUser(userId: number): Promise<any>;
32 | }
33 | 
34 | // pg-promise initialization options:
35 | const options: pgPromise.IInitOptions<IExtensions> = {
36 |     extend(obj) {
37 |         obj.findUser = userId => {
38 |             return obj.one('SELECT * FROM Users WHERE id = $1', [userId]);
39 |         }
40 |     }
41 | };
42 | 
43 | // initializing the library:
44 | const pgp = pgPromise(options);
45 | 
46 | // database object:
47 | const db = pgp('postgres://username:password@host:port/database');
48 | 
49 | // protocol is extended on each level:
50 | const user = await db.findUser(123);
51 | 
52 | // ...including inside tasks and transactions:
53 | await db.task(async t => {
54 |     const user = await t.findUser(123);
55 |     // ...etc
56 | });
57 | ```
58 | 
59 | For a comprehensive example, check out [pg-promise-demo].
60 | 
61 | [pg-promise-demo]:https://github.com/vitaly-t/pg-promise-demo
62 | [extend]:https://vitaly-t.github.io/pg-promise/global.html#event:extend
63 | [pg-promise]:https://github.com/vitaly-t/pg-promise
64 | 


--------------------------------------------------------------------------------
/typescript/tslint.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "rules": {
 3 |     "trailing-comma": [
 4 |       true,
 5 |       {
 6 |         "multiline": "never",
 7 |         "singleline": "never"
 8 |       }
 9 |     ],
10 |     "quotemark": [
11 |       true,
12 |       "single"
13 |     ],
14 |     "class-name": true,
15 |     "interface-name": [
16 |       true,
17 |       "always-prefix"
18 |     ],
19 |     "no-consecutive-blank-lines": true
20 |   }
21 | }


--------------------------------------------------------------------------------