@imqueue/pg-sequelize 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CONTRIBUTING.md +58 -0
  3. package/CONTRIBUTION-TERMS.md +79 -0
  4. package/LICENSE +585 -0
  5. package/README.md +94 -0
  6. package/SECURITY.md +41 -0
  7. package/index.d.ts +86 -0
  8. package/index.js +87 -0
  9. package/package.json +75 -0
  10. package/src/BaseModel.d.ts +695 -0
  11. package/src/BaseModel.js +917 -0
  12. package/src/Graph.d.ts +215 -0
  13. package/src/Graph.js +257 -0
  14. package/src/decorators/AssociatedWith.d.ts +94 -0
  15. package/src/decorators/AssociatedWith.js +71 -0
  16. package/src/decorators/ColumnIndex.d.ts +206 -0
  17. package/src/decorators/ColumnIndex.js +98 -0
  18. package/src/decorators/CreatedBy.d.ts +27 -0
  19. package/src/decorators/CreatedBy.js +84 -0
  20. package/src/decorators/DeletedBy.d.ts +30 -0
  21. package/src/decorators/DeletedBy.js +89 -0
  22. package/src/decorators/DynamicView.d.ts +124 -0
  23. package/src/decorators/DynamicView.js +113 -0
  24. package/src/decorators/Emittable.d.ts +39 -0
  25. package/src/decorators/Emittable.js +42 -0
  26. package/src/decorators/NullableIndex.d.ts +77 -0
  27. package/src/decorators/NullableIndex.js +64 -0
  28. package/src/decorators/UpdatedBy.d.ts +27 -0
  29. package/src/decorators/UpdatedBy.js +105 -0
  30. package/src/decorators/View.d.ts +87 -0
  31. package/src/decorators/View.js +93 -0
  32. package/src/decorators/index.d.ts +32 -0
  33. package/src/decorators/index.js +33 -0
  34. package/src/helpers/index.d.ts +24 -0
  35. package/src/helpers/index.js +25 -0
  36. package/src/helpers/js.d.ts +61 -0
  37. package/src/helpers/js.js +88 -0
  38. package/src/helpers/query.d.ts +445 -0
  39. package/src/helpers/query.js +1095 -0
  40. package/src/index.d.ts +162 -0
  41. package/src/index.js +223 -0
  42. package/src/types/DataPage.d.ts +52 -0
  43. package/src/types/DataPage.js +2 -0
  44. package/src/types/FieldsInput.d.ts +41 -0
  45. package/src/types/FieldsInput.js +75 -0
  46. package/src/types/FilterInput.d.ts +136 -0
  47. package/src/types/FilterInput.js +291 -0
  48. package/src/types/JsonObject.d.ts +16 -0
  49. package/src/types/JsonObject.js +50 -0
  50. package/src/types/OrderByInput.d.ts +45 -0
  51. package/src/types/OrderByInput.js +80 -0
  52. package/src/types/PaginationInput.d.ts +44 -0
  53. package/src/types/PaginationInput.js +90 -0
  54. package/src/types/index.d.ts +30 -0
  55. package/src/types/index.js +31 -0
  56. package/src/types/ranges/DateRange.d.ts +27 -0
  57. package/src/types/ranges/DateRange.js +69 -0
  58. package/src/types/ranges/IRange.d.ts +47 -0
  59. package/src/types/ranges/IRange.js +2 -0
  60. package/src/types/ranges/NumericRange.d.ts +19 -0
  61. package/src/types/ranges/NumericRange.js +61 -0
  62. package/src/types/ranges/index.d.ts +26 -0
  63. package/src/types/ranges/index.js +27 -0
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # @imqueue/pg-sequelize
2
+
3
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/imqueue/pg-sequelize/build.yml)](https://github.com/imqueue/pg-sequelize)
4
+ [![Known Vulnerabilities](https://snyk.io/test/github/imqueue/pg-sequelize/badge.svg?targetFile=package.json)](https://snyk.io/test/github/imqueue/pg-sequelize?targetFile=package.json)
5
+ [![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://github.com/imqueue/pg-sequelize/blob/master/LICENSE)
6
+
7
+ Turns a query described as data — a filter, a page, an order and the fields the caller
8
+ actually needs — into one efficient Sequelize statement. Plus database views as models,
9
+ the Postgres index options Sequelize cannot express, and a single import surface for the
10
+ whole ORM stack.
11
+
12
+ # Sequelize v6, and the alternative
13
+
14
+ This targets Sequelize v6 — a mature line, proven in production, and the one this
15
+ package is actively developed against. Sequelize v7 is still in alpha upstream, so v6 is
16
+ what there is to build on today; if v7 lands, this follows it.
17
+
18
+ If you would rather build on Prisma,
19
+ [@imqueue/pg-prisma](https://github.com/imqueue/pg-prisma) covers the same ground for
20
+ that stack. Both are supported — pick the ORM you want to live with.
21
+
22
+ # Renamed
23
+
24
+ This package was called `@imqueue/sequelize` up to and including 4.1.3. The old
25
+ name is deprecated on npm and receives no further releases; there is no
26
+ compatibility shim. To migrate, change the dependency and every import specifier
27
+ — no export changed name or signature, and the `pg-` prefix only states what was
28
+ always true: this targets Postgres specifically, not every Sequelize dialect.
29
+
30
+ # Install
31
+
32
+ ~~~bash
33
+ npm i --save @imqueue/pg-sequelize
34
+ ~~~
35
+
36
+ # Usage
37
+
38
+ Connect once, anywhere in the service. Every later call hands back the same instance, so
39
+ only the first one needs the configuration:
40
+
41
+ ~~~typescript
42
+ import { database, query } from '@imqueue/pg-sequelize';
43
+
44
+ const sequelize = database({
45
+ logger: console,
46
+ modelsPath: './src/orm/models',
47
+ sequelize: {
48
+ benchmark: true,
49
+ dialect: 'postgres',
50
+ storage: 'sequelize',
51
+ pool: {
52
+ max: 250,
53
+ min: 2,
54
+ idle: 30000,
55
+ acquire: 30000,
56
+ },
57
+ },
58
+ });
59
+ ~~~
60
+
61
+ Then let the caller's own arguments build the query. `autoQuery` reads the requested
62
+ field map, so a column nobody asked for is not selected and a relation nobody reached
63
+ into is not joined:
64
+
65
+ ~~~typescript
66
+ const where = query.toWhereOptions(query.withRangeFilters(filter));
67
+ const rows = await LeadModel.findAll(query.autoQuery<FindOptions>(
68
+ LeadModel,
69
+ fields,
70
+ where,
71
+ query.toLimitOptions(pageOptions),
72
+ query.toOrderOptions(orderBy),
73
+ ));
74
+ const total = await LeadModel.count(query.autoCountQuery(LeadModel, fields, where));
75
+ ~~~
76
+
77
+ `filter`, `fields`, `pageOptions` and `orderBy` are plain JSON — `FilterInput`,
78
+ `FieldsInput`, `PaginationInput` and `OrderByInput` describe them — because Sequelize
79
+ writes its operators as ES symbols, and a symbol cannot survive a wire format. A GraphQL
80
+ resolver is the case this was written against, passing its arguments and its selected
81
+ field set straight through; an RPC method taking a filter object is the same problem.
82
+
83
+ # Docs
84
+
85
+ Every exported symbol carries its own documentation, so an editor is the fastest
86
+ reference. The same content is published, symbol by symbol, as the
87
+ [API reference](https://imqueue.org/api/pg-sequelize/latest/) — searchable, and linkable
88
+ when you need to point someone at one thing. The wider ecosystem documentation is at
89
+ [imqueue.org](https://imqueue.org/docs/).
90
+
91
+ ## License
92
+
93
+ This project is licensed under the GNU General Public License v3.0.
94
+ See the [LICENSE](LICENSE)
package/SECURITY.md ADDED
@@ -0,0 +1,41 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ If you believe you have found a security vulnerability in this `@imqueue` project (or
6
+ any `@imqueue/*` package), please report it **privately** — do not open a public
7
+ issue, pull request, or discussion for it.
8
+
9
+ Two private channels:
10
+
11
+ - **GitHub** — use *Security → Report a vulnerability* on this repository to open a
12
+ private advisory (preferred; it keeps the report and the fix coordinated in one
13
+ place).
14
+ - **Email** — <support@imqueue.com> with the details below.
15
+
16
+ Please include:
17
+
18
+ - the affected package or repository and version(s);
19
+ - a description of the issue and its impact;
20
+ - steps to reproduce, or a proof of concept, where possible.
21
+
22
+ ## What to expect
23
+
24
+ - We aim to acknowledge a report within a few business days.
25
+ - We'll confirm the issue, keep you updated on progress, and coordinate a fix and a
26
+ disclosure timeline with you.
27
+ - Once a fix is released we'll credit the reporter in the advisory unless you prefer
28
+ to remain anonymous.
29
+
30
+ ## Supported versions
31
+
32
+ Security fixes land on the latest published release line of each `@imqueue/*`
33
+ package on npm. Please make sure you can reproduce an issue against the current
34
+ release before reporting.
35
+
36
+ ## Scope
37
+
38
+ The `@imqueue` framework is open source under GPL-3.0. This policy covers the code
39
+ in the `@imqueue/*` packages and the project repositories. Vulnerabilities in
40
+ third-party dependencies should be reported to those projects, though we're glad to
41
+ help coordinate an upgrade.
package/index.d.ts ADDED
@@ -0,0 +1,86 @@
1
+ /*!
2
+ * @imqueue/pg-sequelize - Sequelize ORM refines for @imqueue
3
+ *
4
+ * I'm Queue Software Project
5
+ * Copyright (C) 2025 imqueue.com <support@imqueue.com>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+ *
20
+ * If you want to use this code in a closed source (commercial) project, you can
21
+ * purchase a proprietary commercial license. Please contact us at
22
+ * <support@imqueue.com> to get commercial licensing options.
23
+ */
24
+ /**
25
+ * Sequelize and `sequelize-typescript`, refined for `@imqueue` services.
26
+ *
27
+ * The problem it was built for: a caller describes the query it wants as DATA — a
28
+ * filter, a page, an order, and the fields it actually needs — and the service has to
29
+ * turn that into one efficient statement, without trusting any of it and without
30
+ * knowing in advance which shape will arrive. Anything can hand you a query described
31
+ * that way; a GraphQL API is the case this was written against, where a resolver passes
32
+ * the arguments and the selected field set through almost untouched and gets back a
33
+ * query that selects the columns asked for, joins only the relations the selection
34
+ * reaches into, and filters on values that arrived as JSON. An RPC method taking a
35
+ * filter object, or a REST endpoint with query parameters, is the same problem with
36
+ * different packaging.
37
+ *
38
+ * Which version, and which package. This targets Sequelize v6 — mature, proven in
39
+ * production, and what this package is actively developed against. Sequelize v7 is
40
+ * still in alpha upstream, so v6 is the line to build on for now, and if v7 lands this
41
+ * follows it. If you would rather build on Prisma, `@imqueue/pg-prisma` covers the same
42
+ * ground for that stack. Both are supported: pick the ORM you want to live with.
43
+ *
44
+ * The `query` namespace and the serializable input types are what do it. Sequelize
45
+ * writes a filter with ES symbols as its operators, and a symbol cannot survive a JSON
46
+ * payload, so {@link FilterInput}, {@link FieldsInput}, {@link PaginationInput} and
47
+ * {@link OrderByInput} give the wire an equivalent that can. `query.autoQuery` turns
48
+ * them back into Sequelize options, and builds the `include` tree the requested fields
49
+ * imply — which is where the efficiency comes from: a field nobody asked for is not
50
+ * selected, and a relation nobody reached into is not joined.
51
+ *
52
+ * {@link database} builds and caches the connection and discovers your compiled model
53
+ * files. It is a process-wide singleton: the first call configures it, every later one
54
+ * hands back the same instance, and SQL logging that can prettify and colourise
55
+ * statements is installed along the way.
56
+ *
57
+ * It is also the single import surface for the ORM stack, which is what most files in
58
+ * a service touch it for. Everything `sequelize` and `sequelize-typescript` export is
59
+ * re-exported here — `Table`, `Column`, `DataType`, `AllowNull`, `ForeignKey`,
60
+ * `BelongsTo`, `HasMany`, `QueryInterface` and the rest — so a model imports from one
61
+ * place rather than three, and several option types are widened on the way through
62
+ * (see {@link ReturningOptions}). A migration usually needs nothing but
63
+ * `QueryInterface`.
64
+ *
65
+ * The decorators are the smallest part and the most opinionated: {@link CreatedBy},
66
+ * {@link UpdatedBy} and {@link DeletedBy} stamp the acting user from the RPC request
67
+ * context, {@link AssociatedWith} declares a relation the query helpers can walk, and
68
+ * `View` and `DynamicView` let a model be a database view — a parameterised one, whose
69
+ * placeholders are filled in per query.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // the shape every paginated read method in a service ends up with
74
+ * const where = query.toWhereOptions(query.withRangeFilters(filter));
75
+ * const rows = await LeadModel.findAll(query.autoQuery<FindOptions>(
76
+ * LeadModel,
77
+ * fields,
78
+ * where,
79
+ * query.toLimitOptions(pageOptions),
80
+ * query.toOrderOptions(orderBy),
81
+ * ));
82
+ * ```
83
+ *
84
+ * @packageDocumentation
85
+ */
86
+ export * from './src/index.js';
package/index.js ADDED
@@ -0,0 +1,87 @@
1
+ /*!
2
+ * @imqueue/pg-sequelize - Sequelize ORM refines for @imqueue
3
+ *
4
+ * I'm Queue Software Project
5
+ * Copyright (C) 2025 imqueue.com <support@imqueue.com>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+ *
20
+ * If you want to use this code in a closed source (commercial) project, you can
21
+ * purchase a proprietary commercial license. Please contact us at
22
+ * <support@imqueue.com> to get commercial licensing options.
23
+ */
24
+ /**
25
+ * Sequelize and `sequelize-typescript`, refined for `@imqueue` services.
26
+ *
27
+ * The problem it was built for: a caller describes the query it wants as DATA — a
28
+ * filter, a page, an order, and the fields it actually needs — and the service has to
29
+ * turn that into one efficient statement, without trusting any of it and without
30
+ * knowing in advance which shape will arrive. Anything can hand you a query described
31
+ * that way; a GraphQL API is the case this was written against, where a resolver passes
32
+ * the arguments and the selected field set through almost untouched and gets back a
33
+ * query that selects the columns asked for, joins only the relations the selection
34
+ * reaches into, and filters on values that arrived as JSON. An RPC method taking a
35
+ * filter object, or a REST endpoint with query parameters, is the same problem with
36
+ * different packaging.
37
+ *
38
+ * Which version, and which package. This targets Sequelize v6 — mature, proven in
39
+ * production, and what this package is actively developed against. Sequelize v7 is
40
+ * still in alpha upstream, so v6 is the line to build on for now, and if v7 lands this
41
+ * follows it. If you would rather build on Prisma, `@imqueue/pg-prisma` covers the same
42
+ * ground for that stack. Both are supported: pick the ORM you want to live with.
43
+ *
44
+ * The `query` namespace and the serializable input types are what do it. Sequelize
45
+ * writes a filter with ES symbols as its operators, and a symbol cannot survive a JSON
46
+ * payload, so {@link FilterInput}, {@link FieldsInput}, {@link PaginationInput} and
47
+ * {@link OrderByInput} give the wire an equivalent that can. `query.autoQuery` turns
48
+ * them back into Sequelize options, and builds the `include` tree the requested fields
49
+ * imply — which is where the efficiency comes from: a field nobody asked for is not
50
+ * selected, and a relation nobody reached into is not joined.
51
+ *
52
+ * {@link database} builds and caches the connection and discovers your compiled model
53
+ * files. It is a process-wide singleton: the first call configures it, every later one
54
+ * hands back the same instance, and SQL logging that can prettify and colourise
55
+ * statements is installed along the way.
56
+ *
57
+ * It is also the single import surface for the ORM stack, which is what most files in
58
+ * a service touch it for. Everything `sequelize` and `sequelize-typescript` export is
59
+ * re-exported here — `Table`, `Column`, `DataType`, `AllowNull`, `ForeignKey`,
60
+ * `BelongsTo`, `HasMany`, `QueryInterface` and the rest — so a model imports from one
61
+ * place rather than three, and several option types are widened on the way through
62
+ * (see {@link ReturningOptions}). A migration usually needs nothing but
63
+ * `QueryInterface`.
64
+ *
65
+ * The decorators are the smallest part and the most opinionated: {@link CreatedBy},
66
+ * {@link UpdatedBy} and {@link DeletedBy} stamp the acting user from the RPC request
67
+ * context, {@link AssociatedWith} declares a relation the query helpers can walk, and
68
+ * `View` and `DynamicView` let a model be a database view — a parameterised one, whose
69
+ * placeholders are filled in per query.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // the shape every paginated read method in a service ends up with
74
+ * const where = query.toWhereOptions(query.withRangeFilters(filter));
75
+ * const rows = await LeadModel.findAll(query.autoQuery<FindOptions>(
76
+ * LeadModel,
77
+ * fields,
78
+ * where,
79
+ * query.toLimitOptions(pageOptions),
80
+ * query.toOrderOptions(orderBy),
81
+ * ));
82
+ * ```
83
+ *
84
+ * @packageDocumentation
85
+ */
86
+ export * from './src/index.js';
87
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@imqueue/pg-sequelize",
3
+ "version": "4.2.0",
4
+ "description": "Sequelize/Postgres toolkit for @imqueue microservices — turns a query described as data (filters, paging, ordering, fields) into one efficient statement, plus database views as models and the Postgres index options Sequelize cannot express",
5
+ "keywords": [
6
+ "imqueue",
7
+ "imq",
8
+ "sequelize",
9
+ "postgres",
10
+ "postgresql",
11
+ "pg",
12
+ "orm",
13
+ "typescript",
14
+ "graphql",
15
+ "microservices"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "scripts": {
21
+ "clean-compiled": "npm run clean-js && npm run clean-typedefs && npm run clean-maps",
22
+ "build": "npm run clean-compiled && tsc",
23
+ "prepare": "npm run build",
24
+ "lint": "oxlint",
25
+ "format": "oxfmt \"index.ts\" \"src/**/*.ts\" \"test/**/*.ts\"",
26
+ "format:check": "oxfmt --check \"index.ts\" \"src/**/*.ts\" \"test/**/*.ts\"",
27
+ "test": "npm run build && node --test --test-timeout=15000 $(find test -name '*.spec.js')",
28
+ "test-coverage": "npm run build && node --enable-source-maps --test --experimental-test-coverage --test-timeout=15000 $(find test -name '*.spec.js')",
29
+ "test-lcov": "npm run build && mkdir -p coverage && node --enable-source-maps --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage/lcov.info --test-timeout=15000 $(find test -name '*.spec.js'); node scripts/strip-comment-coverage.mjs coverage/lcov.info",
30
+ "test-coverage-html": "npm run test-lcov; genhtml coverage/lcov.info --output-directory coverage/html --ignore-errors inconsistent,corrupt,format,mismatch && echo \"Coverage report: file://$(pwd)/coverage/html/index.html\"",
31
+ "test-dev": "npm run test && npm run clean-js && npm run clean-typedefs && npm run clean-maps",
32
+ "clean-typedefs": "find . -name '*.d.ts' -not -wholename '*node_modules*' -type f -delete",
33
+ "clean-maps": "find . -name '*.js.map' -not -wholename '*node_modules*' -type f -delete",
34
+ "clean-js": "find . -name '*.js' -not -wholename '*node_modules*' -type f -delete",
35
+ "clean-tests": "rm -rf .nyc_output coverage",
36
+ "clean": "npm run clean-tests && npm run clean-typedefs && npm run clean-maps && npm run clean-js"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/imqueue/pg-sequelize.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/imqueue/pg-sequelize/issues"
44
+ },
45
+ "homepage": "https://imqueue.org/",
46
+ "author": "imqueue.com <support@imqueue.com>",
47
+ "license": "GPL-3.0-only",
48
+ "dependencies": {
49
+ "@imqueue/rpc": "^3.4.1",
50
+ "pg": "^8.22.0",
51
+ "reflect-metadata": "^0.2.2",
52
+ "sequelize": "^6.37.8",
53
+ "sequelize-typescript": "^2.1.6",
54
+ "sql-formatter": "^15.8.2"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^24.9.1",
58
+ "oxfmt": "0.57.0",
59
+ "oxlint": "1.72.0",
60
+ "typescript": "^7.0.2"
61
+ },
62
+ "main": "index.js",
63
+ "types": "index.d.ts",
64
+ "type": "module",
65
+ "engines": {
66
+ "node": ">=22.12.0"
67
+ },
68
+ "exports": {
69
+ ".": {
70
+ "types": "./index.d.ts",
71
+ "default": "./index.js"
72
+ },
73
+ "./package.json": "./package.json"
74
+ }
75
+ }