uql-orm 0.42.1 → 0.44.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.
- package/dist/browser/querier/httpQuerier.d.ts +6 -0
- package/dist/browser/querier/httpQuerier.js +1 -1
- package/dist/browser/uql-browser.min.js +2 -2
- package/dist/browser/uql-browser.min.js.map +5 -5
- package/dist/dialect/abstractDialect.js +5 -6
- package/dist/dialect/abstractSqlDialect.d.ts +10 -12
- package/dist/dialect/abstractSqlDialect.js +34 -34
- package/dist/dialect/jsonSql.d.ts +3 -2
- package/dist/dialect/jsonSql.js +7 -5
- package/dist/dialect/vectorCast.d.ts +0 -6
- package/dist/dialect/vectorCast.js +0 -8
- package/dist/entity/decorator/bag.d.ts +3 -0
- package/dist/entity/decorator/members.d.ts +5 -2
- package/dist/entity/index.d.ts +1 -1
- package/dist/entity/index.js +1 -1
- package/dist/entity/metadata/definition.d.ts +15 -13
- package/dist/entity/metadata/definition.js +73 -25
- package/dist/http/handler.d.ts +8 -0
- package/dist/http/handler.js +5 -5
- package/dist/maria/mariaDialect.js +2 -2
- package/dist/migrate/cli.d.ts +5 -0
- package/dist/migrate/cli.js +33 -16
- package/dist/migrate/codegen/entityTypes.d.ts +7 -0
- package/dist/migrate/codegen/entityTypes.js +69 -0
- package/dist/migrate/codegen/index.d.ts +1 -0
- package/dist/migrate/codegen/index.js +1 -0
- package/dist/migrate/drift/driftDetector.js +5 -1
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js +1 -1
- package/dist/migrate/index.d.ts +1 -1
- package/dist/migrate/migrator.d.ts +34 -20
- package/dist/migrate/migrator.js +77 -34
- package/dist/migrate/schemaGenerator.d.ts +1 -5
- package/dist/migrate/schemaGenerator.js +11 -15
- package/dist/schema/canonicalType.d.ts +19 -4
- package/dist/schema/canonicalType.js +114 -164
- package/dist/schema/schemaASTBuilder.d.ts +23 -2
- package/dist/schema/schemaASTBuilder.js +2 -2
- package/dist/schema/schemaASTDiffer.js +6 -2
- package/dist/type/entity.d.ts +36 -6
- package/dist/type/migration.d.ts +14 -1
- package/dist/type/query.d.ts +2 -6
- package/dist/type/queryWhere.d.ts +13 -3
- package/dist/util/field.util.d.ts +19 -8
- package/dist/util/field.util.js +47 -51
- package/dist/util/fieldOption.util.d.ts +79 -0
- package/dist/util/fieldOption.util.js +84 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/util/object.util.d.ts +3 -3
- package/dist/util/object.util.js +3 -3
- package/dist/util/sql.util.d.ts +4 -0
- package/dist/util/sql.util.js +4 -0
- package/package.json +3 -3
package/dist/util/field.util.js
CHANGED
|
@@ -1,56 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
int: true,
|
|
3
|
-
integer: true,
|
|
4
|
-
tinyint: true,
|
|
5
|
-
smallint: true,
|
|
6
|
-
bigint: true,
|
|
7
|
-
float: true,
|
|
8
|
-
float4: true,
|
|
9
|
-
float8: true,
|
|
10
|
-
double: true,
|
|
11
|
-
'double precision': true,
|
|
12
|
-
decimal: true,
|
|
13
|
-
numeric: true,
|
|
14
|
-
real: true,
|
|
15
|
-
serial: true,
|
|
16
|
-
smallserial: true,
|
|
17
|
-
bigserial: true,
|
|
18
|
-
};
|
|
19
|
-
const JSON_COLUMN_TYPES = {
|
|
20
|
-
json: true,
|
|
21
|
-
jsonb: true,
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Checks if a field type is numeric (Number, BigInt, or explicit numeric logical types)
|
|
25
|
-
*/
|
|
26
|
-
export function isNumericType(type) {
|
|
27
|
-
if (type === Number || type === BigInt)
|
|
28
|
-
return true;
|
|
29
|
-
if (typeof type === 'string') {
|
|
30
|
-
return type.toLowerCase() in NUMERIC_COLUMN_TYPES;
|
|
31
|
-
}
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
1
|
+
import { getKeys } from './object.util.js';
|
|
34
2
|
/**
|
|
35
|
-
*
|
|
3
|
+
* The runtime half of the column-type unions in `type/entity.ts`, which TypeScript erases. Each list
|
|
4
|
+
* is checked against its own union, so a type cannot be filed under the wrong family, and
|
|
5
|
+
* {@link UnplacedColumnType} refuses to compile if a new one is filed under none. Nothing here
|
|
6
|
+
* restates the unions: the compile-time side of the same question reads them directly.
|
|
36
7
|
*/
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
8
|
+
export const COLUMN_TYPES_BY_FAMILY = {
|
|
9
|
+
numeric: [
|
|
10
|
+
'int',
|
|
11
|
+
'integer',
|
|
12
|
+
'tinyint',
|
|
13
|
+
'smallint',
|
|
14
|
+
'bigint',
|
|
15
|
+
'float',
|
|
16
|
+
'float4',
|
|
17
|
+
'float8',
|
|
18
|
+
'double',
|
|
19
|
+
'double precision',
|
|
20
|
+
'decimal',
|
|
21
|
+
'numeric',
|
|
22
|
+
'real',
|
|
23
|
+
'serial',
|
|
24
|
+
'smallserial',
|
|
25
|
+
'bigserial',
|
|
26
|
+
],
|
|
27
|
+
string: ['char', 'varchar', 'text', 'uuid'],
|
|
28
|
+
date: ['date', 'time', 'datetime', 'timestamp', 'timestamptz'],
|
|
29
|
+
json: ['json', 'jsonb'],
|
|
30
|
+
blob: ['blob', 'bytea'],
|
|
31
|
+
boolean: ['bool', 'boolean'],
|
|
32
|
+
vector: ['vector', 'halfvec', 'sparsevec'],
|
|
33
|
+
};
|
|
34
|
+
// Constructors and type strings in one map: a logical type is either, and every caller asks the same
|
|
35
|
+
// question of both.
|
|
36
|
+
const FAMILY_OF = new Map([
|
|
37
|
+
[String, 'string'],
|
|
38
|
+
[Number, 'numeric'],
|
|
39
|
+
[BigInt, 'numeric'],
|
|
40
|
+
[Boolean, 'boolean'],
|
|
41
|
+
[Date, 'date'],
|
|
42
|
+
]);
|
|
43
|
+
for (const family of getKeys(COLUMN_TYPES_BY_FAMILY)) {
|
|
44
|
+
for (const columnType of COLUMN_TYPES_BY_FAMILY[family]) {
|
|
45
|
+
FAMILY_OF.set(columnType, family);
|
|
43
46
|
}
|
|
44
|
-
return false;
|
|
45
47
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export function isJsonType(type) {
|
|
50
|
-
if (typeof type === 'string') {
|
|
51
|
-
return type.toLowerCase() in JSON_COLUMN_TYPES;
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
48
|
+
/** The family of a logical field type, or `undefined` where it names none. */
|
|
49
|
+
export function columnFamily(type) {
|
|
50
|
+
return FAMILY_OF.get(typeof type === 'string' ? type.toLowerCase() : type);
|
|
54
51
|
}
|
|
55
52
|
/**
|
|
56
53
|
* Whether the field is the entity's *whole* primary key - the only kind a serial can stand in for,
|
|
@@ -75,6 +72,5 @@ export function isAutoIncrement(field, isPrimaryKey) {
|
|
|
75
72
|
const colType = field.columnType?.toLowerCase();
|
|
76
73
|
if (colType === 'serial' || colType === 'smallserial' || colType === 'bigserial')
|
|
77
74
|
return true;
|
|
78
|
-
|
|
79
|
-
return isPrimaryKey && isNumeric && !field.onInsert && !field.columnType;
|
|
75
|
+
return isPrimaryKey && columnFamily(field.type) === 'numeric' && !field.onInsert && !field.columnType;
|
|
80
76
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { BlobColumnType, BooleanColumnType, DateColumnType, FieldOptions, JsonColumnType, NumericColumnType, QueryRaw, StringColumnType, VectorColumnType } from '../type/index.js';
|
|
2
|
+
import { type ColumnFamily } from './field.util.js';
|
|
3
|
+
/**
|
|
4
|
+
* The column family each field option means anything on, or `'*'` where it applies to every column.
|
|
5
|
+
* Exhaustive over {@link FieldOptions}, so a new option cannot be added without placing it - the
|
|
6
|
+
* discipline `INDEX_FEATURE_LABELS` uses for index features.
|
|
7
|
+
*/
|
|
8
|
+
declare const FIELD_OPTION_FAMILY: {
|
|
9
|
+
readonly name: '*';
|
|
10
|
+
readonly isId: '*';
|
|
11
|
+
readonly type: '*';
|
|
12
|
+
readonly dimensions: 'vector';
|
|
13
|
+
readonly distance: 'vector';
|
|
14
|
+
readonly references: '*';
|
|
15
|
+
readonly onDelete: '*';
|
|
16
|
+
readonly enum: '*';
|
|
17
|
+
readonly virtual: '*';
|
|
18
|
+
readonly updatable: '*';
|
|
19
|
+
readonly eager: '*';
|
|
20
|
+
readonly onInsert: '*';
|
|
21
|
+
readonly onUpdate: '*';
|
|
22
|
+
readonly softDelete: '*';
|
|
23
|
+
readonly columnType: '*';
|
|
24
|
+
readonly length: 'string';
|
|
25
|
+
readonly precision: 'numeric';
|
|
26
|
+
readonly scale: 'numeric';
|
|
27
|
+
readonly nullable: '*';
|
|
28
|
+
readonly unique: '*';
|
|
29
|
+
readonly defaultValue: '*';
|
|
30
|
+
readonly autoIncrement: 'numeric';
|
|
31
|
+
readonly index: '*';
|
|
32
|
+
readonly comment: '*';
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The only options a `virtual` field reaches: it is skipped in DDL and dropped from every insert and
|
|
36
|
+
* update, so the whole persistence half of the options above is dead on one. Stated as what survives
|
|
37
|
+
* rather than on each option that dies, because it is one fact rather than nineteen - and because an
|
|
38
|
+
* option added without a thought then lands on the safe side of it.
|
|
39
|
+
*/
|
|
40
|
+
declare const VIRTUAL_READS: readonly ["type", "virtual", "enum", "eager", "distance"];
|
|
41
|
+
type VirtualRead = (typeof VIRTUAL_READS)[number];
|
|
42
|
+
/**
|
|
43
|
+
* The first option `opts` cannot use, phrased as the tail of `'Entity.field' ...`, or `undefined`
|
|
44
|
+
* where every option applies. The runtime half of the decorators' check, so the imperative API and
|
|
45
|
+
* plain JavaScript reach the same answer.
|
|
46
|
+
*/
|
|
47
|
+
export declare function fieldOptionConflict(opts: FieldOptions): string | undefined;
|
|
48
|
+
/** The family the options put the column in; every family where they name no type to put it in. */
|
|
49
|
+
type FamilyOf<O> = O extends {
|
|
50
|
+
readonly columnType: infer C;
|
|
51
|
+
} ? FamilyOfType<C> : O extends {
|
|
52
|
+
readonly type: infer T;
|
|
53
|
+
} ? FamilyOfType<T> : ColumnFamily;
|
|
54
|
+
/** Read off the column-type unions themselves, which is what `COLUMN_TYPES_BY_FAMILY` is checked against. */
|
|
55
|
+
type FamilyOfType<T> = T extends NumericColumnType | NumberConstructor | BigIntConstructor ? 'numeric' : T extends StringColumnType | StringConstructor ? 'string' : T extends VectorColumnType ? 'vector' : T extends JsonColumnType ? 'json' : T extends DateColumnType | DateConstructor ? 'date' : T extends BooleanColumnType | BooleanConstructor ? 'boolean' : T extends BlobColumnType ? 'blob' : ColumnFamily;
|
|
56
|
+
/** What the field's own values leave unread, matching {@link deadOn} line for line. */
|
|
57
|
+
type DeadOptions<O> = (O extends {
|
|
58
|
+
readonly virtual: QueryRaw;
|
|
59
|
+
} ? Exclude<keyof FieldOptions, VirtualRead> : never) | (O extends {
|
|
60
|
+
readonly isId: true;
|
|
61
|
+
readonly nullable: true;
|
|
62
|
+
} ? 'nullable' : never) | (O extends {
|
|
63
|
+
readonly updatable: false;
|
|
64
|
+
} ? 'onUpdate' : never);
|
|
65
|
+
type Given<O> = Extract<keyof O, keyof FieldOptions>;
|
|
66
|
+
type Offending<O> = {
|
|
67
|
+
[K in Given<O>]: (typeof FIELD_OPTION_FAMILY)[K] extends FamilyOf<O> | '*' ? K extends DeadOptions<O> ? K : never : K;
|
|
68
|
+
}[Given<O>];
|
|
69
|
+
/**
|
|
70
|
+
* Maps every option `O` states but cannot use to `never`, the way `RejectUnknown` maps a typo'd one,
|
|
71
|
+
* so an option that would be silently ignored reads as the same compile error. Resolves to `unknown`
|
|
72
|
+
* - an inert intersection member - when there are none.
|
|
73
|
+
*
|
|
74
|
+
* `@Id` adds `{ nullable?: false }` of its own rather than passing the `isId` it stamps on, which
|
|
75
|
+
* would have to reach `O` as an intersection - and a non-naked `O` in its own constraint stops it
|
|
76
|
+
* inferring from the options at all.
|
|
77
|
+
*/
|
|
78
|
+
export type RejectIncompatible<O> = [Offending<O>] extends [never] ? unknown : Record<Offending<O> & string, never>;
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { columnFamily } from './field.util.js';
|
|
2
|
+
import { getKeys } from './object.util.js';
|
|
3
|
+
/**
|
|
4
|
+
* The column family each field option means anything on, or `'*'` where it applies to every column.
|
|
5
|
+
* Exhaustive over {@link FieldOptions}, so a new option cannot be added without placing it - the
|
|
6
|
+
* discipline `INDEX_FEATURE_LABELS` uses for index features.
|
|
7
|
+
*/
|
|
8
|
+
const FIELD_OPTION_FAMILY = {
|
|
9
|
+
name: '*',
|
|
10
|
+
isId: '*',
|
|
11
|
+
type: '*',
|
|
12
|
+
dimensions: 'vector',
|
|
13
|
+
distance: 'vector',
|
|
14
|
+
references: '*',
|
|
15
|
+
onDelete: '*',
|
|
16
|
+
enum: '*',
|
|
17
|
+
virtual: '*',
|
|
18
|
+
updatable: '*',
|
|
19
|
+
eager: '*',
|
|
20
|
+
onInsert: '*',
|
|
21
|
+
onUpdate: '*',
|
|
22
|
+
softDelete: '*',
|
|
23
|
+
columnType: '*',
|
|
24
|
+
length: 'string',
|
|
25
|
+
precision: 'numeric',
|
|
26
|
+
scale: 'numeric',
|
|
27
|
+
nullable: '*',
|
|
28
|
+
unique: '*',
|
|
29
|
+
defaultValue: '*',
|
|
30
|
+
autoIncrement: 'numeric',
|
|
31
|
+
index: '*',
|
|
32
|
+
comment: '*',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The only options a `virtual` field reaches: it is skipped in DDL and dropped from every insert and
|
|
36
|
+
* update, so the whole persistence half of the options above is dead on one. Stated as what survives
|
|
37
|
+
* rather than on each option that dies, because it is one fact rather than nineteen - and because an
|
|
38
|
+
* option added without a thought then lands on the safe side of it.
|
|
39
|
+
*/
|
|
40
|
+
const VIRTUAL_READS = [
|
|
41
|
+
'type',
|
|
42
|
+
'virtual',
|
|
43
|
+
'enum',
|
|
44
|
+
'eager',
|
|
45
|
+
'distance',
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Whatever leaves `key` unread, named for the message, or `undefined` where the field reads it. Only
|
|
49
|
+
* `nullable: true` contradicts a key: `nullable: false` says what the key already is, and rejecting
|
|
50
|
+
* an accurate statement teaches an author to distrust the check.
|
|
51
|
+
*/
|
|
52
|
+
function deadOn(opts, key) {
|
|
53
|
+
if (opts.virtual !== undefined && !VIRTUAL_READS.some((read) => read === key))
|
|
54
|
+
return 'a virtual field';
|
|
55
|
+
if (opts.isId === true && key === 'nullable' && opts.nullable === true)
|
|
56
|
+
return 'a primary key';
|
|
57
|
+
if (opts.updatable === false && key === 'onUpdate')
|
|
58
|
+
return "a field declared 'updatable: false'";
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The first option `opts` cannot use, phrased as the tail of `'Entity.field' ...`, or `undefined`
|
|
63
|
+
* where every option applies. The runtime half of the decorators' check, so the imperative API and
|
|
64
|
+
* plain JavaScript reach the same answer.
|
|
65
|
+
*/
|
|
66
|
+
export function fieldOptionConflict(opts) {
|
|
67
|
+
const family = columnFamily(opts.columnType ?? opts.type);
|
|
68
|
+
// Walked in table order, not in the order the field happened to be written, so a field with two
|
|
69
|
+
// conflicts always reports the same one. An option no rule knows is a typo, which `RejectUnknown`
|
|
70
|
+
// reports where it can still be spelled right.
|
|
71
|
+
for (const key of getKeys(FIELD_OPTION_FAMILY)) {
|
|
72
|
+
const applies = FIELD_OPTION_FAMILY[key];
|
|
73
|
+
if (opts[key] === undefined)
|
|
74
|
+
continue;
|
|
75
|
+
if (family && applies !== '*' && applies !== family) {
|
|
76
|
+
return `cannot use '${key}': it applies to a ${applies} column, not to a ${family} one`;
|
|
77
|
+
}
|
|
78
|
+
const dead = deadOn(opts, key);
|
|
79
|
+
if (dead) {
|
|
80
|
+
return `cannot use '${key}': it is ignored on ${dead}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
package/dist/util/index.d.ts
CHANGED
package/dist/util/index.js
CHANGED
|
@@ -21,9 +21,9 @@ export declare function isOperatorObject(value: unknown): value is Record<string
|
|
|
21
21
|
export declare function isOperatorOnlyObject(value: unknown): value is Record<string, unknown>;
|
|
22
22
|
export declare function getKeys<T extends object>(obj: T): (keyof T & string)[];
|
|
23
23
|
/**
|
|
24
|
-
* The entity's own name
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* The entity's own name, declared or its class's. `meta.name` holds only what the author wrote, so
|
|
25
|
+
* the fallback is what an entity that named no table is called - which is why the sites spelling this
|
|
26
|
+
* out reached for three different fallbacks, `?? ''` among them, and named nothing at all.
|
|
27
27
|
*/
|
|
28
28
|
export declare function entityName<E>(meta: EntityMeta<E>): string;
|
|
29
29
|
export declare function getFieldKeys<E>(fields: {
|
package/dist/util/object.util.js
CHANGED
|
@@ -53,9 +53,9 @@ export function getKeys(obj) {
|
|
|
53
53
|
return obj ? Object.keys(obj) : [];
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* The entity's own name
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* The entity's own name, declared or its class's. `meta.name` holds only what the author wrote, so
|
|
57
|
+
* the fallback is what an entity that named no table is called - which is why the sites spelling this
|
|
58
|
+
* out reached for three different fallbacks, `?? ''` among them, and named nothing at all.
|
|
59
59
|
*/
|
|
60
60
|
export function entityName(meta) {
|
|
61
61
|
return meta.name ?? meta.entity.name;
|
package/dist/util/sql.util.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ export declare function qualifyName(name: string, schema?: string): string;
|
|
|
25
25
|
*
|
|
26
26
|
* The kind goes last, as Postgres spells its own (`users_pkey`, `users_email_idx`), so a table's
|
|
27
27
|
* constraints sort together under the table they belong to.
|
|
28
|
+
*
|
|
29
|
+
* Not overridable, deliberately: a `NamingStrategy` hook would have to reach the eight call sites
|
|
30
|
+
* these have, an introspector and two builders among them, to replace a name any declaration can
|
|
31
|
+
* already set outright with `name:`. Worth revisiting only for a case that option cannot express.
|
|
28
32
|
*/
|
|
29
33
|
export declare function derivedConstraintName(table: string, parts: readonly (string | number)[], kind: ConstraintKind): string;
|
|
30
34
|
/** The kinds of derived name, which is also what `indexNameStem` strips to compare them. */
|
package/dist/util/sql.util.js
CHANGED
|
@@ -74,6 +74,10 @@ const NAME_HASH_LENGTH = 6;
|
|
|
74
74
|
*
|
|
75
75
|
* The kind goes last, as Postgres spells its own (`users_pkey`, `users_email_idx`), so a table's
|
|
76
76
|
* constraints sort together under the table they belong to.
|
|
77
|
+
*
|
|
78
|
+
* Not overridable, deliberately: a `NamingStrategy` hook would have to reach the eight call sites
|
|
79
|
+
* these have, an introspector and two builders among them, to replace a name any declaration can
|
|
80
|
+
* already set outright with `name:`. Worth revisiting only for a case that option cannot express.
|
|
77
81
|
*/
|
|
78
82
|
export function derivedConstraintName(table, parts, kind) {
|
|
79
83
|
const body = parts.length ? `${table}${TABLE_SEPARATOR}${parts.join('_')}` : table;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uql-orm",
|
|
3
3
|
"homepage": "https://uql-orm.dev",
|
|
4
|
-
"description": "JSON-native ORM for Node.js, Bun and Deno. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
4
|
+
"description": "JSON-native TypeScript ORM for Node.js, Bun and Deno. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.44.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=24"
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"express": "^5.2.1",
|
|
146
146
|
"mariadb": "^3.5.4",
|
|
147
147
|
"mongodb": "^7.6.0",
|
|
148
|
-
"mysql2": "^3.24.
|
|
148
|
+
"mysql2": "^3.24.4",
|
|
149
149
|
"pg": "^8.23.0",
|
|
150
150
|
"pg-query-stream": "^4.17.0",
|
|
151
151
|
"rxjs": "^7.8.2",
|