@next-k8s/tickets 1.0.9
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.
- 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];
|