/
item.ts
225 lines (191 loc) · 6.76 KB
/
item.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import * as alt from 'alt-server';
import Database from '@stuyk/ezmongodb';
import { Item } from '../../shared/interfaces/item';
import { deepCloneObject } from '../../shared/utility/deepCopy';
import { Collections } from '../interface/iDatabaseCollections';
const databaseItemNames: Array<{ name: string; dbName: string }> = [];
let isDoneLoading = false;
export class ItemFactory {
/**
* Initialize the Item Factory Database
* @static
* @memberof ItemFactory
*/
static async init() {
await Database.createCollection(Collections.Items);
const items = await Database.fetchAllData<Item>(Collections.Items);
for (let i = 0; i < items.length; i++) {
databaseItemNames.push({ name: items[i].name, dbName: items[i].dbName });
}
isDoneLoading = true;
}
/**
* Wait until the `isDoneLoading` variable is set to `true` before continuing.
*/
static async isDoneLoading(): Promise<void> {
return new Promise((resolve: Function) => {
const interval = alt.setInterval(() => {
if (!isDoneLoading) {
return;
}
alt.clearInterval(interval);
resolve();
}, 100);
});
}
/**
* Creates and adds an item to the database if it does not exist.
* @static
* @param {Item} item
* @memberof ItemFactory
*/
static async add(item: Item): Promise<Item> {
await ItemFactory.isDoneLoading();
delete item.quantity;
// Check that the item has 'dbName'
if (!item.dbName) {
console.error(`Item during add is missing 'dbName' for item ${JSON.stringify(item)}`);
console.error(`Add a 'dbName' to the item to successfully append it to the database.`);
return null;
}
// Prevents duplicate items being inserted
if (databaseItemNames.findIndex((x) => x.dbName === item.dbName) >= 0) {
return null;
}
if (item._id) {
return null;
}
// Creates and adds an item into the item database
const itemDocument = await Database.insertData(item, Collections.Items, true);
if (!itemDocument) {
return null;
}
databaseItemNames.push({ name: itemDocument.name, dbName: itemDocument.dbName });
alt.log(`Added Item to Registry | ${itemDocument.name} | ${itemDocument.dbName}`);
return itemDocument;
}
/**
* Simply get an item from the Database.
* @static
* @param {string} dbItemName
* @return { Promise<Item> }
* @memberof ItemFactory
*/
static async get(dbItemName: string): Promise<Item | null> {
await ItemFactory.isDoneLoading();
if (databaseItemNames.findIndex((x) => x.dbName === dbItemName) <= -1) {
return null;
}
const item = await Database.fetchData<Item>('dbName', dbItemName, Collections.Items);
if (!item) {
return null;
}
const newItem = deepCloneObject<Item>(item);
newItem.quantity = 1;
return newItem;
}
/**
* Updates a Database Item
* Item requires full-overwrite and returns true if updated.
* May return false if item does not exist.
* @static
* @param {string} dbItemName
* @return {*} {Promise<boolean>}
* @memberof ItemFactory
*/
static async update(dbItemName: string, partialItemReplacement: Partial<Item>): Promise<boolean> {
await ItemFactory.isDoneLoading();
if (databaseItemNames.findIndex((x) => x.dbName === dbItemName) <= -1) {
alt.logWarning(`Item Registry - Could not find item ${dbItemName} to update.`);
return false;
}
const item = await Database.fetchData<Item>('dbName', dbItemName, Collections.Items);
if (!item) {
alt.logWarning(`Item Registry - Could not find item ${dbItemName} to update.`);
return false;
}
return await Database.updatePartialData(item._id.toString(), partialItemReplacement, Collections.Items);
}
/**
* Get all items stored for local lookups.
* Fastest way to find an item that exists in the database.
*
* Make sure to you `ItemFactory.get` with the `dbName` to get the full item.
* @static
* @return {*} {Array<{ name: string; dbName: string }>}
* @memberof ItemFactory
*/
static getAllItems(): Array<{ name: string; dbName: string }> {
return databaseItemNames;
}
/**
* Get all items from the database.
* Considered as an expensive database call.
* Use sparingly.
* @static
* @return {Promise<Array<Item>>}
* @memberof ItemFactory
*/
static async getAllItemsFromDatabase(): Promise<Array<Item>> {
return await Database.fetchAllData<Item>(Collections.Items);
}
/**
* Get item by item name.
* It's like a fuzzy search for an item.
* @static
* @param {string} name
* @return {*}
* @memberof ItemFactory
*/
static async getByName(name: string): Promise<Item | null> {
await ItemFactory.isDoneLoading();
const itemName = name.replace(/\s/g, '').toLowerCase();
// First Pass Through - Exact Name Check
let index = databaseItemNames.findIndex((itemRef) => {
const refItemName = itemRef.name.replace(/\s/g, '').toLowerCase();
if (refItemName === itemName) {
return true;
}
return false;
});
// Second Pass Through - Includes Search
if (index <= -1) {
index = databaseItemNames.findIndex((itemRef) => {
const refItemName = itemRef.name.replace(/\s/g, '').toLowerCase();
if (refItemName.includes(itemName)) {
return true;
}
return false;
});
}
if (index <= -1) {
return null;
}
const newItem = await ItemFactory.get(databaseItemNames[index].dbName);
newItem.quantity = 1;
return newItem;
}
/**
* Check if an item with a specified dbName exists.
* @static
* @param {string} dbItemName
* @return {*} {boolean}
* @memberof ItemFactory
*/
static async doesExist(dbItemName: string): Promise<boolean> {
await ItemFactory.isDoneLoading();
const index = databaseItemNames.findIndex((x) => x.dbName === dbItemName);
return index !== -1;
}
/**
* Creates an exact clone of an item but gives it a new hash.
* @static
* @param {Item} item
* @return {Item}
* @memberof ItemFactory
*/
static clone(item: Item): Item {
return deepCloneObject(item);
}
}
ItemFactory.init();