@next-k8s/tickets 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- package/.dockerignore +1 -0
- package/CHANGELOG.md +72 -0
- package/Dockerfile +7 -0
- package/build/__mocks__/nats-client.js +12 -0
- package/build/app.js +31 -0
- package/build/events/publishers/tickets/created.js +12 -0
- package/build/events/publishers/tickets/updated.js +12 -0
- package/build/index.js +45 -0
- package/build/models/ticket.js +37 -0
- package/build/nats-client.js +42 -0
- package/build/routes/__test__/create.test.js +85 -0
- package/build/routes/__test__/find.test.js +30 -0
- package/build/routes/__test__/get.test.js +43 -0
- package/build/routes/__test__/update.test.js +95 -0
- package/build/routes/create.js +33 -0
- package/build/routes/find.js +22 -0
- package/build/routes/get.js +28 -0
- package/build/routes/index.js +10 -0
- package/build/routes/update.js +41 -0
- package/build/test/setup.js +34 -0
- package/build/test/utils.js +33 -0
- package/package.json +53 -0
- package/pnpm-lock.yaml +3641 -0
- package/src/__mocks__/nats-client.ts +10 -0
- package/src/app.ts +21 -0
- package/src/events/publishers/tickets/created.ts +7 -0
- package/src/events/publishers/tickets/updated.ts +7 -0
- package/src/index.ts +31 -0
- package/src/models/ticket.ts +42 -0
- package/src/nats-client.ts +30 -0
- package/src/routes/__test__/create.test.ts +83 -0
- package/src/routes/__test__/find.test.ts +18 -0
- package/src/routes/__test__/get.test.ts +34 -0
- package/src/routes/__test__/update.test.ts +101 -0
- package/src/routes/create.ts +24 -0
- package/src/routes/find.ts +11 -0
- package/src/routes/get.ts +16 -0
- package/src/routes/index.ts +8 -0
- package/src/routes/update.ts +29 -0
- package/src/test/setup.ts +24 -0
- package/src/test/utils.ts +18 -0
- 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,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];
|