@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/src/index.d.ts ADDED
@@ -0,0 +1,162 @@
1
+ /*!
2
+ * @imqueue/pg-sequelize - Sequelize ORM refines for @imqueue
3
+ *
4
+ * Copyright (c) 2019, imqueue.com <support@imqueue.com>
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
+ * PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+ import { type ILogger } from '@imqueue/rpc';
19
+ import { type SequelizeOptions } from 'sequelize-typescript';
20
+ import { Sequelize } from './BaseModel.js';
21
+ export * from './Graph.js';
22
+ export * from './BaseModel.js';
23
+ export * from './helpers/index.js';
24
+ export * from './decorators/index.js';
25
+ export * from './types/index.js';
26
+ /**
27
+ * Everything {@link database} needs on its first call.
28
+ *
29
+ * @remarks
30
+ * Only the first `database()` call reads this, so treat it as start-up config rather
31
+ * than something to vary per call. Note also that `database()` WRITES to the object
32
+ * it is given — it fills in `connectionString` from the environment and replaces
33
+ * `sequelize.logging` — so a config exported as a module constant and passed at every
34
+ * call site does not stay as written.
35
+ */
36
+ export interface IMQORMOptions {
37
+ /**
38
+ * Where SQL statements are logged.
39
+ *
40
+ * @remarks
41
+ * Falls back to the `@imqueue/rpc` service default, then to `console`, so it can
42
+ * be left out. `@imqueue/async-logger` is the usual choice.
43
+ */
44
+ logger: ILogger;
45
+ /**
46
+ * Postgres connection string.
47
+ *
48
+ * @remarks
49
+ * Optional only because {@link DB_CONN_STR} can supply it. With neither,
50
+ * `database()` throws.
51
+ */
52
+ connectionString?: string;
53
+ /**
54
+ * Options passed through to the Sequelize constructor.
55
+ *
56
+ * @remarks
57
+ * `logging` is the one property `database()` overwrites — see {@link database}
58
+ * for what each value means.
59
+ */
60
+ sequelize: SequelizeOptions;
61
+ /**
62
+ * Directory holding the COMPILED model files.
63
+ *
64
+ * @remarks
65
+ * Walked recursively for `.js` files, so point it at build output rather than at
66
+ * `.ts` sources. Each file must export a symbol named exactly after the file —
67
+ * `Lead.js` must export `Lead` — because that is how the loader picks the model
68
+ * out of the module. A mismatch hands Sequelize `undefined` instead of a model.
69
+ */
70
+ modelsPath: string;
71
+ }
72
+ /**
73
+ * `DB_CONN_STR` from the environment, read once when this module loads.
74
+ *
75
+ * @remarks
76
+ * The fallback {@link database} uses when {@link IMQORMOptions.connectionString} is
77
+ * absent. Because it is captured at import time, changing `process.env` later has no
78
+ * effect on it.
79
+ */
80
+ export declare const DB_CONN_STR: string | undefined;
81
+ /**
82
+ * Whether logged SQL is reformatted across multiple lines. Off by default.
83
+ *
84
+ * @remarks
85
+ * Set `SQL_PRETTIFY` to a positive number to enable. Read once at import, so it is a
86
+ * deployment setting rather than something to toggle at runtime. Affects logging
87
+ * only — never the SQL that is executed.
88
+ */
89
+ export declare const SQL_PRETTIFY: boolean;
90
+ /**
91
+ * Whether logged SQL carries ANSI colour. Off by default.
92
+ *
93
+ * @remarks
94
+ * Set `SQL_COLORIZE` to a positive number to enable. Worth leaving off wherever logs
95
+ * are collected rather than read in a terminal, since the escape sequences end up in
96
+ * the stored line. Independent of {@link SQL_PRETTIFY}.
97
+ */
98
+ export declare const SQL_COLORIZE: boolean;
99
+ /**
100
+ * Reformats a SQL string for logging, when {@link SQL_PRETTIFY} is on.
101
+ *
102
+ * @remarks
103
+ * A pass-through when prettifying is off, so it is always safe to call. Otherwise
104
+ * `sql-formatter` does the work and a handful of substitutions tidy up what it does
105
+ * to Postgres-specific syntax — casts, `&&`, and bind-parameter markers, which the
106
+ * formatter would otherwise break across lines.
107
+ *
108
+ * For logs only. It is not a parser and the result is not guaranteed to be
109
+ * executable.
110
+ *
111
+ * @param sql - Statement as sequelize reports it.
112
+ * @returns The reformatted statement, or `sql` unchanged when prettifying is off.
113
+ */
114
+ export declare function formatSql(sql: string): string;
115
+ /**
116
+ * A sequelize `logging` callback: the SQL, and the timing when benchmarking is on.
117
+ */
118
+ export type SqlLoggingFunction = (sql: string, time?: number) => void;
119
+ /**
120
+ * Connects to the database, loads the models, and returns the Sequelize instance.
121
+ *
122
+ * @remarks
123
+ * A process-wide singleton. The first call does all the work; every call after it
124
+ * returns the cached instance and DOES NOT LOOK AT ITS ARGUMENT — so passing a
125
+ * different config later is silently ignored rather than reconnecting. That is why
126
+ * services can import `database` anywhere and call `database(dbConfig)` freely, and
127
+ * also why there is no way to swap the connection once it is up.
128
+ *
129
+ * The first call resolves its configuration in this order:
130
+ *
131
+ * - `connectionString`, or {@link DB_CONN_STR} from the environment. Neither throws.
132
+ * - `logger`, or the `@imqueue/rpc` service default, or `console`.
133
+ * - `sequelize.logging`: left alone if explicitly falsy, so `false` disables logging;
134
+ * otherwise replaced with this package's formatter, honouring {@link SQL_PRETTIFY}
135
+ * and {@link SQL_COLORIZE}. A function you supply is wrapped rather than discarded,
136
+ * and receives the formatted SQL.
137
+ *
138
+ * Models are then discovered by walking `modelsPath` for compiled `.js` files and
139
+ * taking the export whose name matches the filename — see
140
+ * {@link IMQORMOptions.modelsPath}, since a mismatch there fails in a way the error
141
+ * does not explain. The require is synchronous and CommonJS-scoped, which is what
142
+ * makes the models loadable from an ESM package.
143
+ *
144
+ * @param options - Required on the first call, ignored on every later one.
145
+ * @returns The single Sequelize instance for this process, with models registered.
146
+ * @throws TypeError when the first call has no options, or when no connection string
147
+ * can be resolved from either the options or the environment.
148
+ * @example
149
+ * ```typescript
150
+ * // config.ts — built once at start-up
151
+ * export const dbConfig: IMQORMOptions = {
152
+ * logger,
153
+ * connectionString: process.env.DB_CONN_STR || '',
154
+ * sequelize: toSequelizeConfig(process.env.DB_CONN_STR, process.env.DB_DIALECT),
155
+ * modelsPath: './src/orm/models',
156
+ * };
157
+ *
158
+ * // anywhere in the service — the first call wins, the rest are free
159
+ * const orm = database(dbConfig);
160
+ * ```
161
+ */
162
+ export declare function database(options?: IMQORMOptions): Sequelize;
package/src/index.js ADDED
@@ -0,0 +1,223 @@
1
+ /*!
2
+ * @imqueue/pg-sequelize - Sequelize ORM refines for @imqueue
3
+ *
4
+ * Copyright (c) 2019, imqueue.com <support@imqueue.com>
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
+ * PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+ import { DEFAULT_IMQ_SERVICE_OPTIONS } from '@imqueue/rpc';
19
+ import { createRequire } from 'node:module';
20
+ import { styleText } from 'node:util';
21
+ import { readdirSync, statSync } from 'node:fs';
22
+ import { resolve, sep } from 'node:path';
23
+ import {} from 'sequelize-typescript';
24
+ import { Sequelize } from './BaseModel.js';
25
+ import { isDefined, isOk } from './helpers/js.js';
26
+ /* models exports! */
27
+ export * from './Graph.js';
28
+ export * from './BaseModel.js';
29
+ export * from './helpers/index.js';
30
+ export * from './decorators/index.js';
31
+ export * from './types/index.js';
32
+ const JS_EXT_RX = /\.js$/;
33
+ /**
34
+ * Every file under a directory, recursively.
35
+ *
36
+ * @param dir - Directory to walk.
37
+ * @returns Absolute paths of every file found, directories excluded.
38
+ */
39
+ function walk(dir) {
40
+ let results = [];
41
+ for (let file of readdirSync(dir)) {
42
+ file = resolve(dir, file);
43
+ const stat = statSync(file);
44
+ if (stat && stat.isDirectory()) {
45
+ results = results.concat(walk(file));
46
+ }
47
+ else {
48
+ results.push(file);
49
+ }
50
+ }
51
+ return results;
52
+ }
53
+ /**
54
+ * `DB_CONN_STR` from the environment, read once when this module loads.
55
+ *
56
+ * @remarks
57
+ * The fallback {@link database} uses when {@link IMQORMOptions.connectionString} is
58
+ * absent. Because it is captured at import time, changing `process.env` later has no
59
+ * effect on it.
60
+ */
61
+ export const DB_CONN_STR = process.env.DB_CONN_STR;
62
+ /**
63
+ * Whether logged SQL is reformatted across multiple lines. Off by default.
64
+ *
65
+ * @remarks
66
+ * Set `SQL_PRETTIFY` to a positive number to enable. Read once at import, so it is a
67
+ * deployment setting rather than something to toggle at runtime. Affects logging
68
+ * only — never the SQL that is executed.
69
+ */
70
+ export const SQL_PRETTIFY = +(process.env.SQL_PRETTIFY || 0) > 0;
71
+ /**
72
+ * Whether logged SQL carries ANSI colour. Off by default.
73
+ *
74
+ * @remarks
75
+ * Set `SQL_COLORIZE` to a positive number to enable. Worth leaving off wherever logs
76
+ * are collected rather than read in a terminal, since the escape sequences end up in
77
+ * the stored line. Independent of {@link SQL_PRETTIFY}.
78
+ */
79
+ export const SQL_COLORIZE = +(process.env.SQL_COLORIZE || 0) > 0;
80
+ import { format as sqlFormat } from 'sql-formatter';
81
+ const RX_SQL_NUM_LAYOUT = /\s+(['"]?\d+['"]?,?)\r?\n/g;
82
+ const RX_SQL_NUM_END = /(\d+['"]?)\s+(\))/g;
83
+ const RX_BRK_DBL_AND = /&\s+&/g;
84
+ const RX_BRK_CAST = /\s+(\[|::)(\s+)?/g;
85
+ const RX_BRK_POCKETS = /(\$)\s+(\d)/g;
86
+ const RX_SQL_PREFIX = /Execut(ed|ing) \(default\):/;
87
+ /**
88
+ * Reformats a SQL string for logging, when {@link SQL_PRETTIFY} is on.
89
+ *
90
+ * @remarks
91
+ * A pass-through when prettifying is off, so it is always safe to call. Otherwise
92
+ * `sql-formatter` does the work and a handful of substitutions tidy up what it does
93
+ * to Postgres-specific syntax — casts, `&&`, and bind-parameter markers, which the
94
+ * formatter would otherwise break across lines.
95
+ *
96
+ * For logs only. It is not a parser and the result is not guaranteed to be
97
+ * executable.
98
+ *
99
+ * @param sql - Statement as sequelize reports it.
100
+ * @returns The reformatted statement, or `sql` unchanged when prettifying is off.
101
+ */
102
+ export function formatSql(sql) {
103
+ return SQL_PRETTIFY
104
+ ? sqlFormat(sql)
105
+ .replace(RX_SQL_NUM_LAYOUT, '$1 ')
106
+ .replace(RX_SQL_NUM_END, '$1$2')
107
+ .replace(RX_BRK_DBL_AND, '&&')
108
+ .replace(RX_BRK_CAST, '$1')
109
+ .replace(RX_BRK_POCKETS, '$1$2')
110
+ : sql;
111
+ }
112
+ /**
113
+ * Builds the sequelize `logging` callback, honouring `SQL_PRETTIFY` and
114
+ * `SQL_COLORIZE`.
115
+ *
116
+ * @remarks
117
+ * Accepts either an `ILogger` or a plain callback, and that distinction is
118
+ * load-bearing rather than convenience: a caller who sets
119
+ * `sequelize.logging` to their own function used to have it swapped for this one
120
+ * with the function itself in the logger slot, so the first query to be logged threw
121
+ * `TypeError: logger.log is not a function`. Both shapes now receive the formatted
122
+ * SQL.
123
+ *
124
+ * @param sink - Where to write: a logger, or a callback in sequelize's own shape.
125
+ * @returns The callback to hand to sequelize as `options.logging`.
126
+ */
127
+ const logging = (sink) => (sql, time) => {
128
+ const message = SQL_COLORIZE
129
+ ? `${styleText(['bold', 'yellow'], 'SQL Query:')} ${styleText('cyan', formatSql(sql.replace(RX_SQL_PREFIX, '')))}`
130
+ : `SQL Query: ${formatSql(sql.replace(RX_SQL_PREFIX, ''))}`;
131
+ if (typeof sink === 'function') {
132
+ sink(message, time);
133
+ return;
134
+ }
135
+ sink.log(message, typeof time === 'number' ? `executed in ${time} ms` : '');
136
+ };
137
+ let orm;
138
+ /**
139
+ * Connects to the database, loads the models, and returns the Sequelize instance.
140
+ *
141
+ * @remarks
142
+ * A process-wide singleton. The first call does all the work; every call after it
143
+ * returns the cached instance and DOES NOT LOOK AT ITS ARGUMENT — so passing a
144
+ * different config later is silently ignored rather than reconnecting. That is why
145
+ * services can import `database` anywhere and call `database(dbConfig)` freely, and
146
+ * also why there is no way to swap the connection once it is up.
147
+ *
148
+ * The first call resolves its configuration in this order:
149
+ *
150
+ * - `connectionString`, or {@link DB_CONN_STR} from the environment. Neither throws.
151
+ * - `logger`, or the `@imqueue/rpc` service default, or `console`.
152
+ * - `sequelize.logging`: left alone if explicitly falsy, so `false` disables logging;
153
+ * otherwise replaced with this package's formatter, honouring {@link SQL_PRETTIFY}
154
+ * and {@link SQL_COLORIZE}. A function you supply is wrapped rather than discarded,
155
+ * and receives the formatted SQL.
156
+ *
157
+ * Models are then discovered by walking `modelsPath` for compiled `.js` files and
158
+ * taking the export whose name matches the filename — see
159
+ * {@link IMQORMOptions.modelsPath}, since a mismatch there fails in a way the error
160
+ * does not explain. The require is synchronous and CommonJS-scoped, which is what
161
+ * makes the models loadable from an ESM package.
162
+ *
163
+ * @param options - Required on the first call, ignored on every later one.
164
+ * @returns The single Sequelize instance for this process, with models registered.
165
+ * @throws TypeError when the first call has no options, or when no connection string
166
+ * can be resolved from either the options or the environment.
167
+ * @example
168
+ * ```typescript
169
+ * // config.ts — built once at start-up
170
+ * export const dbConfig: IMQORMOptions = {
171
+ * logger,
172
+ * connectionString: process.env.DB_CONN_STR || '',
173
+ * sequelize: toSequelizeConfig(process.env.DB_CONN_STR, process.env.DB_DIALECT),
174
+ * modelsPath: './src/orm/models',
175
+ * };
176
+ *
177
+ * // anywhere in the service — the first call wins, the rest are free
178
+ * const orm = database(dbConfig);
179
+ * ```
180
+ */
181
+ export function database(options) {
182
+ if (typeof orm !== 'undefined') {
183
+ return orm;
184
+ }
185
+ else if (typeof options === 'undefined') {
186
+ throw new TypeError('First call of database() must provide valid options!');
187
+ }
188
+ if (!options.connectionString) {
189
+ if (!DB_CONN_STR) {
190
+ throw new TypeError('Either environment DB_CONN_STR should be set or ' +
191
+ 'connectionString property given!');
192
+ }
193
+ options.connectionString = DB_CONN_STR;
194
+ }
195
+ if (!options.connectionString) {
196
+ throw new TypeError('Database connection string is required!');
197
+ }
198
+ if (!options.logger) {
199
+ options.logger =
200
+ DEFAULT_IMQ_SERVICE_OPTIONS.logger || console;
201
+ }
202
+ // A caller-supplied function is a logging SINK, not a logger object — it has
203
+ // no `.log`, so casting it to ILogger threw on the first query that got
204
+ // logged. It is still wrapped rather than used raw, so SQL_PRETTIFY and
205
+ // SQL_COLORIZE keep working for this path too.
206
+ options.sequelize.logging =
207
+ !isDefined(options.sequelize.logging) || isOk(options.sequelize.logging)
208
+ ? logging(typeof options.sequelize.logging === 'function'
209
+ ? options.sequelize.logging
210
+ : options.logger)
211
+ : options.sequelize.logging;
212
+ orm = new Sequelize(options.connectionString, options.sequelize);
213
+ // model files are loaded synchronously with a CommonJS require
214
+ // scoped to this module: consumer model builds are CJS today, and
215
+ // require(esm) covers them if they migrate (Node >= 22.12)
216
+ const requireModel = createRequire(import.meta.url);
217
+ orm.addModels(walk(resolve(options.modelsPath))
218
+ .filter(name => JS_EXT_RX.test(name))
219
+ .map(filename => requireModel(filename)[filename.split(sep).reverse()[0].replace(JS_EXT_RX, '')]));
220
+ options.logger.log('Database models initialized...');
221
+ return orm;
222
+ }
223
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,52 @@
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
+ * One page of results together with the size of the whole set.
26
+ *
27
+ * @remarks
28
+ * The envelope a paginated service method returns, so a caller that asked for 20
29
+ * rows can still render "20 of 1,340" without a second round trip. Nothing in this
30
+ * package produces one — it is a shape for your own service methods to declare and
31
+ * fill, which is why `data` is whatever you put in it rather than an array.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * @expose()
36
+ * public async listReservations(
37
+ * page?: PaginationInput,
38
+ * ): Promise<DataPage<Reservation[]>> {
39
+ * const { rows, count } = await Reservation.findAndCountAll(
40
+ * query.toLimitOptions(page),
41
+ * );
42
+ *
43
+ * return { total: count, data: rows };
44
+ * }
45
+ * ```
46
+ */
47
+ export interface DataPage<T> {
48
+ /** Rows matching the query in total, ignoring the page window. */
49
+ total: number;
50
+ /** The page itself. */
51
+ data: T;
52
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DataPage.js.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Which fields to return, nested to match the shape of the relations.
3
+ *
4
+ * @remarks
5
+ * Selection is by KEY PRESENCE, not by value — the single most important thing to
6
+ * know about this type, and the opposite of what `false` suggests. A key names a
7
+ * field to return; `false` means return that column and nothing further; a nested
8
+ * `FieldsInput` on a relation includes the relation and selects within it. So
9
+ * `{ id: false }` DOES return `id`. Omit a field entirely to leave it out, and pass
10
+ * no map at all to get everything the model declares.
11
+ *
12
+ * A value other than `false` is also read as a filter for that column by
13
+ * `query.autoQuery`, which is why the declared value type is `false | FieldsInput`:
14
+ * the two roles are told apart by that `false`.
15
+ *
16
+ * The recursion is what makes it worth a type of its own — one map describes a whole
17
+ * object graph, so a caller asking for a reservation with only its car's id does not
18
+ * need one argument per level. `query.createEntity` threads the nested map down to
19
+ * each related model as it goes, and `autoQuery` turns each nested level into a
20
+ * Sequelize `include`.
21
+ *
22
+ * Note that `autoQuery` MUTATES the map it is given: a column named in the `order`
23
+ * that the map does not mention is added to it as `false`, so ordering cannot break
24
+ * the selection. Do not share one map across calls and expect it to stay as written.
25
+ *
26
+ * It is a class rather than an interface because `@indexed` describes it to
27
+ * `@imqueue/rpc`, which needs a runtime value to attach the description to.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // the reservation with its type and id, and its car's id and model
32
+ * const fields: FieldsInput = {
33
+ * id: false,
34
+ * type: false,
35
+ * car: { id: false, model: false },
36
+ * };
37
+ * ```
38
+ */
39
+ export declare class FieldsInput {
40
+ [fieldName: string]: false | FieldsInput;
41
+ }
@@ -0,0 +1,75 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /*!
8
+ * @imqueue/pg-sequelize - Sequelize ORM refines for @imqueue
9
+ *
10
+ * I'm Queue Software Project
11
+ * Copyright (C) 2025 imqueue.com <support@imqueue.com>
12
+ *
13
+ * This program is free software: you can redistribute it and/or modify
14
+ * it under the terms of the GNU General Public License as published by
15
+ * the Free Software Foundation, either version 3 of the License, or
16
+ * (at your option) any later version.
17
+ *
18
+ * This program is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License
24
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
25
+ *
26
+ * If you want to use this code in a closed source (commercial) project, you can
27
+ * purchase a proprietary commercial license. Please contact us at
28
+ * <support@imqueue.com> to get commercial licensing options.
29
+ */
30
+ import { indexed } from '@imqueue/rpc';
31
+ /**
32
+ * Which fields to return, nested to match the shape of the relations.
33
+ *
34
+ * @remarks
35
+ * Selection is by KEY PRESENCE, not by value — the single most important thing to
36
+ * know about this type, and the opposite of what `false` suggests. A key names a
37
+ * field to return; `false` means return that column and nothing further; a nested
38
+ * `FieldsInput` on a relation includes the relation and selects within it. So
39
+ * `{ id: false }` DOES return `id`. Omit a field entirely to leave it out, and pass
40
+ * no map at all to get everything the model declares.
41
+ *
42
+ * A value other than `false` is also read as a filter for that column by
43
+ * `query.autoQuery`, which is why the declared value type is `false | FieldsInput`:
44
+ * the two roles are told apart by that `false`.
45
+ *
46
+ * The recursion is what makes it worth a type of its own — one map describes a whole
47
+ * object graph, so a caller asking for a reservation with only its car's id does not
48
+ * need one argument per level. `query.createEntity` threads the nested map down to
49
+ * each related model as it goes, and `autoQuery` turns each nested level into a
50
+ * Sequelize `include`.
51
+ *
52
+ * Note that `autoQuery` MUTATES the map it is given: a column named in the `order`
53
+ * that the map does not mention is added to it as `false`, so ordering cannot break
54
+ * the selection. Do not share one map across calls and expect it to stay as written.
55
+ *
56
+ * It is a class rather than an interface because `@indexed` describes it to
57
+ * `@imqueue/rpc`, which needs a runtime value to attach the description to.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // the reservation with its type and id, and its car's id and model
62
+ * const fields: FieldsInput = {
63
+ * id: false,
64
+ * type: false,
65
+ * car: { id: false, model: false },
66
+ * };
67
+ * ```
68
+ */
69
+ let FieldsInput = class FieldsInput {
70
+ };
71
+ FieldsInput = __decorate([
72
+ indexed(() => `[fieldName: string]: false | ${FieldsInput.name}`)
73
+ ], FieldsInput);
74
+ export { FieldsInput };
75
+ //# sourceMappingURL=FieldsInput.js.map