memory.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { parse as parserExpression } from 'pivotql-parser-expression';
  2. import { compile as compilerJavascript } from 'pivotql-compiler-javascript';
  3. import { throwError } from '../../error.js';
  4. import { uid } from '../../uid.js';
  5. import { DEFAULT_BOX_OPTIONS } from './utils.js';
  6. // Memory backend for proof of concept
  7. export const MemoryBackend = () => {
  8. const dataMemoryStore = {};
  9. const boxOptions = {};
  10. const getOrCreateBox = (boxId) => {
  11. if (typeof dataMemoryStore[boxId] !== 'object') {
  12. dataMemoryStore[boxId] = {};
  13. }
  14. return dataMemoryStore[boxId];
  15. };
  16. const filterObjectProperties = (obj, propArr) => {
  17. const newObj = {};
  18. for (let key in obj) {
  19. if (propArr.includes(key)) {
  20. newObj[key] = obj[key];
  21. }
  22. }
  23. return newObj;
  24. };
  25. return {
  26. async getBoxOption(boxId) {
  27. return boxOptions[boxId];
  28. },
  29. async createOrUpdateBox(boxId, options = { ...DEFAULT_BOX_OPTIONS }) {
  30. getOrCreateBox(boxId);
  31. boxOptions[boxId] = options;
  32. return { box: boxId, ...options };
  33. },
  34. async list(
  35. boxId,
  36. {
  37. limit = 50,
  38. sort = '_id',
  39. asc = true,
  40. skip = 0,
  41. onlyFields = [],
  42. q,
  43. } = {}
  44. ) {
  45. if (dataMemoryStore[boxId] === undefined) {
  46. throwError('Box not found', 404);
  47. }
  48. let filter = () => true;
  49. if (q) {
  50. try {
  51. filter = compilerJavascript(parserExpression(q));
  52. } catch (e) {
  53. throwError('Invalid query expression.', 400);
  54. }
  55. }
  56. let result = Object.values(dataMemoryStore[boxId]);
  57. result = result.filter(filter);
  58. result.sort((resource1, resource2) => {
  59. if (resource1[sort] < resource2[sort]) {
  60. return asc ? -1 : 1;
  61. }
  62. if (resource1[sort] > resource2[sort]) {
  63. return asc ? 1 : -1;
  64. }
  65. return 0;
  66. });
  67. result = result.slice(skip, skip + limit);
  68. if (onlyFields.length) {
  69. result = result.map((resource) =>
  70. filterObjectProperties(resource, onlyFields)
  71. );
  72. }
  73. return result;
  74. },
  75. async get(boxId, id) {
  76. if (!dataMemoryStore[boxId]) {
  77. throwError('Box not found', 404);
  78. }
  79. if (!dataMemoryStore[boxId][id]) {
  80. throwError('Resource not found', 404);
  81. }
  82. return dataMemoryStore[boxId][id];
  83. },
  84. async save(boxId, id, data) {
  85. if (dataMemoryStore[boxId] === undefined) {
  86. throwError('Box not found', 404);
  87. }
  88. const cleanedData = data;
  89. delete cleanedData._createdOn;
  90. delete cleanedData._modifiedOn;
  91. const actualId = id || uid();
  92. const box = dataMemoryStore[boxId];
  93. let newRessource = null;
  94. if (box[actualId]) {
  95. // Update
  96. newRessource = {
  97. ...cleanedData,
  98. _id: actualId,
  99. _createdOn: box[actualId]._createdOn,
  100. _updatedOn: Date.now(),
  101. };
  102. box[actualId] = newRessource;
  103. } else {
  104. newRessource = {
  105. ...cleanedData,
  106. _id: actualId,
  107. _createdOn: Date.now(),
  108. };
  109. box[actualId] = newRessource;
  110. }
  111. return newRessource;
  112. },
  113. async update(boxId, id, data) {
  114. if (!dataMemoryStore[boxId]) {
  115. throwError('Box not found', 404);
  116. }
  117. if (!dataMemoryStore[boxId][id]) {
  118. throwError('Ressource not found', 404);
  119. }
  120. const cleanedData = data;
  121. delete cleanedData._createdOn;
  122. delete cleanedData._modifiedOn;
  123. // To prevent created modification
  124. const currentData = dataMemoryStore[boxId][id];
  125. const updatedItem = {
  126. ...currentData,
  127. ...cleanedData,
  128. _id: id,
  129. _updatedOn: Date.now(),
  130. };
  131. dataMemoryStore[boxId][id] = updatedItem;
  132. return updatedItem;
  133. },
  134. async delete(boxId, id) {
  135. if (!dataMemoryStore[boxId]) {
  136. return 0;
  137. }
  138. if (dataMemoryStore[boxId][id] !== undefined) {
  139. delete dataMemoryStore[boxId][id];
  140. return 1;
  141. }
  142. return 0;
  143. },
  144. };
  145. };
  146. export default MemoryBackend;