reslop 0.2.4 → 0.2.6

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/LICENSE +1 -1
  3. package/README.md +12 -13
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -12
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +48 -18
  9. package/lib/dashboard/git.js +128 -0
  10. package/lib/dashboard/model.js +332 -0
  11. package/lib/dashboard/npm.js +193 -0
  12. package/lib/dashboard/tree.js +278 -0
  13. package/lib/deps-diff.js +196 -404
  14. package/lib/deps.js +240 -399
  15. package/lib/detect.js +8 -18
  16. package/lib/diff/align.js +41 -113
  17. package/lib/diff/diff.js +12 -43
  18. package/lib/diff/display.js +25 -36
  19. package/lib/diff/edit.js +6 -20
  20. package/lib/diff/inline.js +138 -141
  21. package/lib/diff/items.js +33 -47
  22. package/lib/diff/parse.js +28 -56
  23. package/lib/diff/patch.js +12 -33
  24. package/lib/diff/unit.js +90 -206
  25. package/lib/editor.js +98 -55
  26. package/lib/files.js +86 -103
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +182 -344
  29. package/lib/git-reword-todo.js +5 -13
  30. package/lib/git-worktree.js +141 -212
  31. package/lib/git.js +21 -49
  32. package/lib/github.js +67 -181
  33. package/lib/gitlab.js +40 -90
  34. package/lib/highlight/bash.js +55 -177
  35. package/lib/highlight/core.js +157 -132
  36. package/lib/highlight/css.js +25 -58
  37. package/lib/highlight/csv.js +19 -37
  38. package/lib/highlight/dart.js +72 -213
  39. package/lib/highlight/dot.js +16 -26
  40. package/lib/highlight/html.js +42 -63
  41. package/lib/highlight/js.js +177 -506
  42. package/lib/highlight/json.js +17 -37
  43. package/lib/highlight/log.js +22 -35
  44. package/lib/highlight/txt.js +9 -22
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +62 -85
  47. package/lib/manifest.js +67 -130
  48. package/lib/npm-commands.js +119 -189
  49. package/lib/remote.js +141 -197
  50. package/lib/render/branches.js +66 -73
  51. package/lib/render/chrome.js +264 -323
  52. package/lib/render/commits.js +187 -500
  53. package/lib/render/dash-activity.js +212 -0
  54. package/lib/render/dash-blocks.js +245 -0
  55. package/lib/render/dash-table.js +290 -0
  56. package/lib/render/dashboard.js +62 -0
  57. package/lib/render/diff.js +123 -228
  58. package/lib/render/files.js +45 -99
  59. package/lib/render/frame.js +129 -183
  60. package/lib/render/notes.js +144 -160
  61. package/lib/render/npm.js +234 -112
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +131 -170
  64. package/lib/render/render.js +5 -14
  65. package/lib/render/report.js +43 -0
  66. package/lib/render/tiles.js +260 -0
  67. package/lib/render/unit.js +15 -28
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -38
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -78
  72. package/lib/report-test.js +256 -141
  73. package/lib/report-tools.js +96 -161
  74. package/lib/review-merge.js +114 -152
  75. package/lib/review.js +115 -189
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +89 -75
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +82 -63
  80. package/lib/session/branches.js +193 -247
  81. package/lib/session/change-actions.js +171 -214
  82. package/lib/session/commit.js +280 -342
  83. package/lib/session/compose.js +559 -674
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +164 -157
  86. package/lib/session/edit-click.js +57 -0
  87. package/lib/session/files-pane.js +85 -53
  88. package/lib/session/items.js +73 -104
  89. package/lib/session/lifecycle.js +403 -541
  90. package/lib/session/load.js +48 -68
  91. package/lib/session/navigation.js +96 -87
  92. package/lib/session/npm.js +409 -345
  93. package/lib/session/ops.js +196 -63
  94. package/lib/session/pointer.js +23 -15
  95. package/lib/session/progress.js +33 -21
  96. package/lib/session/review.js +33 -54
  97. package/lib/session/tasks.js +333 -0
  98. package/lib/session/templates.js +51 -59
  99. package/lib/session/terminal.js +85 -136
  100. package/lib/session/unit.js +3 -4
  101. package/lib/session/update.js +76 -97
  102. package/lib/session/view.js +52 -83
  103. package/lib/session/watch.js +208 -204
  104. package/lib/session.js +112 -237
  105. package/lib/update.js +45 -116
  106. package/lib/utilities.js +67 -89
  107. package/lib/wrap.js +33 -44
  108. package/package.json +1 -1
  109. package/lib/session/todos.js +0 -293
@@ -1,48 +1,184 @@
1
1
  'use strict';
2
2
 
3
- const accessors = require('./accessors.js');
4
- const { stateView } = accessors;
5
-
6
3
  const ASYNC_WITHOUT_UI = ['pull', 'push'];
4
+ const QUIET_KIND = new Set(['staged', 'unstaged']);
7
5
 
8
6
  const pickRepoWrite = (repo, name, uiOpen) => {
9
7
  const asyncFn = repo[`${name}Async`];
10
8
  const allowAsync = uiOpen === true || ASYNC_WITHOUT_UI.includes(name);
11
- if (allowAsync && typeof asyncFn === 'function') {
12
- return {
13
- async: true,
14
- write: (top, ...args) => asyncFn(top, ...args),
15
- };
16
- }
17
- const syncFn = repo[name];
18
- return {
19
- async: false,
20
- write: (top, ...args) => syncFn(top, ...args),
21
- };
9
+ const isAsync = allowAsync && typeof asyncFn === 'function';
10
+ return { async: isAsync, write: isAsync ? asyncFn : repo[name] };
22
11
  };
23
12
 
24
- const createOpsRunner = (ui) => {
25
- const state = {
26
- gitBusy: false,
27
- busy: '',
28
- };
13
+ const showsBusy = (kind) => Boolean(kind) && !QUIET_KIND.has(kind);
14
+
15
+ class ChangeQueue {
16
+ constructor(ui, runner) {
17
+ this.ui = ui;
18
+ this.runner = runner;
19
+ this.jobs = [];
20
+ this.head = 0;
21
+ this.epoch = 0;
22
+ this.draining = false;
23
+ this.pumpQueued = false;
24
+ this.holding = false;
25
+ this.resume = null;
26
+ this.reloading = false;
27
+ }
28
+
29
+ noteFree() {
30
+ const resume = this.resume;
31
+ this.resume = null;
32
+ if (resume) resume();
33
+ }
34
+
35
+ dropJobs() {
36
+ this.jobs = [];
37
+ this.head = 0;
38
+ }
39
+
40
+ reset() {
41
+ this.epoch += 1;
42
+ this.dropJobs();
43
+ this.draining = false;
44
+ this.pumpQueued = false;
45
+ this.holding = false;
46
+ this.reloading = false;
47
+ this.noteFree();
48
+ }
49
+
50
+ armBusy(kind) {
51
+ if (!showsBusy(kind)) return;
52
+ this.ui.status = '';
53
+ this.ui.progressFrame = 0;
54
+ this.runner.setBusy(kind);
55
+ }
56
+
57
+ waitTurn() {
58
+ if (!this.runner.gitBusy || this.holding) return Promise.resolve();
59
+ return new Promise((resolve) => {
60
+ this.resume = resolve;
61
+ });
62
+ }
63
+
64
+ hasPendingBusy() {
65
+ const { jobs, head } = this;
66
+ for (let i = head; i < jobs.length; i++) {
67
+ if (showsBusy(jobs[i].kind)) return true;
68
+ }
69
+ return false;
70
+ }
71
+
72
+ releaseHold() {
73
+ this.holding = false;
74
+ this.runner.gitBusy = false;
75
+ this.noteFree();
76
+ }
77
+
78
+ startReload() {
79
+ const { ui } = this;
80
+ this.reloading = true;
81
+ ui.reloadAfterChange(() => {
82
+ this.reloading = false;
83
+ ui.paint();
84
+ });
85
+ }
86
+
87
+ async takeJob(stamp) {
88
+ const job = this.jobs[this.head];
89
+ this.head += 1;
90
+ this.armBusy(job.kind);
91
+ try {
92
+ await job.write(this.ui.top);
93
+ } catch (error) {
94
+ if (stamp !== this.epoch) return 'stale';
95
+ this.ui.status = error.message;
96
+ return 'fail';
97
+ }
98
+ if (stamp !== this.epoch) return 'stale';
99
+ if (job.done) this.ui.status = job.done;
100
+ if (!this.hasPendingBusy()) this.runner.clearBusy();
101
+ return job.reload ? 'reload' : 'ok';
102
+ }
103
+
104
+ schedule() {
105
+ if (this.draining || this.pumpQueued) return;
106
+ this.pumpQueued = true;
107
+ queueMicrotask(() => {
108
+ this.pumpQueued = false;
109
+ void this.run();
110
+ });
111
+ }
112
+
113
+ finish(stamp, needReload) {
114
+ if (stamp !== this.epoch) return;
115
+ this.draining = false;
116
+ this.releaseHold();
117
+ if (this.head < this.jobs.length) return void this.schedule();
118
+ this.dropJobs();
119
+ if (needReload) this.startReload();
120
+ else this.ui.paint();
121
+ }
122
+
123
+ async run() {
124
+ const stamp = this.epoch;
125
+ this.draining = true;
126
+ if (this.runner.gitBusy && !this.holding) await this.waitTurn();
127
+ if (stamp !== this.epoch) return;
128
+ this.holding = true;
129
+ this.runner.gitBusy = true;
130
+ let needReload = false;
131
+ while (this.head < this.jobs.length) {
132
+ const result = await this.takeJob(stamp);
133
+ if (result === 'stale') return;
134
+ if (result === 'fail') {
135
+ needReload = true;
136
+ this.dropJobs();
137
+ break;
138
+ }
139
+ if (result === 'reload') needReload = true;
140
+ }
141
+ this.finish(stamp, needReload);
142
+ }
143
+
144
+ enqueue(job) {
145
+ if (this.reloading) {
146
+ this.ui.loader.bump();
147
+ this.reloading = false;
148
+ job.reload = true;
149
+ }
150
+ this.jobs.push(job);
151
+ this.armBusy(job.kind);
152
+ this.schedule();
153
+ }
154
+ }
155
+
156
+ class OpsRunner {
157
+ constructor(ui) {
158
+ this.ui = ui;
159
+ this.gitBusy = false;
160
+ this.busy = '';
161
+ this.queue = new ChangeQueue(ui, this);
162
+ }
29
163
 
30
- const reset = () => {
31
- state.gitBusy = false;
32
- state.busy = '';
33
- };
164
+ setBusy(kind) {
165
+ this.busy = kind;
166
+ this.ui.startProgress();
167
+ }
34
168
 
35
- const setBusy = (kind) => {
36
- state.busy = kind;
37
- ui.startProgress();
38
- };
169
+ clearBusy() {
170
+ this.busy = '';
171
+ this.ui.stopProgress();
172
+ }
39
173
 
40
- const clearBusy = () => {
41
- state.busy = '';
42
- ui.stopProgress();
43
- };
174
+ reset() {
175
+ this.gitBusy = false;
176
+ this.busy = '';
177
+ this.queue.reset();
178
+ }
44
179
 
45
- const runRepo = (label, write) => {
180
+ runRepo(label, write) {
181
+ const { ui } = this;
46
182
  try {
47
183
  write(ui.top);
48
184
  ui.status = label;
@@ -51,21 +187,23 @@ const createOpsRunner = (ui) => {
51
187
  ui.status = error.message;
52
188
  return false;
53
189
  }
54
- };
190
+ }
55
191
 
56
- const finishBusy = (done, after) => {
192
+ finishBusy(done, after) {
193
+ const { ui } = this;
57
194
  if (ui.done || ui.mode === 'confirmPush') return void ui.paint();
58
195
  if (!ui.status && after) after();
59
- if (!ui.status && !state.busy) ui.status = done;
196
+ if (!ui.status && !this.busy) ui.status = done;
60
197
  ui.paint();
61
- };
198
+ }
62
199
 
63
- const runBusy = async (kind, done, write, after) => {
64
- if (state.gitBusy) return;
65
- state.gitBusy = true;
200
+ async runBusy(kind, done, write, after) {
201
+ const { ui } = this;
202
+ if (this.gitBusy) return;
203
+ this.gitBusy = true;
66
204
  ui.status = '';
67
205
  ui.progressFrame = 0;
68
- setBusy(kind);
206
+ this.setBusy(kind);
69
207
  ui.paint();
70
208
  try {
71
209
  await write(ui.top);
@@ -76,36 +214,31 @@ const createOpsRunner = (ui) => {
76
214
  ui.status = error.message;
77
215
  }
78
216
  } finally {
79
- clearBusy();
80
- state.gitBusy = false;
217
+ this.clearBusy();
218
+ this.gitBusy = false;
219
+ this.queue.noteFree();
81
220
  }
82
- finishBusy(done, after);
83
- };
221
+ this.finishBusy(done, after);
222
+ }
84
223
 
85
- const runWrite = (name, args, kind, done, after) => {
224
+ runWrite(name, args, kind, done, after, leave = null) {
225
+ const { ui } = this;
86
226
  const picked = pickRepoWrite(ui.repo, name, ui.uiOpen);
87
227
  const write = (top) => picked.write(top, ...args);
88
228
  if (picked.async) {
229
+ if (leave) leave();
89
230
  const refresh = () => after({ doneStatus: done });
90
- return void runBusy(kind, done, write, refresh);
231
+ return void this.runBusy(kind, done, write, refresh);
91
232
  }
92
- if (!runRepo(done, write)) return;
233
+ if (!this.runRepo(done, write)) return;
234
+ if (leave) leave();
93
235
  after({});
94
236
  if (!ui.status) ui.status = done;
95
- };
96
-
97
- return stateView(
98
- state,
99
- {
100
- reset,
101
- setBusy,
102
- clearBusy,
103
- runRepo,
104
- runWrite,
105
- runBusy,
106
- },
107
- ['gitBusy', 'busy'],
108
- );
109
- };
237
+ }
238
+
239
+ enqueueLazy(job) {
240
+ this.queue.enqueue(job);
241
+ }
242
+ }
110
243
 
111
- module.exports = { ASYNC_WITHOUT_UI, pickRepoWrite, createOpsRunner };
244
+ module.exports = { pickRepoWrite, OpsRunner };
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const select = require('../select.js');
4
+ const editClick = require('./edit-click.js');
5
+ const filesPane = require('./files-pane.js');
4
6
  const { extractText, isRange } = select;
5
7
  const keys = require('../keys.js');
6
8
  const { hitAction } = keys;
@@ -93,23 +95,30 @@ const RELEASE_TARGETS = [
93
95
  hits: 'statusHits',
94
96
  onHit: (ui, hit) => {
95
97
  if (hit.id === 'branch') return void ui.gitBranches.onBranch();
96
- ui.input.confirmChoice(hit.id);
98
+ ui.confirmChoice(hit.id);
97
99
  },
98
100
  },
101
+ {
102
+ match: (ui) => ui.pane === 'dashboard',
103
+ hits: 'fileHits',
104
+ onHit: (ui, hit) => ui.dashboard.open(hit.cursor),
105
+ },
99
106
  {
100
107
  match: (ui) => ui.pane === 'files',
101
108
  hits: 'fileHits',
102
109
  onHit: (ui, hit) => {
110
+ const again = armDoubleClick(ui.nav, 'files', hit.cursor);
103
111
  ui.nav.fileCursor = hit.cursor;
104
- ui.filesPane.onOpenFile();
112
+ if (again) filesPane.onOpenFile(ui);
105
113
  },
106
114
  },
107
115
  {
108
116
  match: (ui) => ui.pane === 'branches',
109
117
  hits: 'fileHits',
110
118
  onHit: (ui, hit) => {
119
+ const again = armDoubleClick(ui.nav, 'branches', hit.cursor);
111
120
  ui.nav.branchCursor = hit.cursor;
112
- ui.gitBranches.onCheckoutBranch();
121
+ if (again) ui.gitBranches.onCheckoutBranch();
113
122
  },
114
123
  },
115
124
  {
@@ -117,7 +126,9 @@ const RELEASE_TARGETS = [
117
126
  hits: 'fileHits',
118
127
  onHit: (ui, hit) => {
119
128
  if (ui.mode === 'compose') return;
129
+ const again = armDoubleClick(ui.nav, 'commits', hit.cursor);
120
130
  ui.nav.commitCursor = hit.cursor;
131
+ if (again) filesPane.onOpenFile(ui);
121
132
  },
122
133
  },
123
134
  {
@@ -130,11 +141,11 @@ const RELEASE_TARGETS = [
130
141
  },
131
142
  },
132
143
  {
133
- match: (ui) => ui.pane === 'diff',
134
- hits: 'todoHits',
144
+ match: (ui) => ui.pane === 'tasks',
145
+ hits: 'taskHits',
135
146
  onHit: (ui, hit) => {
136
- if (hit.check) return void ui.composer.onTodoCheck(hit.cursor);
137
- ui.composer.onTodoHit(hit.cursor);
147
+ if (hit.check) return void ui.composer.tasks.onTaskCheck(hit.cursor);
148
+ ui.composer.tasks.onTaskHit(hit.cursor);
138
149
  },
139
150
  },
140
151
  {
@@ -154,6 +165,7 @@ const onRelease = (ui, event) => {
154
165
  nav.pendingClick = null;
155
166
  nav.mouseAnchor = null;
156
167
  if (clickButton(ui, cell, clickId)) return;
168
+ if (editClick.placeClick(ui, cell)) return;
157
169
  const frame = ui.lastFrame;
158
170
  for (const target of RELEASE_TARGETS) {
159
171
  if (!target.match(ui)) continue;
@@ -165,14 +177,14 @@ const onRelease = (ui, event) => {
165
177
  };
166
178
 
167
179
  const POINTER_HANDLERS = {
168
- wheelUp: (ui) => ui.filesPane.onScroll(-1),
169
- wheelDown: (ui) => ui.filesPane.onScroll(1),
180
+ wheelUp: (ui) => filesPane.onScroll(ui, -1),
181
+ wheelDown: (ui) => filesPane.onScroll(ui, 1),
170
182
  press: onPress,
171
183
  drag: onDrag,
172
184
  release: onRelease,
173
185
  };
174
186
 
175
- const handle = (ui, event) => {
187
+ const handlePointer = (ui, event) => {
176
188
  const kind = event.kind;
177
189
  const handler = POINTER_HANDLERS[kind];
178
190
  if (!handler) return;
@@ -181,8 +193,4 @@ const handle = (ui, event) => {
181
193
  handler(ui, event);
182
194
  };
183
195
 
184
- const createPointer = (ui) => ({
185
- handle: (event) => handle(ui, event),
186
- });
187
-
188
- module.exports = { createPointer };
196
+ module.exports = { handlePointer };
@@ -1,29 +1,41 @@
1
1
  'use strict';
2
2
 
3
- const createProgress = (term, onTick, intervalMs) => {
4
- const active = new Set();
3
+ class Progress {
4
+ constructor(term, onTick, intervalMs) {
5
+ this.term = term;
6
+ this.onTick = onTick;
7
+ this.intervalMs = intervalMs;
8
+ this.active = new Set();
9
+ }
5
10
 
6
- const start = (id) => {
7
- const wasEmpty = active.size === 0;
8
- active.add(id);
9
- if (wasEmpty) {
10
- term.startTimer('progress', onTick, intervalMs);
11
- }
12
- };
11
+ tick() {
12
+ if (!this.active.size) return;
13
+ this.onTick();
14
+ this.schedule();
15
+ }
13
16
 
14
- const stop = (id) => {
15
- active.delete(id);
16
- if (active.size === 0) term.stopTimer('progress');
17
- };
17
+ schedule() {
18
+ this.term.later('progress', () => this.tick(), this.intervalMs);
19
+ }
18
20
 
19
- const clear = () => {
20
- active.clear();
21
- term.stopTimer('progress');
22
- };
21
+ start(id) {
22
+ this.active.add(id);
23
+ this.schedule();
24
+ }
23
25
 
24
- const size = () => active.size;
26
+ stop(id) {
27
+ this.active.delete(id);
28
+ if (!this.active.size) this.term.cancel('progress');
29
+ }
25
30
 
26
- return { start, stop, clear, size };
27
- };
31
+ clear() {
32
+ this.active.clear();
33
+ this.term.cancel('progress');
34
+ }
28
35
 
29
- module.exports = { createProgress };
36
+ size() {
37
+ return this.active.size;
38
+ }
39
+ }
40
+
41
+ module.exports = { Progress };
@@ -1,75 +1,54 @@
1
1
  'use strict';
2
2
 
3
- const accessors = require('./accessors.js');
4
- const { stateView } = accessors;
5
-
6
3
  const review = require('../review.js');
7
4
  const { createStore, applyImportedNotes, setStatus } = review;
8
5
  const { listReviewNames, loadTemplates, resolveReviewPath } = review;
9
6
  const { loadReview, flushReview } = review;
10
7
 
11
- const createReviewController = () => {
12
- const state = {
13
- store: null,
14
- didResume: false,
15
- importedRemote: false,
16
- };
8
+ class ReviewController {
9
+ constructor() {
10
+ this.reset();
11
+ }
17
12
 
18
- const reset = () => {
19
- state.store = null;
20
- state.didResume = false;
21
- state.importedRemote = false;
22
- };
13
+ reset() {
14
+ this.store = null;
15
+ this.didResume = false;
16
+ this.importedRemote = false;
17
+ }
23
18
 
24
- const init = (dir, date, extra = {}) => {
19
+ init(dir, date, extra = {}) {
25
20
  const names = listReviewNames(dir);
26
21
  const templates = loadTemplates(dir);
27
22
  const resolved = resolveReviewPath(dir, date, names, extra);
28
- if (resolved.resume) {
29
- state.store = loadReview(resolved.reviewPath, templates);
30
- state.didResume = true;
31
- return state.store;
32
- }
33
- state.store = createStore(resolved.reviewPath, templates);
34
- state.didResume = false;
35
- return state.store;
36
- };
37
-
38
- const applyImported = (imported) => {
39
- if (!imported || !state.store) return false;
40
- if (state.didResume || state.importedRemote) return false;
41
- applyImportedNotes(state.store, imported);
42
- state.importedRemote = true;
23
+ this.didResume = resolved.resume === true;
24
+ this.store = this.didResume
25
+ ? loadReview(resolved.reviewPath, templates)
26
+ : createStore(resolved.reviewPath, templates);
27
+ return this.store;
28
+ }
29
+
30
+ applyImported(imported) {
31
+ if (!imported || !this.store) return false;
32
+ if (this.didResume || this.importedRemote) return false;
33
+ applyImportedNotes(this.store, imported);
34
+ this.importedRemote = true;
43
35
  return true;
44
- };
36
+ }
45
37
 
46
- const flush = (force = false) => {
47
- if (!state.store) return { ok: true, wrote: false };
38
+ flush(force = false) {
39
+ if (!this.store) return { ok: true, wrote: false };
48
40
  try {
49
- const wrote = flushReview(state.store, force);
41
+ const wrote = flushReview(this.store, force);
50
42
  return { ok: true, wrote };
51
43
  } catch (error) {
52
44
  return { ok: false, wrote: false, error };
53
45
  }
54
- };
55
-
56
- const finishQuit = (status) => {
57
- setStatus(state.store, status);
58
- return flush();
59
- };
46
+ }
60
47
 
61
- return stateView(
62
- state,
63
- {
64
- reset,
65
- init,
66
- applyImported,
67
- flush,
68
- finishQuit,
69
- },
70
- [],
71
- ['store', 'didResume', 'importedRemote'],
72
- );
73
- };
48
+ finishQuit(status) {
49
+ setStatus(this.store, status);
50
+ return this.flush();
51
+ }
52
+ }
74
53
 
75
- module.exports = { createReviewController };
54
+ module.exports = { ReviewController };