destroy.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // ██████╗ ███████╗███████╗████████╗██████╗ ██████╗ ██╗ ██╗ █████╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗
  2. // ██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔═══██╗╚██╗ ██╔╝ ██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║
  3. // ██║ ██║█████╗ ███████╗ ██║ ██████╔╝██║ ██║ ╚████╔╝ ███████║██║ ██║ ██║██║ ██║██╔██╗ ██║
  4. // ██║ ██║██╔══╝ ╚════██║ ██║ ██╔══██╗██║ ██║ ╚██╔╝ ██╔══██║██║ ██║ ██║██║ ██║██║╚██╗██║
  5. // ██████╔╝███████╗███████║ ██║ ██║ ██║╚██████╔╝ ██║ ██║ ██║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║
  6. // ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
  7. //
  8. module.exports = require('machine').build({
  9. friendlyName: 'Destroy',
  10. description: 'Destroy record(s) in the database matching a query criteria.',
  11. inputs: {
  12. datastore: {
  13. description: 'The datastore to use for connections.',
  14. extendedDescription: 'Datastores represent the config and manager required to obtain an active database connection.',
  15. required: true,
  16. readOnly: true,
  17. example: '==='
  18. },
  19. models: {
  20. description: 'An object containing all of the model definitions that have been registered.',
  21. required: true,
  22. example: '==='
  23. },
  24. query: {
  25. description: 'A valid stage three Waterline query.',
  26. required: true,
  27. example: '==='
  28. }
  29. },
  30. exits: {
  31. success: {
  32. description: 'The results of the destroy query.',
  33. outputType: 'ref'
  34. },
  35. invalidDatastore: {
  36. description: 'The datastore used is invalid. It is missing key pieces.'
  37. },
  38. badConnection: {
  39. friendlyName: 'Bad connection',
  40. description: 'A connection either could not be obtained or there was an error using the connection.'
  41. }
  42. },
  43. fn: function destroy(inputs, exits) {
  44. // Dependencies
  45. var _ = require('@sailshq/lodash');
  46. var WLUtils = require('waterline-utils');
  47. var Helpers = require('./private');
  48. var Converter = WLUtils.query.converter;
  49. // Store the Query input for easier access
  50. var query = inputs.query;
  51. query.meta = query.meta || {};
  52. // Find the model definition
  53. var model = inputs.models[query.using];
  54. if (!model) {
  55. return exits.invalidDatastore();
  56. }
  57. // Set a flag if a leased connection from outside the adapter was used or not.
  58. var leased = _.has(query.meta, 'leasedConnection');
  59. // Set a flag to determine if records are being returned
  60. var fetchRecords = false;
  61. // ╔═╗╔═╗╔╗╔╦ ╦╔═╗╦═╗╔╦╗ ┌┬┐┌─┐ ┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┐┌┌┬┐
  62. // ║ ║ ║║║║╚╗╔╝║╣ ╠╦╝ ║ │ │ │ └─┐ │ ├─┤ │ ├┤ │││├┤ │││ │
  63. // ╚═╝╚═╝╝╚╝ ╚╝ ╚═╝╩╚═ ╩ ┴ └─┘ └─┘ ┴ ┴ ┴ ┴ └─┘┴ ┴└─┘┘└┘ ┴
  64. // Convert the Waterline criteria into a Waterline Query Statement. This
  65. // turns it into something that is declarative and can be easily used to
  66. // build a SQL query.
  67. // See: https://github.com/treelinehq/waterline-query-docs for more info
  68. // on Waterline Query Statements.
  69. var statement;
  70. try {
  71. statement = Converter({
  72. model: query.using,
  73. method: 'destroy',
  74. criteria: query.criteria
  75. });
  76. } catch (e) {
  77. return exits.error(e);
  78. }
  79. // ╔╦╗╔═╗╔╦╗╔═╗╦═╗╔╦╗╦╔╗╔╔═╗ ┬ ┬┬ ┬┬┌─┐┬ ┬ ┬ ┬┌─┐┬ ┬ ┬┌─┐┌─┐
  80. // ║║║╣ ║ ║╣ ╠╦╝║║║║║║║║╣ │││├─┤││ ├─┤ └┐┌┘├─┤│ │ │├┤ └─┐
  81. // ═╩╝╚═╝ ╩ ╚═╝╩╚═╩ ╩╩╝╚╝╚═╝ └┴┘┴ ┴┴└─┘┴ ┴ └┘ ┴ ┴┴─┘└─┘└─┘└─┘
  82. // ┌┬┐┌─┐ ┬─┐┌─┐┌┬┐┬ ┬┬─┐┌┐┌
  83. // │ │ │ ├┬┘├┤ │ │ │├┬┘│││
  84. // ┴ └─┘ ┴└─└─┘ ┴ └─┘┴└─┘└┘
  85. if (_.has(query.meta, 'fetch') && query.meta.fetch) {
  86. fetchRecords = true;
  87. }
  88. // Find the Primary Key
  89. var primaryKeyField = model.primaryKey;
  90. var primaryKeyColumnName = model.definition[primaryKeyField].columnName;
  91. // ╔═╗╔═╗╔═╗╦ ╦╔╗╔ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  92. // ╚═╗╠═╝╠═╣║║║║║║ │ │ │││││││├┤ │ │ ││ ││││
  93. // ╚═╝╩ ╩ ╩╚╩╝╝╚╝ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  94. // ┌─┐┬─┐ ┬ ┬┌─┐┌─┐ ┬ ┌─┐┌─┐┌─┐┌─┐┌┬┐ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  95. // │ │├┬┘ │ │└─┐├┤ │ ├┤ ├─┤└─┐├┤ ││ │ │ │││││││├┤ │ │ ││ ││││
  96. // └─┘┴└─ └─┘└─┘└─┘ ┴─┘└─┘┴ ┴└─┘└─┘─┴┘ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  97. // Spawn a new connection for running queries on.
  98. Helpers.connection.spawnOrLeaseConnection(inputs.datastore, query.meta, function spawnConnectionCb(err, connection) {
  99. if (err) {
  100. return exits.badConnection(err);
  101. }
  102. // ╦═╗╦ ╦╔╗╔ ┌┬┐┌─┐┌─┐┌┬┐┬─┐┌─┐┬ ┬ ┌─┐ ┬ ┬┌─┐┬─┐┬ ┬
  103. // ╠╦╝║ ║║║║ ││├┤ └─┐ │ ├┬┘│ │└┬┘ │─┼┐│ │├┤ ├┬┘└┬┘
  104. // ╩╚═╚═╝╝╚╝ ─┴┘└─┘└─┘ ┴ ┴└─└─┘ ┴ └─┘└└─┘└─┘┴└─ ┴
  105. Helpers.query.destroy({
  106. connection: connection,
  107. statement: statement,
  108. fetch: fetchRecords,
  109. primaryKey: primaryKeyColumnName
  110. },
  111. function destroyRecordCb(err, destroyedRecords) {
  112. // Always release the connection unless a leased connection from outside
  113. // the adapter was used.
  114. Helpers.connection.releaseConnection(connection, leased, function cb() {
  115. // If there was an error return it.
  116. if (err) {
  117. return exits.error(err);
  118. }
  119. if (fetchRecords) {
  120. var orm = {
  121. collections: inputs.models
  122. };
  123. // Process each record to normalize output
  124. try {
  125. Helpers.query.processEachRecord({
  126. records: destroyedRecords,
  127. identity: model.identity,
  128. orm: orm
  129. });
  130. } catch (e) {
  131. return exits.error(e);
  132. }
  133. return exits.success({ records: destroyedRecords });
  134. }
  135. return exits.success();
  136. }); // </ releaseConnection >
  137. }); // </ runQuery >
  138. }); // </ spawnConnection >
  139. }
  140. });