sequelize.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __defProps = Object.defineProperties;
  4. var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
  5. var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  6. var __hasOwnProp = Object.prototype.hasOwnProperty;
  7. var __propIsEnum = Object.prototype.propertyIsEnumerable;
  8. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  9. var __spreadValues = (a, b) => {
  10. for (var prop in b || (b = {}))
  11. if (__hasOwnProp.call(b, prop))
  12. __defNormalProp(a, prop, b[prop]);
  13. if (__getOwnPropSymbols)
  14. for (var prop of __getOwnPropSymbols(b)) {
  15. if (__propIsEnum.call(b, prop))
  16. __defNormalProp(a, prop, b[prop]);
  17. }
  18. return a;
  19. };
  20. var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
  21. const url = require("url");
  22. const path = require("path");
  23. const pgConnectionString = require("pg-connection-string");
  24. const retry = require("retry-as-promised");
  25. const _ = require("lodash");
  26. const Utils = require("./utils");
  27. const Model = require("./model");
  28. const DataTypes = require("./data-types");
  29. const Deferrable = require("./deferrable");
  30. const ModelManager = require("./model-manager");
  31. const Transaction = require("./transaction");
  32. const QueryTypes = require("./query-types");
  33. const TableHints = require("./table-hints");
  34. const IndexHints = require("./index-hints");
  35. const sequelizeErrors = require("./errors");
  36. const Hooks = require("./hooks");
  37. const Association = require("./associations/index");
  38. const Validator = require("./utils/validator-extras").validator;
  39. const Op = require("./operators");
  40. const deprecations = require("./utils/deprecations");
  41. const { QueryInterface } = require("./dialects/abstract/query-interface");
  42. const { BelongsTo } = require("./associations/belongs-to");
  43. const HasOne = require("./associations/has-one");
  44. const { BelongsToMany } = require("./associations/belongs-to-many");
  45. const { HasMany } = require("./associations/has-many");
  46. class Sequelize {
  47. constructor(database, username, password, options) {
  48. let config;
  49. if (arguments.length === 1 && typeof database === "object") {
  50. options = database;
  51. config = _.pick(options, "host", "port", "database", "username", "password");
  52. } else if (arguments.length === 1 && typeof database === "string" || arguments.length === 2 && typeof username === "object") {
  53. config = {};
  54. options = username || {};
  55. const urlParts = url.parse(arguments[0], true);
  56. options.dialect = urlParts.protocol.replace(/:$/, "");
  57. options.host = urlParts.hostname;
  58. if (options.dialect === "sqlite" && urlParts.pathname && !urlParts.pathname.startsWith("/:memory")) {
  59. const storagePath = path.join(options.host, urlParts.pathname);
  60. options.storage = path.resolve(options.storage || storagePath);
  61. }
  62. if (urlParts.pathname) {
  63. config.database = urlParts.pathname.replace(/^\//, "");
  64. }
  65. if (urlParts.port) {
  66. options.port = urlParts.port;
  67. }
  68. if (urlParts.auth) {
  69. const authParts = urlParts.auth.split(":");
  70. config.username = authParts[0];
  71. if (authParts.length > 1)
  72. config.password = authParts.slice(1).join(":");
  73. }
  74. if (urlParts.query) {
  75. if (urlParts.query.host) {
  76. options.host = urlParts.query.host;
  77. }
  78. if (options.dialectOptions) {
  79. Object.assign(options.dialectOptions, urlParts.query);
  80. } else {
  81. options.dialectOptions = urlParts.query;
  82. if (urlParts.query.options) {
  83. try {
  84. const o = JSON.parse(urlParts.query.options);
  85. options.dialectOptions.options = o;
  86. } catch (e) {
  87. }
  88. }
  89. }
  90. }
  91. if (["postgres", "postgresql"].includes(options.dialect)) {
  92. Object.assign(options.dialectOptions, pgConnectionString.parse(arguments[0]));
  93. }
  94. } else {
  95. options = options || {};
  96. config = { database, username, password };
  97. }
  98. Sequelize.runHooks("beforeInit", config, options);
  99. this.options = __spreadValues({
  100. dialect: null,
  101. dialectModule: null,
  102. dialectModulePath: null,
  103. host: "localhost",
  104. protocol: "tcp",
  105. define: {},
  106. query: {},
  107. sync: {},
  108. timezone: "+00:00",
  109. standardConformingStrings: true,
  110. logging: console.log,
  111. omitNull: false,
  112. native: false,
  113. replication: false,
  114. ssl: void 0,
  115. pool: {},
  116. quoteIdentifiers: true,
  117. hooks: {},
  118. retry: {
  119. max: 5,
  120. match: [
  121. "SQLITE_BUSY: database is locked"
  122. ]
  123. },
  124. transactionType: Transaction.TYPES.DEFERRED,
  125. isolationLevel: null,
  126. databaseVersion: 0,
  127. typeValidation: false,
  128. benchmark: false,
  129. minifyAliases: false,
  130. logQueryParameters: false
  131. }, options);
  132. if (!this.options.dialect) {
  133. throw new Error("Dialect needs to be explicitly supplied as of v4.0.0");
  134. }
  135. if (this.options.dialect === "postgresql") {
  136. this.options.dialect = "postgres";
  137. }
  138. if (this.options.dialect === "sqlite" && this.options.timezone !== "+00:00") {
  139. throw new Error("Setting a custom timezone is not supported by SQLite, dates are always returned as UTC. Please remove the custom timezone parameter.");
  140. }
  141. if (this.options.logging === true) {
  142. deprecations.noTrueLogging();
  143. this.options.logging = console.log;
  144. }
  145. this._setupHooks(options.hooks);
  146. this.config = {
  147. database: config.database || this.options.database,
  148. username: config.username || this.options.username,
  149. password: config.password || this.options.password || null,
  150. host: config.host || this.options.host,
  151. port: config.port || this.options.port,
  152. pool: this.options.pool,
  153. protocol: this.options.protocol,
  154. native: this.options.native,
  155. ssl: this.options.ssl,
  156. replication: this.options.replication,
  157. dialectModule: this.options.dialectModule,
  158. dialectModulePath: this.options.dialectModulePath,
  159. keepDefaultTimezone: this.options.keepDefaultTimezone,
  160. dialectOptions: this.options.dialectOptions
  161. };
  162. let Dialect;
  163. switch (this.getDialect()) {
  164. case "mariadb":
  165. Dialect = require("./dialects/mariadb");
  166. break;
  167. case "mssql":
  168. Dialect = require("./dialects/mssql");
  169. break;
  170. case "mysql":
  171. Dialect = require("./dialects/mysql");
  172. break;
  173. case "postgres":
  174. Dialect = require("./dialects/postgres");
  175. break;
  176. case "sqlite":
  177. Dialect = require("./dialects/sqlite");
  178. break;
  179. case "db2":
  180. Dialect = require("./dialects/db2");
  181. break;
  182. case "snowflake":
  183. Dialect = require("./dialects/snowflake");
  184. break;
  185. default:
  186. throw new Error(`The dialect ${this.getDialect()} is not supported. Supported dialects: mssql, mariadb, mysql, postgres, db2 and sqlite.`);
  187. }
  188. this.dialect = new Dialect(this);
  189. this.dialect.queryGenerator.typeValidation = options.typeValidation;
  190. if (_.isPlainObject(this.options.operatorsAliases)) {
  191. deprecations.noStringOperators();
  192. this.dialect.queryGenerator.setOperatorsAliases(this.options.operatorsAliases);
  193. } else if (typeof this.options.operatorsAliases === "boolean") {
  194. deprecations.noBoolOperatorAliases();
  195. }
  196. this.queryInterface = this.dialect.queryInterface;
  197. this.models = {};
  198. this.modelManager = new ModelManager(this);
  199. this.connectionManager = this.dialect.connectionManager;
  200. Sequelize.runHooks("afterInit", this);
  201. }
  202. refreshTypes() {
  203. this.connectionManager.refreshTypeParser(DataTypes);
  204. }
  205. getDialect() {
  206. return this.options.dialect;
  207. }
  208. getDatabaseName() {
  209. return this.config.database;
  210. }
  211. getQueryInterface() {
  212. return this.queryInterface;
  213. }
  214. define(modelName, attributes, options = {}) {
  215. options.modelName = modelName;
  216. options.sequelize = this;
  217. const model = class extends Model {
  218. };
  219. model.init(attributes, options);
  220. return model;
  221. }
  222. model(modelName) {
  223. if (!this.isDefined(modelName)) {
  224. throw new Error(`${modelName} has not been defined`);
  225. }
  226. return this.modelManager.getModel(modelName);
  227. }
  228. isDefined(modelName) {
  229. return !!this.modelManager.models.find((model) => model.name === modelName);
  230. }
  231. async query(sql, options) {
  232. options = __spreadValues(__spreadValues({}, this.options.query), options);
  233. if (options.instance && !options.model) {
  234. options.model = options.instance.constructor;
  235. }
  236. if (!options.instance && !options.model) {
  237. options.raw = true;
  238. }
  239. if (options.mapToModel) {
  240. options.fieldMap = _.get(options, "model.fieldAttributeMap", {});
  241. }
  242. options = _.defaults(options, {
  243. logging: Object.prototype.hasOwnProperty.call(this.options, "logging") ? this.options.logging : console.log,
  244. searchPath: Object.prototype.hasOwnProperty.call(this.options, "searchPath") ? this.options.searchPath : "DEFAULT"
  245. });
  246. if (!options.type) {
  247. if (options.model || options.nest || options.plain) {
  248. options.type = QueryTypes.SELECT;
  249. } else {
  250. options.type = QueryTypes.RAW;
  251. }
  252. }
  253. if (!this.dialect.supports.searchPath || !this.options.dialectOptions || !this.options.dialectOptions.prependSearchPath || options.supportsSearchPath === false) {
  254. delete options.searchPath;
  255. } else if (!options.searchPath) {
  256. options.searchPath = "DEFAULT";
  257. }
  258. if (typeof sql === "object") {
  259. if (sql.values !== void 0) {
  260. if (options.replacements !== void 0) {
  261. throw new Error("Both `sql.values` and `options.replacements` cannot be set at the same time");
  262. }
  263. options.replacements = sql.values;
  264. }
  265. if (sql.bind !== void 0) {
  266. if (options.bind !== void 0) {
  267. throw new Error("Both `sql.bind` and `options.bind` cannot be set at the same time");
  268. }
  269. options.bind = sql.bind;
  270. }
  271. if (sql.query !== void 0) {
  272. sql = sql.query;
  273. }
  274. }
  275. sql = sql.trim();
  276. if (options.replacements && options.bind) {
  277. throw new Error("Both `replacements` and `bind` cannot be set at the same time");
  278. }
  279. if (options.replacements) {
  280. if (Array.isArray(options.replacements)) {
  281. sql = Utils.format([sql].concat(options.replacements), this.options.dialect);
  282. } else {
  283. sql = Utils.formatNamedParameters(sql, options.replacements, this.options.dialect);
  284. }
  285. }
  286. let bindParameters;
  287. if (options.bind) {
  288. [sql, bindParameters] = this.dialect.Query.formatBindParameters(sql, options.bind, this.options.dialect);
  289. }
  290. const checkTransaction = () => {
  291. if (options.transaction && options.transaction.finished && !options.completesTransaction) {
  292. const error = new Error(`${options.transaction.finished} has been called on this transaction(${options.transaction.id}), you can no longer use it. (The rejected query is attached as the 'sql' property of this error)`);
  293. error.sql = sql;
  294. throw error;
  295. }
  296. };
  297. const retryOptions = __spreadValues(__spreadValues({}, this.options.retry), options.retry);
  298. return retry(async () => {
  299. if (options.transaction === void 0 && Sequelize._cls) {
  300. options.transaction = Sequelize._cls.get("transaction");
  301. }
  302. checkTransaction();
  303. const connection = await (options.transaction ? options.transaction.connection : this.connectionManager.getConnection(options));
  304. if (this.options.dialect === "db2" && options.alter) {
  305. if (options.alter.drop === false) {
  306. connection.dropTable = false;
  307. }
  308. }
  309. const query = new this.dialect.Query(connection, this, options);
  310. try {
  311. await this.runHooks("beforeQuery", options, query);
  312. checkTransaction();
  313. return await query.run(sql, bindParameters);
  314. } finally {
  315. await this.runHooks("afterQuery", options, query);
  316. if (!options.transaction) {
  317. await this.connectionManager.releaseConnection(connection);
  318. }
  319. }
  320. }, retryOptions);
  321. }
  322. async set(variables, options) {
  323. options = __spreadValues(__spreadValues({}, this.options.set), typeof options === "object" && options);
  324. if (!["mysql", "mariadb"].includes(this.options.dialect)) {
  325. throw new Error("sequelize.set is only supported for mysql or mariadb");
  326. }
  327. if (!options.transaction || !(options.transaction instanceof Transaction)) {
  328. throw new TypeError("options.transaction is required");
  329. }
  330. options.raw = true;
  331. options.plain = true;
  332. options.type = "SET";
  333. const query = `SET ${_.map(variables, (v, k) => `@${k} := ${typeof v === "string" ? `"${v}"` : v}`).join(", ")}`;
  334. return await this.query(query, options);
  335. }
  336. escape(value) {
  337. return this.dialect.queryGenerator.escape(value);
  338. }
  339. async createSchema(schema, options) {
  340. return await this.getQueryInterface().createSchema(schema, options);
  341. }
  342. async showAllSchemas(options) {
  343. return await this.getQueryInterface().showAllSchemas(options);
  344. }
  345. async dropSchema(schema, options) {
  346. return await this.getQueryInterface().dropSchema(schema, options);
  347. }
  348. async dropAllSchemas(options) {
  349. return await this.getQueryInterface().dropAllSchemas(options);
  350. }
  351. async sync(options) {
  352. options = __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, this.options), this.options.sync), options), {
  353. hooks: options ? options.hooks !== false : true
  354. });
  355. if (options.match) {
  356. if (!options.match.test(this.config.database)) {
  357. throw new Error(`Database "${this.config.database}" does not match sync match parameter "${options.match}"`);
  358. }
  359. }
  360. if (options.hooks) {
  361. await this.runHooks("beforeBulkSync", options);
  362. }
  363. if (options.force) {
  364. await this.drop(options);
  365. }
  366. const models = [];
  367. this.modelManager.forEachModel((model) => {
  368. if (model) {
  369. models.push(model);
  370. } else {
  371. }
  372. });
  373. if (!models.length) {
  374. await this.authenticate(options);
  375. } else {
  376. for (const model of models)
  377. await model.sync(options);
  378. }
  379. if (options.hooks) {
  380. await this.runHooks("afterBulkSync", options);
  381. }
  382. return this;
  383. }
  384. async truncate(options) {
  385. const models = [];
  386. this.modelManager.forEachModel((model) => {
  387. if (model) {
  388. models.push(model);
  389. }
  390. }, { reverse: false });
  391. if (options && options.cascade) {
  392. for (const model of models)
  393. await model.truncate(options);
  394. } else {
  395. await Promise.all(models.map((model) => model.truncate(options)));
  396. }
  397. }
  398. async drop(options) {
  399. const models = [];
  400. this.modelManager.forEachModel((model) => {
  401. if (model) {
  402. models.push(model);
  403. }
  404. }, { reverse: false });
  405. for (const model of models)
  406. await model.drop(options);
  407. }
  408. async authenticate(options) {
  409. options = __spreadValues({
  410. raw: true,
  411. plain: true,
  412. type: QueryTypes.SELECT
  413. }, options);
  414. await this.query("SELECT 1+1 AS result", options);
  415. return;
  416. }
  417. async databaseVersion(options) {
  418. return await this.getQueryInterface().databaseVersion(options);
  419. }
  420. random() {
  421. if (["postgres", "sqlite", "snowflake"].includes(this.getDialect())) {
  422. return this.fn("RANDOM");
  423. }
  424. return this.fn("RAND");
  425. }
  426. static fn(fn, ...args) {
  427. return new Utils.Fn(fn, args);
  428. }
  429. static col(col) {
  430. return new Utils.Col(col);
  431. }
  432. static cast(val, type) {
  433. return new Utils.Cast(val, type);
  434. }
  435. static literal(val) {
  436. return new Utils.Literal(val);
  437. }
  438. static and(...args) {
  439. return { [Op.and]: args };
  440. }
  441. static or(...args) {
  442. return { [Op.or]: args };
  443. }
  444. static json(conditionsOrPath, value) {
  445. return new Utils.Json(conditionsOrPath, value);
  446. }
  447. static where(attr, comparator, logic) {
  448. return new Utils.Where(attr, comparator, logic);
  449. }
  450. async transaction(options, autoCallback) {
  451. if (typeof options === "function") {
  452. autoCallback = options;
  453. options = void 0;
  454. }
  455. const transaction = new Transaction(this, options);
  456. if (!autoCallback) {
  457. await transaction.prepareEnvironment(false);
  458. return transaction;
  459. }
  460. return Sequelize._clsRun(async () => {
  461. try {
  462. await transaction.prepareEnvironment();
  463. const result = await autoCallback(transaction);
  464. await transaction.commit();
  465. return await result;
  466. } catch (err) {
  467. try {
  468. if (!transaction.finished) {
  469. await transaction.rollback();
  470. } else {
  471. await transaction.cleanup();
  472. }
  473. } catch (err0) {
  474. }
  475. throw err;
  476. }
  477. });
  478. }
  479. static useCLS(ns) {
  480. if (!ns || typeof ns !== "object" || typeof ns.bind !== "function" || typeof ns.run !== "function")
  481. throw new Error("Must provide CLS namespace");
  482. Sequelize._cls = ns;
  483. return this;
  484. }
  485. static _clsRun(fn) {
  486. const ns = Sequelize._cls;
  487. if (!ns)
  488. return fn();
  489. let res;
  490. ns.run((context) => res = fn(context));
  491. return res;
  492. }
  493. log(...args) {
  494. let options;
  495. const last = _.last(args);
  496. if (last && _.isPlainObject(last) && Object.prototype.hasOwnProperty.call(last, "logging")) {
  497. options = last;
  498. if (options.logging === console.log) {
  499. args.splice(args.length - 1, 1);
  500. }
  501. } else {
  502. options = this.options;
  503. }
  504. if (options.logging) {
  505. if (options.logging === true) {
  506. deprecations.noTrueLogging();
  507. options.logging = console.log;
  508. }
  509. if ((this.options.benchmark || options.benchmark) && options.logging === console.log) {
  510. args = [`${args[0]} Elapsed time: ${args[1]}ms`];
  511. }
  512. options.logging(...args);
  513. }
  514. }
  515. close() {
  516. return this.connectionManager.close();
  517. }
  518. normalizeDataType(Type) {
  519. let type = typeof Type === "function" ? new Type() : Type;
  520. const dialectTypes = this.dialect.DataTypes || {};
  521. if (dialectTypes[type.key]) {
  522. type = dialectTypes[type.key].extend(type);
  523. }
  524. if (type instanceof DataTypes.ARRAY) {
  525. if (!type.type) {
  526. throw new Error("ARRAY is missing type definition for its values.");
  527. }
  528. if (dialectTypes[type.type.key]) {
  529. type.type = dialectTypes[type.type.key].extend(type.type);
  530. }
  531. }
  532. return type;
  533. }
  534. normalizeAttribute(attribute) {
  535. if (!_.isPlainObject(attribute)) {
  536. attribute = { type: attribute };
  537. }
  538. if (!attribute.type)
  539. return attribute;
  540. attribute.type = this.normalizeDataType(attribute.type);
  541. if (Object.prototype.hasOwnProperty.call(attribute, "defaultValue")) {
  542. if (typeof attribute.defaultValue === "function" && [DataTypes.NOW, DataTypes.UUIDV1, DataTypes.UUIDV4].includes(attribute.defaultValue)) {
  543. attribute.defaultValue = new attribute.defaultValue();
  544. }
  545. }
  546. if (attribute.type instanceof DataTypes.ENUM) {
  547. if (attribute.values) {
  548. attribute.type.values = attribute.type.options.values = attribute.values;
  549. } else {
  550. attribute.values = attribute.type.values;
  551. }
  552. if (!attribute.values.length) {
  553. throw new Error("Values for ENUM have not been defined.");
  554. }
  555. }
  556. return attribute;
  557. }
  558. }
  559. Sequelize.prototype.fn = Sequelize.fn;
  560. Sequelize.prototype.col = Sequelize.col;
  561. Sequelize.prototype.cast = Sequelize.cast;
  562. Sequelize.prototype.literal = Sequelize.literal;
  563. Sequelize.prototype.and = Sequelize.and;
  564. Sequelize.prototype.or = Sequelize.or;
  565. Sequelize.prototype.json = Sequelize.json;
  566. Sequelize.prototype.where = Sequelize.where;
  567. Sequelize.prototype.validate = Sequelize.prototype.authenticate;
  568. Object.defineProperty(Sequelize, "version", {
  569. enumerable: true,
  570. get() {
  571. return require("../package.json").version;
  572. }
  573. });
  574. Sequelize.options = { hooks: {} };
  575. Sequelize.Utils = Utils;
  576. Sequelize.Op = Op;
  577. Sequelize.TableHints = TableHints;
  578. Sequelize.IndexHints = IndexHints;
  579. Sequelize.Transaction = Transaction;
  580. Sequelize.prototype.Sequelize = Sequelize;
  581. Sequelize.prototype.QueryTypes = Sequelize.QueryTypes = QueryTypes;
  582. Sequelize.prototype.Validator = Sequelize.Validator = Validator;
  583. Sequelize.Model = Model;
  584. Sequelize.QueryInterface = QueryInterface;
  585. Sequelize.BelongsTo = BelongsTo;
  586. Sequelize.HasOne = HasOne;
  587. Sequelize.HasMany = HasMany;
  588. Sequelize.BelongsToMany = BelongsToMany;
  589. Sequelize.DataTypes = DataTypes;
  590. for (const dataType in DataTypes) {
  591. Sequelize[dataType] = DataTypes[dataType];
  592. }
  593. Sequelize.Deferrable = Deferrable;
  594. Sequelize.prototype.Association = Sequelize.Association = Association;
  595. Sequelize.useInflection = Utils.useInflection;
  596. Hooks.applyTo(Sequelize);
  597. Hooks.applyTo(Sequelize.prototype);
  598. Sequelize.Error = sequelizeErrors.BaseError;
  599. for (const error of Object.keys(sequelizeErrors)) {
  600. Sequelize[error] = sequelizeErrors[error];
  601. }
  602. module.exports = Sequelize;
  603. module.exports.Sequelize = Sequelize;
  604. module.exports.default = Sequelize;
  605. //# sourceMappingURL=sequelize.js.map