whitelabel-db 1.3.3 → 1.3.4
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/dist/libs/database.js
CHANGED
|
@@ -42,6 +42,7 @@ const LoyaltyProgramTier_1 = require("../models/LoyaltyProgramTier");
|
|
|
42
42
|
const BookingLoyaltyRecord_1 = require("../models/BookingLoyaltyRecord");
|
|
43
43
|
const migration_1 = require("./migration");
|
|
44
44
|
const connect = (connectionDetails) => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
var _a;
|
|
45
46
|
const connection = new sequelize_typescript_1.Sequelize({
|
|
46
47
|
dialect: 'postgres',
|
|
47
48
|
host: connectionDetails.host,
|
|
@@ -93,8 +94,31 @@ const connect = (connectionDetails) => __awaiter(void 0, void 0, void 0, functio
|
|
|
93
94
|
}
|
|
94
95
|
// Only create tables that don't exist, don't alter existing schema
|
|
95
96
|
// This prevents conflicts with migrations
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
try {
|
|
98
|
+
yield connection.sync({ force: false, alter: false });
|
|
99
|
+
console.log('Database sync completed successfully.');
|
|
100
|
+
}
|
|
101
|
+
catch (syncError) {
|
|
102
|
+
// Ignore errors about creating indexes on primary key columns
|
|
103
|
+
// Primary keys already have indexes, so Sequelize trying to create
|
|
104
|
+
// a separate index on them will fail
|
|
105
|
+
const errorMessage = (syncError === null || syncError === void 0 ? void 0 : syncError.message) || '';
|
|
106
|
+
const errorSql = (syncError === null || syncError === void 0 ? void 0 : syncError.sql) || '';
|
|
107
|
+
const originalCode = ((_a = syncError === null || syncError === void 0 ? void 0 : syncError.original) === null || _a === void 0 ? void 0 : _a.code) || '';
|
|
108
|
+
if ((errorMessage.includes('already exists') &&
|
|
109
|
+
errorSql.includes('CREATE INDEX')) ||
|
|
110
|
+
originalCode === '42P07' || // duplicate_table
|
|
111
|
+
originalCode === '42710' || // duplicate_object (index already exists)
|
|
112
|
+
(errorSql.includes('CREATE INDEX') &&
|
|
113
|
+
errorSql.includes('_id"') &&
|
|
114
|
+
errorSql.includes('"id")'))) {
|
|
115
|
+
console.log('Sync completed with expected warnings (indexes on primary keys may already exist).');
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.error('Error during database sync:', syncError);
|
|
119
|
+
throw syncError;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
98
122
|
return connection;
|
|
99
123
|
}
|
|
100
124
|
catch (err) {
|
|
@@ -0,0 +1,146 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.down = exports.up = void 0;
|
|
13
|
+
// Purpose: Add phoneNo, country, language, currency columns to guests table
|
|
14
|
+
const sequelize_1 = require("sequelize");
|
|
15
|
+
const up = (queryInterface) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
try {
|
|
17
|
+
// Check which columns already exist
|
|
18
|
+
const tableDescription = yield queryInterface.describeTable('guests');
|
|
19
|
+
const existingColumns = Object.keys(tableDescription);
|
|
20
|
+
// Add phoneNo column
|
|
21
|
+
if (!existingColumns.includes('phoneNo')) {
|
|
22
|
+
yield queryInterface.addColumn('guests', 'phoneNo', {
|
|
23
|
+
type: sequelize_1.DataTypes.STRING,
|
|
24
|
+
allowNull: true,
|
|
25
|
+
});
|
|
26
|
+
console.log('phoneNo column added successfully.');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.log('phoneNo column already exists, skipping.');
|
|
30
|
+
}
|
|
31
|
+
// Add country column
|
|
32
|
+
if (!existingColumns.includes('country')) {
|
|
33
|
+
yield queryInterface.addColumn('guests', 'country', {
|
|
34
|
+
type: sequelize_1.DataTypes.STRING,
|
|
35
|
+
allowNull: true,
|
|
36
|
+
});
|
|
37
|
+
console.log('country column added successfully.');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log('country column already exists, skipping.');
|
|
41
|
+
}
|
|
42
|
+
// Add language column
|
|
43
|
+
if (!existingColumns.includes('language')) {
|
|
44
|
+
yield queryInterface.addColumn('guests', 'language', {
|
|
45
|
+
type: sequelize_1.DataTypes.STRING,
|
|
46
|
+
allowNull: true,
|
|
47
|
+
});
|
|
48
|
+
console.log('language column added successfully.');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log('language column already exists, skipping.');
|
|
52
|
+
}
|
|
53
|
+
// Add currency column
|
|
54
|
+
if (!existingColumns.includes('currency')) {
|
|
55
|
+
yield queryInterface.addColumn('guests', 'currency', {
|
|
56
|
+
type: sequelize_1.DataTypes.STRING,
|
|
57
|
+
allowNull: true,
|
|
58
|
+
});
|
|
59
|
+
console.log('currency column added successfully.');
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log('currency column already exists, skipping.');
|
|
63
|
+
}
|
|
64
|
+
// Add index for phoneNo for faster lookups
|
|
65
|
+
try {
|
|
66
|
+
yield queryInterface.addIndex('guests', ['phoneNo'], {
|
|
67
|
+
name: 'guests_phoneNo_idx',
|
|
68
|
+
});
|
|
69
|
+
console.log('phoneNo index added successfully.');
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error.message.includes('already exists')) {
|
|
73
|
+
console.log('phoneNo index already exists, skipping.');
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Add unique index for (phoneNo, projectId) only when phoneNo is not null
|
|
80
|
+
try {
|
|
81
|
+
yield queryInterface.addIndex('guests', ['phoneNo', 'projectId'], {
|
|
82
|
+
unique: true,
|
|
83
|
+
where: {
|
|
84
|
+
phoneNo: {
|
|
85
|
+
[sequelize_1.Op.ne]: null,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
name: 'guests_phoneNo_projectId_unique',
|
|
89
|
+
});
|
|
90
|
+
console.log('phoneNo-projectId unique index added successfully.');
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error.message.includes('already exists')) {
|
|
94
|
+
console.log('phoneNo-projectId unique index already exists, skipping.');
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
console.log('phoneNo, country, language, currency columns added to guests table successfully.');
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('Error while adding phoneNo, country, language, currency columns:', error.message);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
exports.up = up;
|
|
108
|
+
const down = (queryInterface) => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
+
try {
|
|
110
|
+
// Remove the unique index
|
|
111
|
+
try {
|
|
112
|
+
yield queryInterface.removeIndex('guests', 'guests_phoneNo_projectId_unique');
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error.message.includes('does not exist')) {
|
|
116
|
+
console.log('phoneNo-projectId unique index does not exist, skipping.');
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Remove the phoneNo index
|
|
123
|
+
try {
|
|
124
|
+
yield queryInterface.removeIndex('guests', 'guests_phoneNo_idx');
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
if (error.message.includes('does not exist')) {
|
|
128
|
+
console.log('phoneNo index does not exist, skipping.');
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Remove the new columns
|
|
135
|
+
yield queryInterface.removeColumn('guests', 'phoneNo');
|
|
136
|
+
yield queryInterface.removeColumn('guests', 'country');
|
|
137
|
+
yield queryInterface.removeColumn('guests', 'language');
|
|
138
|
+
yield queryInterface.removeColumn('guests', 'currency');
|
|
139
|
+
console.log('phoneNo, country, language, currency columns removed from guests table successfully.');
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error('Error while removing phoneNo, country, language, currency columns:', error.message);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
exports.down = down;
|
package/dist/models/Guest.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export declare class Guest extends Model<Partial<Guest>> {
|
|
|
6
6
|
firstName: string;
|
|
7
7
|
lastName: string;
|
|
8
8
|
email: string;
|
|
9
|
+
phoneNo: string;
|
|
10
|
+
country: string;
|
|
11
|
+
language: string;
|
|
12
|
+
currency: string;
|
|
9
13
|
password: string;
|
|
10
14
|
projectId?: string;
|
|
11
15
|
liteApiGuestId: number;
|
|
@@ -24,14 +28,20 @@ export declare class Guest extends Model<Partial<Guest>> {
|
|
|
24
28
|
project?: Project;
|
|
25
29
|
bookings?: Booking[];
|
|
26
30
|
static checkEmail(email: string, projectId: string): Promise<void>;
|
|
31
|
+
static checkPhoneNo(phoneNo: string, projectId: string): Promise<void>;
|
|
32
|
+
static checkEmailOrPhone(email?: string, phoneNo?: string, projectId?: string): Promise<void>;
|
|
27
33
|
generateSession(secret: string): string;
|
|
28
34
|
static createAnonymous(projectId: string, sessionToken: string): Promise<Guest>;
|
|
29
35
|
static findBySessionToken(sessionToken: string, projectId: string): Promise<Guest | null>;
|
|
30
36
|
convertToRegistered(userData: {
|
|
31
|
-
firstName
|
|
32
|
-
lastName
|
|
33
|
-
email
|
|
37
|
+
firstName?: string;
|
|
38
|
+
lastName?: string;
|
|
39
|
+
email?: string;
|
|
40
|
+
phoneNo?: string;
|
|
34
41
|
password?: string;
|
|
42
|
+
country?: string;
|
|
43
|
+
language?: string;
|
|
44
|
+
currency?: string;
|
|
35
45
|
}): Promise<this>;
|
|
36
46
|
updateLastSeen(): Promise<this>;
|
|
37
47
|
}
|
package/dist/models/Guest.js
CHANGED
|
@@ -38,6 +38,28 @@ let Guest = Guest_1 = class Guest extends sequelize_typescript_1.Model {
|
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
+
static checkPhoneNo(phoneNo, projectId) {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
if (!phoneNo)
|
|
44
|
+
return; // Handle null phone numbers
|
|
45
|
+
if (yield Guest_1.findOne({ where: { phoneNo, projectId } })) {
|
|
46
|
+
throw new Error('This phone number is already registered to another account.');
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
static checkEmailOrPhone(email, phoneNo, projectId) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
if (!email && !phoneNo) {
|
|
53
|
+
throw new Error('Either email or phone number must be provided.');
|
|
54
|
+
}
|
|
55
|
+
if (email) {
|
|
56
|
+
yield Guest_1.checkEmail(email, projectId);
|
|
57
|
+
}
|
|
58
|
+
if (phoneNo) {
|
|
59
|
+
yield Guest_1.checkPhoneNo(phoneNo, projectId);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
41
63
|
generateSession(secret) {
|
|
42
64
|
return jsonwebtoken_1.default.sign({ id: this.id, projectId: this.projectId }, secret, {
|
|
43
65
|
algorithm: 'HS256',
|
|
@@ -66,14 +88,32 @@ let Guest = Guest_1 = class Guest extends sequelize_typescript_1.Model {
|
|
|
66
88
|
// New method to convert anonymous to registered
|
|
67
89
|
convertToRegistered(userData) {
|
|
68
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
91
|
+
if (userData.firstName) {
|
|
92
|
+
this.firstName = userData.firstName;
|
|
93
|
+
}
|
|
94
|
+
if (userData.lastName) {
|
|
95
|
+
this.lastName = userData.lastName;
|
|
96
|
+
}
|
|
97
|
+
if (userData.email) {
|
|
98
|
+
this.email = userData.email.toLowerCase();
|
|
99
|
+
}
|
|
100
|
+
if (userData.phoneNo) {
|
|
101
|
+
this.phoneNo = userData.phoneNo;
|
|
102
|
+
}
|
|
72
103
|
if (userData.password) {
|
|
73
104
|
this.password = userData.password;
|
|
74
105
|
}
|
|
106
|
+
if (userData.country) {
|
|
107
|
+
this.country = userData.country;
|
|
108
|
+
}
|
|
109
|
+
if (userData.language) {
|
|
110
|
+
this.language = userData.language;
|
|
111
|
+
}
|
|
112
|
+
if (userData.currency) {
|
|
113
|
+
this.currency = userData.currency;
|
|
114
|
+
}
|
|
75
115
|
this.isAnonymous = false;
|
|
76
|
-
this.isVerified = false; // Will be verified through email verification process
|
|
116
|
+
this.isVerified = false; // Will be verified through email/phone verification process
|
|
77
117
|
this.lastSeen = new Date();
|
|
78
118
|
return yield this.save();
|
|
79
119
|
});
|
|
@@ -118,6 +158,35 @@ __decorate([
|
|
|
118
158
|
}),
|
|
119
159
|
__metadata("design:type", String)
|
|
120
160
|
], Guest.prototype, "email", void 0);
|
|
161
|
+
__decorate([
|
|
162
|
+
sequelize_typescript_1.Index,
|
|
163
|
+
(0, sequelize_typescript_1.Column)({
|
|
164
|
+
type: sequelize_typescript_1.DataType.STRING,
|
|
165
|
+
allowNull: true,
|
|
166
|
+
}),
|
|
167
|
+
__metadata("design:type", String)
|
|
168
|
+
], Guest.prototype, "phoneNo", void 0);
|
|
169
|
+
__decorate([
|
|
170
|
+
(0, sequelize_typescript_1.Column)({
|
|
171
|
+
type: sequelize_typescript_1.DataType.STRING,
|
|
172
|
+
allowNull: true,
|
|
173
|
+
}),
|
|
174
|
+
__metadata("design:type", String)
|
|
175
|
+
], Guest.prototype, "country", void 0);
|
|
176
|
+
__decorate([
|
|
177
|
+
(0, sequelize_typescript_1.Column)({
|
|
178
|
+
type: sequelize_typescript_1.DataType.STRING,
|
|
179
|
+
allowNull: true,
|
|
180
|
+
}),
|
|
181
|
+
__metadata("design:type", String)
|
|
182
|
+
], Guest.prototype, "language", void 0);
|
|
183
|
+
__decorate([
|
|
184
|
+
(0, sequelize_typescript_1.Column)({
|
|
185
|
+
type: sequelize_typescript_1.DataType.STRING,
|
|
186
|
+
allowNull: true,
|
|
187
|
+
}),
|
|
188
|
+
__metadata("design:type", String)
|
|
189
|
+
], Guest.prototype, "currency", void 0);
|
|
121
190
|
__decorate([
|
|
122
191
|
(0, sequelize_typescript_1.Column)({
|
|
123
192
|
type: sequelize_typescript_1.DataType.STRING,
|
|
@@ -252,6 +321,15 @@ exports.Guest = Guest = Guest_1 = __decorate([
|
|
|
252
321
|
},
|
|
253
322
|
},
|
|
254
323
|
},
|
|
324
|
+
{
|
|
325
|
+
unique: true,
|
|
326
|
+
fields: ['phoneNo', 'projectId'],
|
|
327
|
+
where: {
|
|
328
|
+
phoneNo: {
|
|
329
|
+
[sequelize_1.Op.ne]: null,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
255
333
|
],
|
|
256
334
|
})
|
|
257
335
|
], Guest);
|