@next-k8s/tickets 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. package/.dockerignore +1 -0
  2. package/CHANGELOG.md +72 -0
  3. package/Dockerfile +7 -0
  4. package/build/__mocks__/nats-client.js +12 -0
  5. package/build/app.js +31 -0
  6. package/build/events/publishers/tickets/created.js +12 -0
  7. package/build/events/publishers/tickets/updated.js +12 -0
  8. package/build/index.js +45 -0
  9. package/build/models/ticket.js +37 -0
  10. package/build/nats-client.js +42 -0
  11. package/build/routes/__test__/create.test.js +85 -0
  12. package/build/routes/__test__/find.test.js +30 -0
  13. package/build/routes/__test__/get.test.js +43 -0
  14. package/build/routes/__test__/update.test.js +95 -0
  15. package/build/routes/create.js +33 -0
  16. package/build/routes/find.js +22 -0
  17. package/build/routes/get.js +28 -0
  18. package/build/routes/index.js +10 -0
  19. package/build/routes/update.js +41 -0
  20. package/build/test/setup.js +34 -0
  21. package/build/test/utils.js +33 -0
  22. package/package.json +53 -0
  23. package/pnpm-lock.yaml +3641 -0
  24. package/src/__mocks__/nats-client.ts +10 -0
  25. package/src/app.ts +21 -0
  26. package/src/events/publishers/tickets/created.ts +7 -0
  27. package/src/events/publishers/tickets/updated.ts +7 -0
  28. package/src/index.ts +31 -0
  29. package/src/models/ticket.ts +42 -0
  30. package/src/nats-client.ts +30 -0
  31. package/src/routes/__test__/create.test.ts +83 -0
  32. package/src/routes/__test__/find.test.ts +18 -0
  33. package/src/routes/__test__/get.test.ts +34 -0
  34. package/src/routes/__test__/update.test.ts +101 -0
  35. package/src/routes/create.ts +24 -0
  36. package/src/routes/find.ts +11 -0
  37. package/src/routes/get.ts +16 -0
  38. package/src/routes/index.ts +8 -0
  39. package/src/routes/update.ts +29 -0
  40. package/src/test/setup.ts +24 -0
  41. package/src/test/utils.ts +18 -0
  42. package/tsconfig.json +101 -0
package/.dockerignore ADDED
@@ -0,0 +1 @@
1
+ node_modules
package/CHANGELOG.md ADDED
@@ -0,0 +1,72 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [1.0.9](https://github.com/mathiscode/next-k8s-boilerplate/compare/@next-k8s/tickets@1.0.8...@next-k8s/tickets@1.0.9) (2022-07-06)
7
+
8
+ **Note:** Version bump only for package @next-k8s/tickets
9
+
10
+
11
+
12
+
13
+
14
+ ## 1.0.8 (2022-07-06)
15
+
16
+ **Note:** Version bump only for package @next-k8s/tickets
17
+
18
+
19
+
20
+
21
+
22
+ ## 1.0.7 (2022-07-06)
23
+
24
+ **Note:** Version bump only for package @next-k8s/tickets
25
+
26
+
27
+
28
+
29
+
30
+ ## 1.0.6 (2022-07-06)
31
+
32
+ **Note:** Version bump only for package @next-k8s/tickets
33
+
34
+
35
+
36
+
37
+
38
+ ## 1.0.5 (2022-07-05)
39
+
40
+ **Note:** Version bump only for package @next-k8s/tickets
41
+
42
+
43
+
44
+
45
+
46
+ ## 1.0.4 (2022-07-05)
47
+
48
+ **Note:** Version bump only for package @next-k8s/tickets
49
+
50
+
51
+
52
+
53
+
54
+ ## 1.0.3 (2022-07-05)
55
+
56
+ **Note:** Version bump only for package @next-k8s/tickets
57
+
58
+
59
+
60
+
61
+
62
+ ## 1.0.2 (2022-07-05)
63
+
64
+ **Note:** Version bump only for package @next-k8s/tickets
65
+
66
+
67
+
68
+
69
+
70
+ ## 1.0.1 (2022-07-05)
71
+
72
+ **Note:** Version bump only for package @next-k8s/tickets
package/Dockerfile ADDED
@@ -0,0 +1,7 @@
1
+ FROM node:alpine
2
+ WORKDIR /app
3
+ COPY package.json .
4
+ RUN npm install --omit=dev
5
+ COPY . .
6
+
7
+ CMD ["npm", "start"]
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.natsClient = void 0;
4
+ exports.natsClient = {
5
+ client: {
6
+ publish: jest.fn()
7
+ .mockImplementation((subject, data, callback) => {
8
+ callback();
9
+ })
10
+ }
11
+ };
12
+ exports.default = exports.natsClient;
package/build/app.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const express_1 = __importDefault(require("express"));
16
+ require("express-async-errors");
17
+ const body_parser_1 = require("body-parser");
18
+ const cookie_session_1 = __importDefault(require("cookie-session"));
19
+ const common_1 = require("@next-k8s/common");
20
+ const routes_1 = __importDefault(require("./routes"));
21
+ const app = (0, express_1.default)();
22
+ app.disable('x-powered-by');
23
+ app.set('trust proxy', true);
24
+ app.use((0, body_parser_1.json)());
25
+ app.use((0, cookie_session_1.default)({ signed: false, secure: process.env.NODE_ENV !== 'test' }));
26
+ app.use(common_1.currentUser);
27
+ for (const route of routes_1.default)
28
+ app.use(route);
29
+ app.use('*', (req, res) => __awaiter(void 0, void 0, void 0, function* () { throw new common_1.NotFoundError(); }));
30
+ app.use(common_1.errorHandler);
31
+ exports.default = app;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TicketCreatedPublisher = void 0;
4
+ const common_1 = require("@next-k8s/common");
5
+ class TicketCreatedPublisher extends common_1.Publisher {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.subject = common_1.Subjects.TicketCreated;
9
+ }
10
+ }
11
+ exports.TicketCreatedPublisher = TicketCreatedPublisher;
12
+ exports.default = TicketCreatedPublisher;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TicketUpdatedPublisher = void 0;
4
+ const common_1 = require("@next-k8s/common");
5
+ class TicketUpdatedPublisher extends common_1.Publisher {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.subject = common_1.Subjects.TicketUpdated;
9
+ }
10
+ }
11
+ exports.TicketUpdatedPublisher = TicketUpdatedPublisher;
12
+ exports.default = TicketUpdatedPublisher;
package/build/index.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const mongoose_1 = __importDefault(require("mongoose"));
16
+ const nats_client_1 = __importDefault(require("./nats-client"));
17
+ const app_1 = __importDefault(require("./app"));
18
+ const start = () => __awaiter(void 0, void 0, void 0, function* () {
19
+ if (!process.env.JWT_KEY)
20
+ throw new Error('JWT_KEY is undefined');
21
+ if (!process.env.MONGO_URI)
22
+ throw new Error('MONGO_URI is undefined');
23
+ if (!process.env.NATS_URL)
24
+ throw new Error('NATS_URL is undefined');
25
+ if (!process.env.NATS_CLUSTER_ID)
26
+ throw new Error('NATS_CLUSTER_ID is undefined');
27
+ if (!process.env.NATS_CLIENT_ID)
28
+ throw new Error('NATS_CLIENT_ID is undefined');
29
+ yield nats_client_1.default.connect(process.env.NATS_CLUSTER_ID, process.env.NATS_CLIENT_ID, process.env.NATS_URL);
30
+ nats_client_1.default.client.on('close', () => {
31
+ var _a;
32
+ if (!((_a = process.env.NODE_ENV) === null || _a === void 0 ? void 0 : _a.includes('test')))
33
+ console.log('NATS connection closed');
34
+ process.exit();
35
+ });
36
+ process.on('SIGINT', () => nats_client_1.default.client.close());
37
+ process.on('SIGTERM', () => nats_client_1.default.client.close());
38
+ yield mongoose_1.default.connect(process.env.MONGO_URI);
39
+ console.log('Database connected!');
40
+ const port = process.env.PORT || 3000;
41
+ app_1.default.listen(port, () => {
42
+ console.log('Service running on port:', port);
43
+ });
44
+ });
45
+ start();
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TicketModel = void 0;
7
+ const mongoose_1 = __importDefault(require("mongoose"));
8
+ const ticketSchema = new mongoose_1.default.Schema({
9
+ title: {
10
+ type: String,
11
+ required: true
12
+ },
13
+ price: {
14
+ type: Number,
15
+ required: true
16
+ },
17
+ owner: {
18
+ type: String,
19
+ required: true
20
+ }
21
+ }, {
22
+ toJSON: {
23
+ versionKey: false,
24
+ transform(doc, ret) {
25
+ ret.id = ret._id;
26
+ delete ret._id;
27
+ delete ret.password;
28
+ }
29
+ }
30
+ });
31
+ exports.TicketModel = mongoose_1.default.model('Ticket', ticketSchema);
32
+ class Ticket extends exports.TicketModel {
33
+ constructor(attributes) {
34
+ super(attributes);
35
+ }
36
+ }
37
+ exports.default = Ticket;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.natsClient = void 0;
16
+ const node_nats_streaming_1 = __importDefault(require("node-nats-streaming"));
17
+ class NatsClient {
18
+ get client() {
19
+ if (!this._client)
20
+ throw new Error('Cannot access NATS client before connecting');
21
+ return this._client;
22
+ }
23
+ connect(clusterId, clientId, url) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ this._client = node_nats_streaming_1.default.connect(clusterId, clientId, { url });
26
+ return new Promise((resolve, reject) => {
27
+ this.client.on('connect', () => {
28
+ var _a;
29
+ if (!((_a = process.env.NODE_ENV) === null || _a === void 0 ? void 0 : _a.includes('test')))
30
+ console.log('Connected to NATS');
31
+ resolve();
32
+ });
33
+ this.client.on('error', (err) => {
34
+ console.error(err);
35
+ reject(err);
36
+ });
37
+ });
38
+ });
39
+ }
40
+ }
41
+ exports.natsClient = new NatsClient();
42
+ exports.default = exports.natsClient;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const supertest_1 = __importDefault(require("supertest"));
16
+ const app_1 = __importDefault(require("../../app"));
17
+ const ticket_1 = __importDefault(require("../../models/ticket"));
18
+ const nats_client_1 = __importDefault(require("../../nats-client"));
19
+ const utils_1 = require("../../test/utils");
20
+ // const createTicket = (cookie?: string, title = 'Test Event', price = 20000, expectedStatusCode = 201) => {
21
+ // return request(app)
22
+ // .post('/api/tickets')
23
+ // .set('Cookie', cookie ? [cookie] : [])
24
+ // .send({ title, price })
25
+ // .expect(expectedStatusCode)
26
+ // }
27
+ describe('[Create New Ticket] Route: /api/tickets', () => {
28
+ it('should be a valid route', () => __awaiter(void 0, void 0, void 0, function* () {
29
+ const response = yield (0, supertest_1.default)(app_1.default).post('/api/tickets').send({});
30
+ expect(response.status).not.toEqual(404);
31
+ }));
32
+ it('should throw UnauthorizedError if unauthenticated', () => __awaiter(void 0, void 0, void 0, function* () {
33
+ const response = yield (0, supertest_1.default)(app_1.default).post('/api/tickets').send({});
34
+ expect(response.status).toEqual(401);
35
+ }));
36
+ it('should not get UnauthorizedError if authenticated', () => __awaiter(void 0, void 0, void 0, function* () {
37
+ const cookie = yield (0, utils_1.getTokenCookie)();
38
+ const response = yield (0, supertest_1.default)(app_1.default)
39
+ .post('/api/tickets')
40
+ .set('Cookie', [cookie])
41
+ .send({});
42
+ expect(response.status).not.toEqual(401);
43
+ }));
44
+ it('should throw error if new ticket has invalid title', () => __awaiter(void 0, void 0, void 0, function* () {
45
+ const cookie = yield (0, utils_1.getTokenCookie)();
46
+ yield (0, supertest_1.default)(app_1.default)
47
+ .post('/api/tickets')
48
+ .set('Cookie', [cookie])
49
+ .send({ title: '', price: 10 })
50
+ .expect(400);
51
+ }));
52
+ it('should throw error if new ticket has invalid price', () => __awaiter(void 0, void 0, void 0, function* () {
53
+ const cookie = yield (0, utils_1.getTokenCookie)();
54
+ yield (0, supertest_1.default)(app_1.default)
55
+ .post('/api/tickets')
56
+ .set('Cookie', [cookie])
57
+ .send({ title: 'Test Event', price: -10 })
58
+ .expect(400);
59
+ yield (0, supertest_1.default)(app_1.default)
60
+ .post('/api/tickets')
61
+ .set('Cookie', [cookie])
62
+ .send({ title: 'Test Event' })
63
+ .expect(400);
64
+ }));
65
+ it('should create a new ticket', () => __awaiter(void 0, void 0, void 0, function* () {
66
+ let tickets = yield ticket_1.default.find({});
67
+ const cookie = yield (0, utils_1.getTokenCookie)();
68
+ yield (0, supertest_1.default)(app_1.default)
69
+ .post('/api/tickets')
70
+ .set('Cookie', [cookie])
71
+ .send({
72
+ title: 'Test Event',
73
+ price: 20000
74
+ });
75
+ tickets = yield ticket_1.default.find({});
76
+ expect(tickets.length).toEqual(1);
77
+ expect(tickets[0].title).toEqual('Test Event');
78
+ expect(tickets[0].price).toEqual(20000);
79
+ }));
80
+ it('should publish a ticket:created event', () => __awaiter(void 0, void 0, void 0, function* () {
81
+ const cookie = yield (0, utils_1.getTokenCookie)();
82
+ yield (0, utils_1.createTicket)(app_1.default, cookie);
83
+ expect(nats_client_1.default.client.publish).toHaveBeenCalled();
84
+ }));
85
+ });
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const supertest_1 = __importDefault(require("supertest"));
16
+ const app_1 = __importDefault(require("../../app"));
17
+ const utils_1 = require("../../test/utils");
18
+ describe('[List Tickets] Route: /api/tickets', () => {
19
+ it('should return a list of tickets', () => __awaiter(void 0, void 0, void 0, function* () {
20
+ const cookie = yield (0, utils_1.getTokenCookie)();
21
+ yield (0, utils_1.createTicket)(app_1.default, cookie);
22
+ yield (0, utils_1.createTicket)(app_1.default, cookie, 'Test Event 2', 40000);
23
+ const list = yield (0, supertest_1.default)(app_1.default)
24
+ .get('/api/tickets')
25
+ .send()
26
+ .expect(200);
27
+ expect(list.body.tickets).toBeDefined();
28
+ expect(list.body.tickets.length).toEqual(2);
29
+ }));
30
+ });
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const supertest_1 = __importDefault(require("supertest"));
16
+ const mongoose_1 = __importDefault(require("mongoose"));
17
+ const app_1 = __importDefault(require("../../app"));
18
+ const utils_1 = require("../../test/utils");
19
+ describe('[Get Ticket] Route: /api/tickets/:id', () => {
20
+ it('should throw a BadRequestError if ticket ID is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
21
+ yield (0, supertest_1.default)(app_1.default)
22
+ .get('/api/tickets/notarealid')
23
+ .send()
24
+ .expect(400);
25
+ }));
26
+ it('should throw a NotFoundError if ticket not found', () => __awaiter(void 0, void 0, void 0, function* () {
27
+ const id = new mongoose_1.default.Types.ObjectId().toHexString();
28
+ yield (0, supertest_1.default)(app_1.default)
29
+ .get(`/api/tickets/${id}`)
30
+ .send()
31
+ .expect(404);
32
+ }));
33
+ it('should return the fetched ticket', () => __awaiter(void 0, void 0, void 0, function* () {
34
+ const cookie = yield (0, utils_1.getTokenCookie)();
35
+ const response = yield (0, utils_1.createTicket)(app_1.default, cookie);
36
+ const ticket = yield (0, supertest_1.default)(app_1.default)
37
+ .get(`/api/tickets/${response.body.ticket.id}`)
38
+ .send()
39
+ .expect(200);
40
+ expect(ticket.body.ticket.title).toEqual('Test Event');
41
+ expect(ticket.body.ticket.price).toEqual(20000);
42
+ }));
43
+ });
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const supertest_1 = __importDefault(require("supertest"));
16
+ const mongoose_1 = __importDefault(require("mongoose"));
17
+ const app_1 = __importDefault(require("../../app"));
18
+ const utils_1 = require("../../test/utils");
19
+ const nats_client_1 = __importDefault(require("../../nats-client"));
20
+ describe('[Update Ticket] Route: /api/tickets/:id', () => {
21
+ it('should throw a NotFoundError if the ticket does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
22
+ const id = new mongoose_1.default.Types.ObjectId().toHexString();
23
+ const cookie = yield (0, utils_1.getTokenCookie)();
24
+ yield (0, supertest_1.default)(app_1.default)
25
+ .put(`/api/tickets/${id}`)
26
+ .set('Cookie', [cookie])
27
+ .send({ title: 'Test Event', price: 23000 })
28
+ .expect(404);
29
+ }));
30
+ it('should throw an UnauthorizedError if not authenticated', () => __awaiter(void 0, void 0, void 0, function* () {
31
+ const cookie = yield (0, utils_1.getTokenCookie)();
32
+ const response = yield (0, supertest_1.default)(app_1.default)
33
+ .post(`/api/tickets`)
34
+ .set('Cookie', [cookie])
35
+ .send({ title: 'Test Event', price: 20000 })
36
+ .expect(201);
37
+ yield (0, supertest_1.default)(app_1.default)
38
+ .put(`/api/tickets/${response.body.ticket.id}`)
39
+ .send({ title: 'Test Event', price: 23000 })
40
+ .expect(401);
41
+ }));
42
+ it('should throw an UnauthorizedError if user does not own the ticket', () => __awaiter(void 0, void 0, void 0, function* () {
43
+ const cookie = yield (0, utils_1.getTokenCookie)();
44
+ const response = yield (0, supertest_1.default)(app_1.default)
45
+ .post(`/api/tickets`)
46
+ .set('Cookie', [cookie])
47
+ .send({ title: 'Test Event', price: 20000 })
48
+ .expect(201);
49
+ const newCookie = yield (0, utils_1.getTokenCookie)();
50
+ yield (0, supertest_1.default)(app_1.default)
51
+ .put(`/api/tickets/${response.body.ticket.id}`)
52
+ .set('Cookie', [newCookie])
53
+ .send({ title: 'Test Event', price: 23000 })
54
+ .expect(401);
55
+ }));
56
+ it('should throw a BadRequestError if an invalid ticket is provided', () => __awaiter(void 0, void 0, void 0, function* () {
57
+ const cookie = yield (0, utils_1.getTokenCookie)();
58
+ yield (0, supertest_1.default)(app_1.default)
59
+ .put(`/api/tickets/notarealid`)
60
+ .set('Cookie', [cookie])
61
+ .send({ title: 'Test Event', price: 20000 })
62
+ .expect(400);
63
+ }));
64
+ it('should throw an error on invalid ticket data', () => __awaiter(void 0, void 0, void 0, function* () {
65
+ const cookie = yield (0, utils_1.getTokenCookie)();
66
+ const response = yield (0, utils_1.createTicket)(app_1.default, cookie);
67
+ yield (0, supertest_1.default)(app_1.default)
68
+ .put(`/api/tickets/${response.body.ticket.id}`)
69
+ .set('Cookie', [cookie])
70
+ .send({ title: '', price: 23000 })
71
+ .expect(400);
72
+ yield (0, supertest_1.default)(app_1.default)
73
+ .put(`/api/tickets/${response.body.ticket.id}`)
74
+ .set('Cookie', [cookie])
75
+ .send({ title: 'Test Event 2', price: -33 })
76
+ .expect(400);
77
+ }));
78
+ it('should update a ticket', () => __awaiter(void 0, void 0, void 0, function* () {
79
+ const cookie = yield (0, utils_1.getTokenCookie)();
80
+ const response = yield (0, utils_1.createTicket)(app_1.default, cookie);
81
+ const updated = yield (0, supertest_1.default)(app_1.default)
82
+ .put(`/api/tickets/${response.body.ticket.id}`)
83
+ .set('Cookie', [cookie])
84
+ .send({ title: 'New Event', price: 23000 })
85
+ .expect(200);
86
+ const ticket = yield (0, supertest_1.default)(app_1.default).get(`/api/tickets/${response.body.ticket.id}`).send();
87
+ expect(ticket.body.ticket.title).toEqual('New Event');
88
+ expect(ticket.body.ticket.price).toEqual(23000);
89
+ }));
90
+ it('should publish a ticket:updated event', () => __awaiter(void 0, void 0, void 0, function* () {
91
+ const cookie = yield (0, utils_1.getTokenCookie)();
92
+ yield (0, utils_1.createTicket)(app_1.default, cookie);
93
+ expect(nats_client_1.default.client.publish).toHaveBeenCalled();
94
+ }));
95
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const express_1 = __importDefault(require("express"));
16
+ const express_validator_1 = require("express-validator");
17
+ const common_1 = require("@next-k8s/common");
18
+ const ticket_1 = __importDefault(require("../models/ticket"));
19
+ const created_1 = require("../events/publishers/tickets/created");
20
+ const nats_client_1 = __importDefault(require("../nats-client"));
21
+ const router = express_1.default.Router();
22
+ const validateInput = [
23
+ (0, express_validator_1.body)('title').not().isEmpty().withMessage('Title is required'),
24
+ (0, express_validator_1.body)('price').isInt({ gt: -1, lt: Number.MAX_SAFE_INTEGER }).withMessage('Price must be an integer of cents or units')
25
+ ];
26
+ router.post('/api/tickets', common_1.requireAuth, validateInput, common_1.validateRequest, (req, res) => __awaiter(void 0, void 0, void 0, function* () {
27
+ const { title, price } = req.body;
28
+ const ticket = new ticket_1.default({ title, price, owner: req.currentUser.id });
29
+ yield ticket.save();
30
+ new created_1.TicketCreatedPublisher(nats_client_1.default.client).publish({ id: ticket.id, title: ticket.title, price: ticket.price, owner: ticket.owner });
31
+ res.status(201).send({ ticket });
32
+ }));
33
+ exports.default = router;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const express_1 = __importDefault(require("express"));
16
+ const ticket_1 = __importDefault(require("../models/ticket"));
17
+ const router = express_1.default.Router();
18
+ router.get('/api/tickets', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
19
+ const tickets = yield ticket_1.default.find({});
20
+ res.send({ tickets });
21
+ }));
22
+ exports.default = router;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const common_1 = require("@next-k8s/common");
16
+ const express_1 = __importDefault(require("express"));
17
+ const mongoose_1 = require("mongoose");
18
+ const ticket_1 = __importDefault(require("../models/ticket"));
19
+ const router = express_1.default.Router();
20
+ router.get('/api/tickets/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
21
+ if (!(0, mongoose_1.isValidObjectId)(req.params.id))
22
+ throw new common_1.BadRequestError('Invalid Ticket ID');
23
+ const ticket = yield ticket_1.default.findById(req.params.id);
24
+ if (!ticket)
25
+ throw new common_1.NotFoundError();
26
+ res.json({ ticket });
27
+ }));
28
+ exports.default = router;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const get_1 = __importDefault(require("./get"));
7
+ const find_1 = __importDefault(require("./find"));
8
+ const create_1 = __importDefault(require("./create"));
9
+ const update_1 = __importDefault(require("./update"));
10
+ exports.default = [find_1.default, get_1.default, create_1.default, update_1.default];