ts-prorm-orm 1.2.2 → 2.0.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/CHANGELOG.md +209 -0
- package/README.md +32 -24
- package/dist/compliance/index.d.ts +2 -0
- package/dist/compliance/index.js +13 -1
- package/dist/connection-manager.js +13 -1
- package/dist/core/expressions.d.ts +58 -0
- package/dist/core/expressions.js +83 -0
- package/dist/core/hooks-manager.d.ts +179 -0
- package/dist/core/hooks-manager.js +291 -0
- package/dist/core/types.d.ts +235 -0
- package/dist/core/types.js +9 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +11 -1
- package/dist/diagrams/chen-diagram.d.ts +15 -12
- package/dist/diagrams/chen-diagram.js +76 -85
- package/dist/diagrams/class-diagram.d.ts +9 -8
- package/dist/diagrams/class-diagram.js +60 -82
- package/dist/diagrams/core/index.d.ts +13 -0
- package/dist/diagrams/core/index.js +33 -0
- package/dist/diagrams/core/layout.d.ts +104 -0
- package/dist/diagrams/core/layout.js +223 -0
- package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
- package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
- package/dist/diagrams/core/theme.d.ts +84 -0
- package/dist/diagrams/core/theme.js +62 -0
- package/dist/diagrams/dependency-diagram.d.ts +15 -14
- package/dist/diagrams/dependency-diagram.js +71 -105
- package/dist/diagrams/er-diagram.d.ts +13 -26
- package/dist/diagrams/er-diagram.js +180 -259
- package/dist/diagrams/flow-diagram.d.ts +16 -11
- package/dist/diagrams/flow-diagram.js +96 -91
- package/dist/diagrams/gantt-diagram.d.ts +10 -5
- package/dist/diagrams/gantt-diagram.js +77 -103
- package/dist/diagrams/index-diagram.d.ts +10 -10
- package/dist/diagrams/index-diagram.js +106 -116
- package/dist/diagrams/index.d.ts +6 -9
- package/dist/diagrams/index.js +9 -24
- package/dist/diagrams/migration-diagram.d.ts +8 -4
- package/dist/diagrams/migration-diagram.js +189 -161
- package/dist/diagrams/model-diagram.d.ts +34 -34
- package/dist/diagrams/model-diagram.js +106 -485
- package/dist/diagrams/package-diagram.d.ts +9 -6
- package/dist/diagrams/package-diagram.js +64 -101
- package/dist/diagrams/relational-diagram.d.ts +12 -10
- package/dist/diagrams/relational-diagram.js +87 -114
- package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
- package/dist/diagrams/schemadoc-diagram.js +71 -93
- package/dist/diagrams/sequence-diagram.d.ts +10 -10
- package/dist/diagrams/sequence-diagram.js +64 -89
- package/dist/diagrams/state-diagram.d.ts +10 -9
- package/dist/diagrams/state-diagram.js +69 -92
- package/dist/diagrams/tree-diagram.d.ts +11 -5
- package/dist/diagrams/tree-diagram.js +41 -65
- package/dist/dialects/clickhouse/index.js +15 -0
- package/dist/dialects/cockroachdb/index.d.ts +1 -1
- package/dist/dialects/cockroachdb/index.js +32 -63
- package/dist/dialects/db2/index.js +23 -8
- package/dist/dialects/dialect.d.ts +29 -5
- package/dist/dialects/duckdb/index.js +9 -2
- package/dist/dialects/hana/index.js +22 -5
- package/dist/dialects/lock-clause-helper.d.ts +167 -0
- package/dist/dialects/lock-clause-helper.js +316 -0
- package/dist/dialects/mariadb/index.d.ts +7 -4
- package/dist/dialects/mariadb/index.js +36 -60
- package/dist/dialects/mssql/index.js +34 -3
- package/dist/dialects/mysql/index.d.ts +1 -1
- package/dist/dialects/mysql/index.js +17 -45
- package/dist/dialects/oracle/index.d.ts +14 -3
- package/dist/dialects/oracle/index.js +66 -36
- package/dist/dialects/order-expression-helper.d.ts +72 -0
- package/dist/dialects/order-expression-helper.js +154 -0
- package/dist/dialects/partial-index.d.ts +52 -0
- package/dist/dialects/partial-index.js +251 -0
- package/dist/dialects/postgres/index.d.ts +1 -1
- package/dist/dialects/postgres/index.js +43 -68
- package/dist/dialects/redshift/index.js +9 -2
- package/dist/dialects/snowflake/index.js +17 -0
- package/dist/dialects/spanner/index.js +7 -2
- package/dist/dialects/sqlite/driver.d.ts +55 -0
- package/dist/dialects/sqlite/driver.js +102 -0
- package/dist/dialects/sqlite/index.d.ts +1 -1
- package/dist/dialects/sqlite/index.js +49 -27
- package/dist/graph/base-graph-dialect.d.ts +24 -3
- package/dist/graph/base-graph-dialect.js +43 -2
- package/dist/graph/dgraph/index.js +6 -0
- package/dist/graph/gremlin/index.d.ts +6 -0
- package/dist/graph/gremlin/index.js +12 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/neo4j/index.d.ts +2 -0
- package/dist/graph/neo4j/index.js +6 -1
- package/dist/graph/types.d.ts +12 -1
- package/dist/index.d.ts +13 -4
- package/dist/index.js +54 -7
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.js +23 -0
- package/dist/logging/query-logging.d.ts +82 -0
- package/dist/logging/query-logging.js +102 -0
- package/dist/models/decorators.d.ts +39 -3
- package/dist/models/decorators.js +74 -0
- package/dist/models/eager-load.d.ts +99 -0
- package/dist/models/eager-load.js +348 -5
- package/dist/models/indexes.d.ts +3 -2
- package/dist/models/indexes.js +7 -1
- package/dist/models/model.js +69 -43
- package/dist/prorm.d.ts +175 -409
- package/dist/prorm.js +1142 -557
- package/dist/query-builders/order-limit-builder.js +12 -10
- package/dist/query-builders/sql-compiler.d.ts +10 -3
- package/dist/query-builders/sql-compiler.js +14 -43
- package/dist/query-interface.d.ts +2 -1
- package/dist/sql-constants.d.ts +44 -0
- package/dist/sql-constants.js +138 -1
- package/dist/types/index.d.ts +53 -17
- package/dist/types/index.js +10 -15
- package/dist/types/query-types.d.ts +26 -0
- package/dist/types/query-types.js +30 -0
- package/package.json +32 -5
- package/dist/decorators/belongs-to-many.js +0 -115
- package/dist/decorators/belongs-to.js +0 -115
- package/dist/decorators/has-many.js +0 -127
- package/dist/decorators/has-one.js +0 -116
- package/dist/diagrams/palette.d.ts +0 -138
- package/dist/diagrams/palette.js +0 -194
- package/dist/hooks/hooks-manager.d.ts +0 -189
- package/dist/hooks/hooks-manager.js +0 -350
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.js +0 -37
- /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
- /package/dist/{logging.js → logging/logger.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -40,13 +40,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
-
exports.
|
|
44
|
-
exports.
|
|
45
|
-
exports.
|
|
46
|
-
exports.
|
|
47
|
-
exports.
|
|
48
|
-
exports.
|
|
49
|
-
exports.sqlSum = exports.sqlReverse = void 0;
|
|
43
|
+
exports.JSONB = exports.JSON = exports.UUIDV4 = exports.UUID = exports.TIME = exports.NOW = exports.DATEONLY = exports.DATE = exports.BOOLEAN = exports.DECIMAL = exports.DOUBLE = exports.FLOAT = exports.BIGINT = exports.INTEGER = exports.TEXT = exports.CHAR = exports.VARCHAR = exports.STRING = exports.BelongsToMany = exports.BelongsTo = exports.HasMany = exports.HasOne = exports.clearMetadata = exports.getModelAttributes = exports.getAttributeMetadata = exports.getModelMetadata = exports.Comment = exports.Unique = exports.Default = exports.NotNull = exports.AutoIncrement = exports.PrimaryKey = exports.AllowNull = exports.Column = exports.Attribute = exports.getInheritedAttributeMetadata = exports.isAbstractModel = exports.AbstractModel = exports.Table = exports.Model = exports.AbstractDataType = exports.DataTypes = exports.createConnectionManager = exports.ConnectionManager = exports.StreamIterator = exports.BatchTransform = exports.FilterTransform = exports.MapTransform = exports.QueryTypes = exports.Prorm = void 0;
|
|
44
|
+
exports.random = exports.desc = exports.asc = exports.overlap = exports.contains = exports.isNotNull = exports.isNull = exports.notBetween = exports.between = exports.notIn = exports.inOp = exports.in = exports.notIRegexp = exports.iRegexp = exports.notRegexp = exports.regexp = exports.match = exports.notSubstring = exports.substring = exports.notEndsWith = exports.endsWith = exports.notStartsWith = exports.startsWith = exports.notILike = exports.iLike = exports.notLike = exports.like = exports.lte = exports.lt = exports.gte = exports.gt = exports.ne = exports.eq = exports.not = exports.or = exports.and = exports.where = exports.normalizeOperatorKeys = exports.operatorToWhereKey = exports.getOperatorString = exports.OpAliases = exports.Operators = exports.Op = exports.GEOGRAPHY = exports.GEOMETRY = exports.ARRAY = exports.ENUM = exports.VARBINARY = exports.BINARY = exports.BLOB = void 0;
|
|
45
|
+
exports.coalesce = exports.isEmpty = exports.formatWhere = exports.escapeId = exports.escapeString = exports.formatValue = exports.formatValues = exports.isValidUUID = exports.generateShortUUID = exports.generateUUID = exports.omit = exports.pick = exports.merge = exports.cloneDeep = exports.singularize = exports.pluralize = exports.snakeCase = exports.camelize = exports.kebabToCamel = exports.camelToKebab = exports.snakeToCamel = exports.camelToSnake = exports.ModelManager = exports.ScopeManager = exports.createPool = exports.PooledConnection = exports.DatabaseConnectionPool = exports.ConnectionPool = exports.createMSSQLDialect = exports.MSSQLDialect = exports.createOracleDialect = exports.OracleDialect = exports.SQLiteDialect = exports.safeIdent = exports.defaultEdgeLabel = exports.deriveAssociationEdge = exports.normalizeWhere = exports.ParamBag = exports.GraphCapabilityError = exports.registerGraphDialects = exports.GRAPH_DIALECTS = exports.DgraphGraphDialect = exports.GremlinGraphDialect = exports.Neo4jGraphDialect = exports.BaseGraphDialect = exports.DialectRegistry = exports.BaseDialect = exports.ReplicaManager = exports.Transaction = exports.isOrderExpression = void 0;
|
|
46
|
+
exports.isEmptyResultError = exports.isConstraintError = exports.isConnectionError = exports.isValidationError = exports.isPrormError = exports.ErrorCodes = exports.EmptyResultError = exports.EagerLoadError = exports.AssociationError = exports.BulkRecordError = exports.ResourceLockedError = exports.TimeoutError = exports.ExclusionConstraintError = exports.ForeignKeyConstraintError = exports.UniqueConstraintError = exports.ValidationError = exports.DatabaseError = exports.ConnectionError = exports.PrormError = exports.setDefaultLogger = exports.getDefaultLogger = exports.createSilentLogger = exports.createLogger = exports.LogLevelStrings = exports.LogLevel = exports.Logger = exports.createQueryInterface = exports.CreateQueryInterface = exports.stringUtils = exports.regex = exports.truncateStr = exports.padEnd = exports.padStart = exports.trimEnd = exports.trimStart = exports.rtrim = exports.ltrim = exports.trim = exports.capitalizeWords = exports.capitalize = exports.lowerCase = exports.upperCase = exports.spliceStr = exports.formatDefaultValue = exports.toDefaultValue = exports.removeTicks = exports.addTicks = exports.escapeLike = exports.pad = exports.truncate = void 0;
|
|
47
|
+
exports.CaseBuilder = exports.arrayAgg = exports.stringAgg = exports.max = exports.min = exports.avg = exports.countDistinct = exports.count = exports.IsolationLevelEnum = exports.UnsupportedForeignKeyChecksError = exports.getForeignKeyChecksSQL = exports.getConstantsForDialect = exports.SQLITE = exports.POSTGRES = exports.MARIADB = exports.MYSQL = exports.SQL = exports.createSQLiteAdvanced = exports.SQLiteAdvanced = exports.PRIVILEGE_LEVELS = exports.UserManager = exports.DatabaseSecurityDecorator = exports.Database = exports.buildCreateFullTextIndexSQL = exports.buildDropPolicySQL = exports.buildCreatePolicySQL = exports.buildEnableRowLevelSecuritySQL = exports.buildDropTriggerSQL = exports.buildCreateTriggerStatements = exports.buildDropSequenceSQL = exports.buildCreateSequenceSQL = exports.UnsupportedSchemaObjectError = exports.buildOptionsClause = exports.KNOWN_FDWS = exports.ForeignDataManager = exports.generateERDiagramFromFile = exports.generateModelDiagramFromFile = exports.generateERDiagram = exports.generateModelDiagram = exports.ERDiagram = exports.ModelDiagram = exports.removeGeneratedModel = exports.listModels = exports.setOutputDir = exports.getOutputDir = exports.configureCLI = exports.generateModels = exports.model = exports.CLI = exports.utils = void 0;
|
|
48
|
+
exports.windowFn = exports.maxOver = exports.minOver = exports.countOver = exports.avgOver = exports.sumOver = exports.nthValue = exports.lastValue = exports.firstValue = exports.lead = exports.lag = exports.ntile = exports.cumeDist = exports.percentRank = exports.denseRank = exports.rank = exports.rowNumber = exports.WindowFunctionBuilder = exports.split = exports.rpad = exports.lpad = exports.replace = exports.length = exports.lower = exports.upper = exports.concat = exports.least = exports.greatest = exports.mod = exports.sign = exports.abs = exports.sqrt = exports.power = exports.floor = exports.ceil = exports.round = exports.jsonTypeOf = exports.jsonKeys = exports.jsonExtract = exports.fullTextRank = exports.fullTextMatch = exports.currentTimestamp = exports.currentDate = exports.dateDiff = exports.dateSub = exports.dateAdd = exports.dateTrunc = exports.caseOf = exports.caseWhen = exports.SimpleCaseBuilder = void 0;
|
|
49
|
+
exports.resolveRelations = exports.parsePrismaSchema = exports.convertPrismaSchema = exports.addAuditHistoryToInstance = exports.addAuditHistoryToModel = exports.getAuditLogger = exports.setAuditLogger = exports.AuditLogger = exports.createRedisClusterCache = exports.RedisClusterCache = exports.AbstractCacheManager = exports.sqlSum = exports.sqlReverse = exports.sqlRepeat = exports.sqlNow = exports.sqlFormatDate = exports.sqlJsonHasKey = exports.sqlJsonContains = exports.sqlRtrim = exports.sqlLtrim = exports.sqlTrim = exports.sqlSubstring = exports.sqlTruncate = exports.sqlRandom = exports.NullsOrder = void 0;
|
|
50
50
|
// Re-export Prorm class and query types
|
|
51
51
|
var prorm_1 = require("./prorm");
|
|
52
52
|
Object.defineProperty(exports, "Prorm", { enumerable: true, get: function () { return prorm_1.Prorm; } });
|
|
@@ -73,6 +73,9 @@ Object.defineProperty(exports, "Model", { enumerable: true, get: function () { r
|
|
|
73
73
|
// Export decorators
|
|
74
74
|
var decorators_1 = require("./models/decorators");
|
|
75
75
|
Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return decorators_1.Table; } });
|
|
76
|
+
Object.defineProperty(exports, "AbstractModel", { enumerable: true, get: function () { return decorators_1.AbstractModel; } });
|
|
77
|
+
Object.defineProperty(exports, "isAbstractModel", { enumerable: true, get: function () { return decorators_1.isAbstractModel; } });
|
|
78
|
+
Object.defineProperty(exports, "getInheritedAttributeMetadata", { enumerable: true, get: function () { return decorators_1.getInheritedAttributeMetadata; } });
|
|
76
79
|
Object.defineProperty(exports, "Attribute", { enumerable: true, get: function () { return decorators_1.Attribute; } });
|
|
77
80
|
Object.defineProperty(exports, "Column", { enumerable: true, get: function () { return decorators_1.Column; } });
|
|
78
81
|
Object.defineProperty(exports, "AllowNull", { enumerable: true, get: function () { return decorators_1.AllowNull; } });
|
|
@@ -137,6 +140,7 @@ Object.defineProperty(exports, "Operators", { enumerable: true, get: function ()
|
|
|
137
140
|
Object.defineProperty(exports, "OpAliases", { enumerable: true, get: function () { return operators_2.Operators; } });
|
|
138
141
|
Object.defineProperty(exports, "getOperatorString", { enumerable: true, get: function () { return operators_2.getOperatorString; } });
|
|
139
142
|
Object.defineProperty(exports, "operatorToWhereKey", { enumerable: true, get: function () { return operators_2.operatorToWhereKey; } });
|
|
143
|
+
Object.defineProperty(exports, "normalizeOperatorKeys", { enumerable: true, get: function () { return operators_2.normalizeOperatorKeys; } });
|
|
140
144
|
// Core where helpers
|
|
141
145
|
Object.defineProperty(exports, "where", { enumerable: true, get: function () { return operators_2.where; } });
|
|
142
146
|
Object.defineProperty(exports, "and", { enumerable: true, get: function () { return operators_2.and; } });
|
|
@@ -211,6 +215,16 @@ Object.defineProperty(exports, "registerGraphDialects", { enumerable: true, get:
|
|
|
211
215
|
const dialect_2 = require("./dialects/dialect");
|
|
212
216
|
const graph_2 = require("./graph");
|
|
213
217
|
(0, graph_2.registerGraphDialects)(dialect_2.DialectRegistry);
|
|
218
|
+
// The rest of './graph': the typed error thrown for relational-only features
|
|
219
|
+
// on a graph backend, plus the where/edge helpers a custom graph dialect needs.
|
|
220
|
+
// None of these names collide with the SQL-side exports above.
|
|
221
|
+
var graph_3 = require("./graph");
|
|
222
|
+
Object.defineProperty(exports, "GraphCapabilityError", { enumerable: true, get: function () { return graph_3.GraphCapabilityError; } });
|
|
223
|
+
Object.defineProperty(exports, "ParamBag", { enumerable: true, get: function () { return graph_3.ParamBag; } });
|
|
224
|
+
Object.defineProperty(exports, "normalizeWhere", { enumerable: true, get: function () { return graph_3.normalizeWhere; } });
|
|
225
|
+
Object.defineProperty(exports, "deriveAssociationEdge", { enumerable: true, get: function () { return graph_3.deriveAssociationEdge; } });
|
|
226
|
+
Object.defineProperty(exports, "defaultEdgeLabel", { enumerable: true, get: function () { return graph_3.defaultEdgeLabel; } });
|
|
227
|
+
Object.defineProperty(exports, "safeIdent", { enumerable: true, get: function () { return graph_3.safeIdent; } });
|
|
214
228
|
// Re-export SQLite dialect
|
|
215
229
|
var sqlite_1 = require("./dialects/sqlite");
|
|
216
230
|
Object.defineProperty(exports, "SQLiteDialect", { enumerable: true, get: function () { return sqlite_1.SQLiteDialect; } });
|
|
@@ -393,6 +407,8 @@ Object.defineProperty(exports, "MARIADB", { enumerable: true, get: function () {
|
|
|
393
407
|
Object.defineProperty(exports, "POSTGRES", { enumerable: true, get: function () { return sql_constants_1.POSTGRES; } });
|
|
394
408
|
Object.defineProperty(exports, "SQLITE", { enumerable: true, get: function () { return sql_constants_1.SQLITE; } });
|
|
395
409
|
Object.defineProperty(exports, "getConstantsForDialect", { enumerable: true, get: function () { return sql_constants_1.getConstantsForDialect; } });
|
|
410
|
+
Object.defineProperty(exports, "getForeignKeyChecksSQL", { enumerable: true, get: function () { return sql_constants_1.getForeignKeyChecksSQL; } });
|
|
411
|
+
Object.defineProperty(exports, "UnsupportedForeignKeyChecksError", { enumerable: true, get: function () { return sql_constants_1.UnsupportedForeignKeyChecksError; } });
|
|
396
412
|
Object.defineProperty(exports, "IsolationLevelEnum", { enumerable: true, get: function () { return sql_constants_1.IsolationLevelEnum; } });
|
|
397
413
|
// Re-export NoSQL stores (MongoDB, Redis, DynamoDB) — separate from the SQL
|
|
398
414
|
// dialects since they don't share the SQL-shaped Dialect interface
|
|
@@ -481,6 +497,37 @@ Object.defineProperty(exports, "sqlNow", { enumerable: true, get: function () {
|
|
|
481
497
|
Object.defineProperty(exports, "sqlRepeat", { enumerable: true, get: function () { return functions_2.repeat; } });
|
|
482
498
|
Object.defineProperty(exports, "sqlReverse", { enumerable: true, get: function () { return functions_2.reverse; } });
|
|
483
499
|
Object.defineProperty(exports, "sqlSum", { enumerable: true, get: function () { return functions_2.sum; } });
|
|
500
|
+
// Re-export the query-result cache (L1 in-memory + L2 Redis Cluster).
|
|
501
|
+
// Five of this module's type names are already taken at the package root by
|
|
502
|
+
// unrelated declarations that consumers may import today, so those five keep
|
|
503
|
+
// their existing meaning and the cache module's versions are aliased:
|
|
504
|
+
// CacheEntry -> ./query-optimizers' prepared-statement entry
|
|
505
|
+
// CacheManagerOptions, -> ./types' (older, flatter) cache option shapes
|
|
506
|
+
// L1CacheOptions,
|
|
507
|
+
// RedisClusterCacheOptions,
|
|
508
|
+
// RedisClusterNode
|
|
509
|
+
// The remaining names don't collide and are exported unchanged.
|
|
510
|
+
var cache_1 = require("./cache");
|
|
511
|
+
Object.defineProperty(exports, "AbstractCacheManager", { enumerable: true, get: function () { return cache_1.AbstractCacheManager; } });
|
|
512
|
+
Object.defineProperty(exports, "RedisClusterCache", { enumerable: true, get: function () { return cache_1.RedisClusterCache; } });
|
|
513
|
+
Object.defineProperty(exports, "createRedisClusterCache", { enumerable: true, get: function () { return cache_1.createRedisClusterCache; } });
|
|
514
|
+
// Re-export the audit log (persists model changes to a database table).
|
|
515
|
+
// Note the neighbours: `Audit`/`getAuditLog`/`AuditEntry` (the in-memory
|
|
516
|
+
// decorator, from './decorators') and `ComplianceAuditTrail` (from
|
|
517
|
+
// './compliance') are different features that happen to share the prefix.
|
|
518
|
+
// No name here collides with either, so all are exported as-is.
|
|
519
|
+
var audit_1 = require("./audit");
|
|
520
|
+
Object.defineProperty(exports, "AuditLogger", { enumerable: true, get: function () { return audit_1.AuditLogger; } });
|
|
521
|
+
Object.defineProperty(exports, "setAuditLogger", { enumerable: true, get: function () { return audit_1.setAuditLogger; } });
|
|
522
|
+
Object.defineProperty(exports, "getAuditLogger", { enumerable: true, get: function () { return audit_1.getAuditLogger; } });
|
|
523
|
+
Object.defineProperty(exports, "addAuditHistoryToModel", { enumerable: true, get: function () { return audit_1.addAuditHistoryToModel; } });
|
|
524
|
+
Object.defineProperty(exports, "addAuditHistoryToInstance", { enumerable: true, get: function () { return audit_1.addAuditHistoryToInstance; } });
|
|
525
|
+
// Re-export the Prisma schema converter (pure functions; the CLI's
|
|
526
|
+
// `prisma:import` command owns the filesystem side).
|
|
527
|
+
var prisma_migrate_1 = require("./prisma-migrate");
|
|
528
|
+
Object.defineProperty(exports, "convertPrismaSchema", { enumerable: true, get: function () { return prisma_migrate_1.convertPrismaSchema; } });
|
|
529
|
+
Object.defineProperty(exports, "parsePrismaSchema", { enumerable: true, get: function () { return prisma_migrate_1.parsePrismaSchema; } });
|
|
530
|
+
Object.defineProperty(exports, "resolveRelations", { enumerable: true, get: function () { return prisma_migrate_1.resolveRelations; } });
|
|
484
531
|
// Export default ORM configuration
|
|
485
532
|
const prorm_2 = require("./prorm");
|
|
486
533
|
const data_types_3 = require("./models/data-types");
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging.
|
|
3
|
+
*
|
|
4
|
+
* - `logger` the general-purpose levelled Logger (debug/info/warn/error)
|
|
5
|
+
* - `query-logging` query logging in the shape of Sequelize's `logging` option
|
|
6
|
+
*/
|
|
7
|
+
export { LogLevel, LogLevelStrings, Logger, createLogger, createSilentLogger, getDefaultLogger, setDefaultLogger, resetDefaultLogger, } from './logger';
|
|
8
|
+
export type { LoggerOptions, LogEntry, LoggerEvents } from './logger';
|
|
9
|
+
export { logQuery, resolveQueryLogger, formatQueryLog, defaultQueryLogger, } from './query-logging';
|
|
10
|
+
export type { LoggingOption, QueryLogFunction, QueryLogContext, QueryLogOptions, } from './query-logging';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Logging.
|
|
4
|
+
*
|
|
5
|
+
* - `logger` the general-purpose levelled Logger (debug/info/warn/error)
|
|
6
|
+
* - `query-logging` query logging in the shape of Sequelize's `logging` option
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.defaultQueryLogger = exports.formatQueryLog = exports.resolveQueryLogger = exports.logQuery = exports.resetDefaultLogger = exports.setDefaultLogger = exports.getDefaultLogger = exports.createSilentLogger = exports.createLogger = exports.Logger = exports.LogLevelStrings = exports.LogLevel = void 0;
|
|
10
|
+
var logger_1 = require("./logger");
|
|
11
|
+
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_1.LogLevel; } });
|
|
12
|
+
Object.defineProperty(exports, "LogLevelStrings", { enumerable: true, get: function () { return logger_1.LogLevelStrings; } });
|
|
13
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
|
|
14
|
+
Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
|
|
15
|
+
Object.defineProperty(exports, "createSilentLogger", { enumerable: true, get: function () { return logger_1.createSilentLogger; } });
|
|
16
|
+
Object.defineProperty(exports, "getDefaultLogger", { enumerable: true, get: function () { return logger_1.getDefaultLogger; } });
|
|
17
|
+
Object.defineProperty(exports, "setDefaultLogger", { enumerable: true, get: function () { return logger_1.setDefaultLogger; } });
|
|
18
|
+
Object.defineProperty(exports, "resetDefaultLogger", { enumerable: true, get: function () { return logger_1.resetDefaultLogger; } });
|
|
19
|
+
var query_logging_1 = require("./query-logging");
|
|
20
|
+
Object.defineProperty(exports, "logQuery", { enumerable: true, get: function () { return query_logging_1.logQuery; } });
|
|
21
|
+
Object.defineProperty(exports, "resolveQueryLogger", { enumerable: true, get: function () { return query_logging_1.resolveQueryLogger; } });
|
|
22
|
+
Object.defineProperty(exports, "formatQueryLog", { enumerable: true, get: function () { return query_logging_1.formatQueryLog; } });
|
|
23
|
+
Object.defineProperty(exports, "defaultQueryLogger", { enumerable: true, get: function () { return query_logging_1.defaultQueryLogger; } });
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query logging, following the Sequelize logger's shape.
|
|
3
|
+
*
|
|
4
|
+
* Sequelize's contract is small and widely known, so this matches it rather
|
|
5
|
+
* than inventing another:
|
|
6
|
+
*
|
|
7
|
+
* logging: false no output
|
|
8
|
+
* logging: true console.log
|
|
9
|
+
* logging: console.log any function, called as (sql, timing)
|
|
10
|
+
* benchmark: true append the elapsed time
|
|
11
|
+
* logQueryParameters: true append the bound values
|
|
12
|
+
*
|
|
13
|
+
* A per-query `logging` overrides the instance-level one, so a single noisy
|
|
14
|
+
* call can be traced without turning logging on globally - and, symmetrically,
|
|
15
|
+
* one call can be silenced with `logging: false`.
|
|
16
|
+
*
|
|
17
|
+
* This module exists because the resolution logic was previously inlined at
|
|
18
|
+
* four call sites and only some of them ran it: `count`, `bulkCreate`,
|
|
19
|
+
* `increment` and the aggregates emitted nothing at all, so turning logging on
|
|
20
|
+
* showed an incomplete picture of what the ORM was doing.
|
|
21
|
+
*/
|
|
22
|
+
/** What `logging` accepts, at instance or query level. */
|
|
23
|
+
export type LoggingOption = boolean | QueryLogFunction | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* A logging callback.
|
|
26
|
+
*
|
|
27
|
+
* `timing` is the elapsed milliseconds; it is passed whenever the caller
|
|
28
|
+
* measured the query, which is always here. Sequelize only guarantees it under
|
|
29
|
+
* `benchmark: true`, so treat it as optional for compatibility.
|
|
30
|
+
*/
|
|
31
|
+
export type QueryLogFunction = (sql: string, timing?: number) => void;
|
|
32
|
+
/** Everything that shapes one log line. */
|
|
33
|
+
export interface QueryLogContext {
|
|
34
|
+
/** The SQL that was executed. */
|
|
35
|
+
sql: string;
|
|
36
|
+
/** Elapsed milliseconds. */
|
|
37
|
+
duration: number;
|
|
38
|
+
/** Values bound to the statement, when known. */
|
|
39
|
+
parameters?: unknown[];
|
|
40
|
+
/** The model this query was issued for, when applicable. */
|
|
41
|
+
model?: string;
|
|
42
|
+
/** The kind of statement, e.g. SELECT or INSERT. */
|
|
43
|
+
type?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Options controlling how a query is logged. */
|
|
46
|
+
export interface QueryLogOptions {
|
|
47
|
+
/** Instance-level `logging`. */
|
|
48
|
+
instanceLogging?: LoggingOption;
|
|
49
|
+
/** Per-query `logging`, which wins when present. */
|
|
50
|
+
queryLogging?: LoggingOption;
|
|
51
|
+
/** Append `Elapsed time: Nms`. */
|
|
52
|
+
benchmark?: boolean;
|
|
53
|
+
/** Append the bound parameters. */
|
|
54
|
+
logQueryParameters?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the effective logging function for one query.
|
|
58
|
+
*
|
|
59
|
+
* Returns null when logging is off. Precedence is query-level, then
|
|
60
|
+
* instance-level; `false` at either level wins over a function at the other,
|
|
61
|
+
* because silencing is the more specific intent.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveQueryLogger(options: QueryLogOptions): QueryLogFunction | null;
|
|
64
|
+
/** The built-in logger used for `logging: true`. */
|
|
65
|
+
export declare const defaultQueryLogger: QueryLogFunction;
|
|
66
|
+
/**
|
|
67
|
+
* Render one log line.
|
|
68
|
+
*
|
|
69
|
+
* Mirrors Sequelize's `Executed (default): <sql>` prefix so existing log
|
|
70
|
+
* parsers and eyeballs both keep working.
|
|
71
|
+
*/
|
|
72
|
+
export declare function formatQueryLog(context: QueryLogContext, options?: QueryLogOptions): string;
|
|
73
|
+
/**
|
|
74
|
+
* Log one query, if logging is enabled for it.
|
|
75
|
+
*
|
|
76
|
+
* A user-supplied function receives the raw SQL and the timing, exactly as
|
|
77
|
+
* Sequelize does, so callbacks written against that API work unchanged. The
|
|
78
|
+
* built-in logger gets the formatted line instead.
|
|
79
|
+
*
|
|
80
|
+
* @returns whether anything was logged
|
|
81
|
+
*/
|
|
82
|
+
export declare function logQuery(context: QueryLogContext, options?: QueryLogOptions): boolean;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query logging, following the Sequelize logger's shape.
|
|
4
|
+
*
|
|
5
|
+
* Sequelize's contract is small and widely known, so this matches it rather
|
|
6
|
+
* than inventing another:
|
|
7
|
+
*
|
|
8
|
+
* logging: false no output
|
|
9
|
+
* logging: true console.log
|
|
10
|
+
* logging: console.log any function, called as (sql, timing)
|
|
11
|
+
* benchmark: true append the elapsed time
|
|
12
|
+
* logQueryParameters: true append the bound values
|
|
13
|
+
*
|
|
14
|
+
* A per-query `logging` overrides the instance-level one, so a single noisy
|
|
15
|
+
* call can be traced without turning logging on globally - and, symmetrically,
|
|
16
|
+
* one call can be silenced with `logging: false`.
|
|
17
|
+
*
|
|
18
|
+
* This module exists because the resolution logic was previously inlined at
|
|
19
|
+
* four call sites and only some of them ran it: `count`, `bulkCreate`,
|
|
20
|
+
* `increment` and the aggregates emitted nothing at all, so turning logging on
|
|
21
|
+
* showed an incomplete picture of what the ORM was doing.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.defaultQueryLogger = void 0;
|
|
25
|
+
exports.resolveQueryLogger = resolveQueryLogger;
|
|
26
|
+
exports.formatQueryLog = formatQueryLog;
|
|
27
|
+
exports.logQuery = logQuery;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the effective logging function for one query.
|
|
30
|
+
*
|
|
31
|
+
* Returns null when logging is off. Precedence is query-level, then
|
|
32
|
+
* instance-level; `false` at either level wins over a function at the other,
|
|
33
|
+
* because silencing is the more specific intent.
|
|
34
|
+
*/
|
|
35
|
+
function resolveQueryLogger(options) {
|
|
36
|
+
const { queryLogging, instanceLogging } = options;
|
|
37
|
+
// An explicit per-query setting decides on its own.
|
|
38
|
+
if (queryLogging === false)
|
|
39
|
+
return null;
|
|
40
|
+
if (typeof queryLogging === 'function')
|
|
41
|
+
return queryLogging;
|
|
42
|
+
if (queryLogging === true)
|
|
43
|
+
return exports.defaultQueryLogger;
|
|
44
|
+
if (instanceLogging === false)
|
|
45
|
+
return null;
|
|
46
|
+
if (typeof instanceLogging === 'function')
|
|
47
|
+
return instanceLogging;
|
|
48
|
+
if (instanceLogging === true)
|
|
49
|
+
return exports.defaultQueryLogger;
|
|
50
|
+
// Unset at both levels: quiet, matching Sequelize's `logging: false` default
|
|
51
|
+
// in recent versions, unless benchmarking was explicitly asked for.
|
|
52
|
+
return options.benchmark ? exports.defaultQueryLogger : null;
|
|
53
|
+
}
|
|
54
|
+
/** The built-in logger used for `logging: true`. */
|
|
55
|
+
const defaultQueryLogger = (sql, timing) => {
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.log(timing === undefined ? sql : `${sql} Elapsed time: ${timing}ms`);
|
|
58
|
+
};
|
|
59
|
+
exports.defaultQueryLogger = defaultQueryLogger;
|
|
60
|
+
/**
|
|
61
|
+
* Render one log line.
|
|
62
|
+
*
|
|
63
|
+
* Mirrors Sequelize's `Executed (default): <sql>` prefix so existing log
|
|
64
|
+
* parsers and eyeballs both keep working.
|
|
65
|
+
*/
|
|
66
|
+
function formatQueryLog(context, options = {}) {
|
|
67
|
+
const label = context.model ? `Executed (${context.model})` : 'Executed (default)';
|
|
68
|
+
let line = `${label}: ${context.sql}`;
|
|
69
|
+
if (options.logQueryParameters && context.parameters?.length) {
|
|
70
|
+
line += `; ${JSON.stringify(context.parameters)}`;
|
|
71
|
+
}
|
|
72
|
+
if (options.benchmark) {
|
|
73
|
+
line += ` Elapsed time: ${context.duration}ms`;
|
|
74
|
+
}
|
|
75
|
+
return line;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Log one query, if logging is enabled for it.
|
|
79
|
+
*
|
|
80
|
+
* A user-supplied function receives the raw SQL and the timing, exactly as
|
|
81
|
+
* Sequelize does, so callbacks written against that API work unchanged. The
|
|
82
|
+
* built-in logger gets the formatted line instead.
|
|
83
|
+
*
|
|
84
|
+
* @returns whether anything was logged
|
|
85
|
+
*/
|
|
86
|
+
function logQuery(context, options = {}) {
|
|
87
|
+
const logger = resolveQueryLogger(options);
|
|
88
|
+
if (!logger)
|
|
89
|
+
return false;
|
|
90
|
+
if (logger === exports.defaultQueryLogger) {
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
92
|
+
console.log(formatQueryLog(context, options));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Custom loggers get the SQL unadorned; decorating it would break anyone
|
|
96
|
+
// parsing it or forwarding it to a structured log.
|
|
97
|
+
logger(options.logQueryParameters && context.parameters?.length
|
|
98
|
+
? `${context.sql}; ${JSON.stringify(context.parameters)}`
|
|
99
|
+
: context.sql, context.duration);
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
@@ -106,11 +106,47 @@ interface AttributeMetadata {
|
|
|
106
106
|
validate?: Record<string, any>;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
-
*
|
|
109
|
+
* Mark a class as an abstract base model.
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
111
|
+
* An abstract model gets no table of its own. Its columns, and any
|
|
112
|
+
* `@PrimaryKey` / `@Default` / validation applied to them, are inherited by the
|
|
113
|
+
* concrete models that extend it, so shared fields are declared once:
|
|
114
|
+
*
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // This is the base model, which defines the common fields between all comments.
|
|
117
|
+
* @AbstractModel()
|
|
118
|
+
* class BaseComment {
|
|
119
|
+
* @Column(DataTypes.INTEGER())
|
|
120
|
+
* @PrimaryKey()
|
|
121
|
+
* @AutoIncrement()
|
|
122
|
+
* declare id: number;
|
|
123
|
+
*
|
|
124
|
+
* @Column(DataTypes.TEXT())
|
|
125
|
+
* declare body: string;
|
|
126
|
+
* }
|
|
127
|
+
*
|
|
128
|
+
* @Table({ tableName: 'post_comments' })
|
|
129
|
+
* class PostComment extends BaseComment {
|
|
130
|
+
* @Column(DataTypes.INTEGER())
|
|
131
|
+
* declare postId: number;
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* `PostComment` is created with id, body and postId. Passing the abstract class
|
|
136
|
+
* itself to `addModel()` is an error - there is no table to address.
|
|
137
|
+
*/
|
|
138
|
+
export declare function AbstractModel(options?: TableOptions): ClassDecorator;
|
|
139
|
+
/** True when the class (by name) was declared `@AbstractModel`. */
|
|
140
|
+
export declare function isAbstractModel(nameOrClass: string | Function): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Attribute metadata for a model, including everything inherited from abstract
|
|
143
|
+
* base classes up the prototype chain.
|
|
144
|
+
*
|
|
145
|
+
* Metadata is keyed by constructor name, so a subclass would otherwise see only
|
|
146
|
+
* the columns declared directly on it. Base columns come first, and a subclass
|
|
147
|
+
* redeclaring a column overrides it.
|
|
113
148
|
*/
|
|
149
|
+
export declare function getInheritedAttributeMetadata(modelClass: Function): Map<string, AttributeMetadata>;
|
|
114
150
|
export declare function Table(options?: TableOptions): ClassDecorator;
|
|
115
151
|
/**
|
|
116
152
|
* Table options interface
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* - @Comment - Add column comment
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.AbstractModel = AbstractModel;
|
|
17
|
+
exports.isAbstractModel = isAbstractModel;
|
|
18
|
+
exports.getInheritedAttributeMetadata = getInheritedAttributeMetadata;
|
|
16
19
|
exports.Table = Table;
|
|
17
20
|
exports.Attribute = Attribute;
|
|
18
21
|
exports.Column = Column;
|
|
@@ -70,6 +73,77 @@ const associationMetadata = new Map();
|
|
|
70
73
|
* @example
|
|
71
74
|
* @Table({ tableName: 'users', timestamps: true })
|
|
72
75
|
*/
|
|
76
|
+
/** Classes marked with `@AbstractModel`, by constructor name. */
|
|
77
|
+
const abstractModels = new Set();
|
|
78
|
+
/**
|
|
79
|
+
* Mark a class as an abstract base model.
|
|
80
|
+
*
|
|
81
|
+
* An abstract model gets no table of its own. Its columns, and any
|
|
82
|
+
* `@PrimaryKey` / `@Default` / validation applied to them, are inherited by the
|
|
83
|
+
* concrete models that extend it, so shared fields are declared once:
|
|
84
|
+
*
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // This is the base model, which defines the common fields between all comments.
|
|
87
|
+
* @AbstractModel()
|
|
88
|
+
* class BaseComment {
|
|
89
|
+
* @Column(DataTypes.INTEGER())
|
|
90
|
+
* @PrimaryKey()
|
|
91
|
+
* @AutoIncrement()
|
|
92
|
+
* declare id: number;
|
|
93
|
+
*
|
|
94
|
+
* @Column(DataTypes.TEXT())
|
|
95
|
+
* declare body: string;
|
|
96
|
+
* }
|
|
97
|
+
*
|
|
98
|
+
* @Table({ tableName: 'post_comments' })
|
|
99
|
+
* class PostComment extends BaseComment {
|
|
100
|
+
* @Column(DataTypes.INTEGER())
|
|
101
|
+
* declare postId: number;
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* `PostComment` is created with id, body and postId. Passing the abstract class
|
|
106
|
+
* itself to `addModel()` is an error - there is no table to address.
|
|
107
|
+
*/
|
|
108
|
+
function AbstractModel(options = {}) {
|
|
109
|
+
return function (target) {
|
|
110
|
+
abstractModels.add(target.name);
|
|
111
|
+
// Record the options so subclasses can inherit timestamps/paranoid and the
|
|
112
|
+
// rest, but never a tableName - each concrete model names its own table.
|
|
113
|
+
const { tableName: _ignored, ...inheritable } = options;
|
|
114
|
+
modelMetadata.set(target.name, { ...inheritable });
|
|
115
|
+
return target;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** True when the class (by name) was declared `@AbstractModel`. */
|
|
119
|
+
function isAbstractModel(nameOrClass) {
|
|
120
|
+
return abstractModels.has(typeof nameOrClass === 'string' ? nameOrClass : nameOrClass.name);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Attribute metadata for a model, including everything inherited from abstract
|
|
124
|
+
* base classes up the prototype chain.
|
|
125
|
+
*
|
|
126
|
+
* Metadata is keyed by constructor name, so a subclass would otherwise see only
|
|
127
|
+
* the columns declared directly on it. Base columns come first, and a subclass
|
|
128
|
+
* redeclaring a column overrides it.
|
|
129
|
+
*/
|
|
130
|
+
function getInheritedAttributeMetadata(modelClass) {
|
|
131
|
+
const chain = [];
|
|
132
|
+
let current = modelClass;
|
|
133
|
+
while (current && current !== Function.prototype && current.name) {
|
|
134
|
+
chain.unshift(current);
|
|
135
|
+
current = Object.getPrototypeOf(current);
|
|
136
|
+
}
|
|
137
|
+
const merged = new Map();
|
|
138
|
+
for (const cls of chain) {
|
|
139
|
+
const own = attributeMetadata.get(cls.name);
|
|
140
|
+
if (!own)
|
|
141
|
+
continue;
|
|
142
|
+
for (const [field, meta] of own)
|
|
143
|
+
merged.set(field, meta);
|
|
144
|
+
}
|
|
145
|
+
return merged;
|
|
146
|
+
}
|
|
73
147
|
function Table(options = {}) {
|
|
74
148
|
return function (target) {
|
|
75
149
|
const modelName = target.name;
|
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
* bugs you hit depended on which API you had used to define the model.
|
|
12
12
|
*
|
|
13
13
|
* Both paths now call `loadIncludes()` below.
|
|
14
|
+
*
|
|
15
|
+
* Two things about this loader are worth knowing before reading it:
|
|
16
|
+
*
|
|
17
|
+
* 1. An include is resolved with ONE query per association level, never a JOIN:
|
|
18
|
+
* all parents are satisfied by a single `WHERE fk IN (...)`. That is
|
|
19
|
+
* deliberate - it keeps the statement count constant in the number of rows -
|
|
20
|
+
* but it is also why a per-include `limit` cannot simply be forwarded to that
|
|
21
|
+
* query; see the per-parent window notes on `loadIncludes()`.
|
|
22
|
+
* 2. `{ all: true }` entries are expanded to one concrete include per
|
|
23
|
+
* association before any of that happens; see `expandAllIncludes()`.
|
|
14
24
|
*/
|
|
15
25
|
/** Minimal view of the association records kept in `Prorm.associations`. */
|
|
16
26
|
export interface EagerLoadAssociation {
|
|
@@ -52,6 +62,49 @@ export declare function resolvePrimaryKeyAttr(m: any): string;
|
|
|
52
62
|
* foreign-key logic to it.
|
|
53
63
|
*/
|
|
54
64
|
export declare function resolveIncludeAssociation(ctx: EagerLoadContext, parentModel: any, parentModelName: string, includeOpt: any): EagerLoadAssociation;
|
|
65
|
+
/**
|
|
66
|
+
* Expand `{ all: true }` / `{ all: 'alias' }` include entries into one concrete
|
|
67
|
+
* include per association.
|
|
68
|
+
*
|
|
69
|
+
* `loadIncludes()` used to open each iteration with `if (!includeOpt.model)
|
|
70
|
+
* continue`, so an entry carrying no `model` - which is exactly what
|
|
71
|
+
* `{ all: true }` is - was skipped without a word: `include: [{ all: true }]`
|
|
72
|
+
* emitted the parent SELECT and attached nothing. The class-based path expanded
|
|
73
|
+
* it (models/model.ts) and the `prorm.define()` path did not, so which of the
|
|
74
|
+
* two APIs you had used decided whether the option existed.
|
|
75
|
+
*
|
|
76
|
+
* Bounding the recursion. `nested: true` walks the association graph, and that
|
|
77
|
+
* graph routinely contains cycles (`User.hasMany(Post)` + `Post.belongsTo(User)`)
|
|
78
|
+
* and self-references (`Category.hasMany(Category)`). Depth alone does not bound
|
|
79
|
+
* those usefully here: unlike the class-based expander - which builds one SQL
|
|
80
|
+
* statement - every expanded include is another round trip, so a cycle across a
|
|
81
|
+
* model with three associations would reach 3^10 queries before the depth cap
|
|
82
|
+
* bit. So expansion is bounded twice: by `MAX_ALL_EXPANSION_DEPTH`, and by the
|
|
83
|
+
* chain of models already expanded on the current branch - a model is never
|
|
84
|
+
* auto-expanded twice on one path, which terminates cycles and self-references
|
|
85
|
+
* at their first repeat.
|
|
86
|
+
*
|
|
87
|
+
* The chain stops *re-expansion*, not the association itself: `User` with
|
|
88
|
+
* `{ all: true, nested: true }` still loads `posts` and each post's `user` (that
|
|
89
|
+
* is one of Post's associations, and `all` means all), but stops there rather
|
|
90
|
+
* than walking back into User's associations again. So a two-model cycle costs
|
|
91
|
+
* three queries, not ten levels of ping-pong.
|
|
92
|
+
*
|
|
93
|
+
* Two deliberate differences from the class-based expander:
|
|
94
|
+
* - the depth cap only ever stops *automatic* expansion; a hand-written include
|
|
95
|
+
* is passed through at any depth rather than silently dropped.
|
|
96
|
+
* - an unknown `{ all: 'alias' }` is an error rather than a console warning.
|
|
97
|
+
*
|
|
98
|
+
* `required` carried onto an expanded include filters parents like any other
|
|
99
|
+
* required include. That needs expansion to happen before the parent-filtering
|
|
100
|
+
* pass rather than inside `loadIncludes()` at the end of the query - the
|
|
101
|
+
* filtering pass calls `resolveRequiredIncludeFilter`, which returns null for an
|
|
102
|
+
* entry with no `model`, so while `{ all: true }` was still un-expanded at that
|
|
103
|
+
* point `{ all: true, required: true }` loaded the associations and narrowed
|
|
104
|
+
* nothing. Callers therefore expand once, up front; expansion is idempotent, so
|
|
105
|
+
* `loadIncludes()` re-running it on an already-expanded list is a no-op.
|
|
106
|
+
*/
|
|
107
|
+
export declare function expandAllIncludes(ctx: EagerLoadContext, parentModel: any, parentModelName: string, includeList: any[], depth?: number, chain?: readonly string[]): any[];
|
|
55
108
|
/**
|
|
56
109
|
* An include filters its parents when it is `required`, and `required` defaults
|
|
57
110
|
* to true whenever the include carries its own `where` - the same rule Sequelize
|
|
@@ -75,6 +128,18 @@ export declare function resolveRequiredIncludeFilter(ctx: EagerLoadContext, pare
|
|
|
75
128
|
parentAttr: string;
|
|
76
129
|
values: any[];
|
|
77
130
|
} | null>;
|
|
131
|
+
/**
|
|
132
|
+
* Attach a count of related rows to each parent, without loading them.
|
|
133
|
+
*
|
|
134
|
+
* `findAll({ withCount: ['posts'] })` sets `row.postsCount` on every parent.
|
|
135
|
+
* The counts are resolved with one grouped query per association, so this stays
|
|
136
|
+
* a constant number of statements no matter how many parents there are - the
|
|
137
|
+
* naive alternative is a count query per row.
|
|
138
|
+
*
|
|
139
|
+
* Use this when you need "how many" but not the rows themselves; a full
|
|
140
|
+
* `include` fetches every child just to measure the array.
|
|
141
|
+
*/
|
|
142
|
+
export declare function loadCounts(ctx: EagerLoadContext, parentRows: any[], parentModel: any, parentModelName: string, aliases: string[]): Promise<void>;
|
|
78
143
|
/**
|
|
79
144
|
* Eager-load `includeList` onto `parentRows`, recursing into nested includes.
|
|
80
145
|
*
|
|
@@ -82,5 +147,39 @@ export declare function resolveRequiredIncludeFilter(ctx: EagerLoadContext, pare
|
|
|
82
147
|
* caught and reported as an empty result, which made a typo'd alias, a missing
|
|
83
148
|
* foreign key column, an unresolvable through model and a genuinely childless
|
|
84
149
|
* parent all look identical - and hid most of the bugs this module now fixes.
|
|
150
|
+
*
|
|
151
|
+
* ## Per-include `limit` / `offset`
|
|
152
|
+
*
|
|
153
|
+
* `include: [{ model: Post, order: [['id', 'DESC']], limit: 5 }]` reads as "the
|
|
154
|
+
* 5 most recent posts *per user*", and that is what it now means. Getting there
|
|
155
|
+
* needs care, because one query serves every parent:
|
|
156
|
+
*
|
|
157
|
+
* SELECT ... FROM "posts" WHERE "userId" IN (1, 2, 3) ORDER BY "id" DESC
|
|
158
|
+
*
|
|
159
|
+
* Forwarding `LIMIT 5` into that statement would cap the *whole result set* at 5
|
|
160
|
+
* rows - user 1 would get five posts and users 2 and 3 none - which is worse
|
|
161
|
+
* than the old behaviour of dropping the option, because the answer looks
|
|
162
|
+
* plausible while being wrong for every parent but the first. So the limit is
|
|
163
|
+
* never forwarded into a multi-parent `IN (...)` query. Instead:
|
|
164
|
+
*
|
|
165
|
+
* - `order` is still applied *in SQL*, so the database decides which rows come
|
|
166
|
+
* first - the window is a window over the ordering the caller asked for, not
|
|
167
|
+
* over insertion order.
|
|
168
|
+
* - the window is then applied per parent, in memory, when the fetched rows are
|
|
169
|
+
* grouped onto their parents.
|
|
170
|
+
* - the one case where the shared query and a per-parent window coincide is a
|
|
171
|
+
* single parent row (`findByPk(...)` with an include, the common case): there
|
|
172
|
+
* `LIMIT`/`OFFSET` *are* pushed down to SQL, for `hasMany` only - see below.
|
|
173
|
+
*
|
|
174
|
+
* What this does NOT do: reduce what crosses the wire for multi-parent queries.
|
|
175
|
+
* All matching children are fetched and most of them are then discarded.
|
|
176
|
+
* `limit` here bounds the arrays you get back, it is not a transfer
|
|
177
|
+
* optimization. Doing better needs per-parent SQL windows (`ROW_NUMBER() OVER
|
|
178
|
+
* (PARTITION BY ...)` or `LATERAL`), which is a dialect-level feature this
|
|
179
|
+
* loader - which only ever calls `Model.findAll()` - cannot express today.
|
|
180
|
+
*
|
|
181
|
+
* `limit`/`offset` are only meaningful on a to-many include. On `belongsTo` and
|
|
182
|
+
* `hasOne` the result is a single row rather than a list, so they are reported
|
|
183
|
+
* and ignored rather than quietly accepted.
|
|
85
184
|
*/
|
|
86
185
|
export declare function loadIncludes(ctx: EagerLoadContext, parentRows: any[], parentModel: any, parentModelName: string, includeList: any[]): Promise<void>;
|