@thzero/library_server 0.18.5 → 0.18.7
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/README.md +93 -93
- package/boot/index.js +466 -466
- package/boot/plugins/admin/index.js +6 -6
- package/boot/plugins/admin/news.js +33 -33
- package/boot/plugins/admin/users.js +33 -33
- package/boot/plugins/api.js +64 -64
- package/boot/plugins/apiFront.js +31 -31
- package/boot/plugins/index.js +70 -70
- package/boot/plugins/news.js +44 -44
- package/boot/plugins/users.js +46 -46
- package/boot/plugins/usersExtended.js +32 -32
- package/constants.js +45 -45
- package/data/baseNews.js +42 -42
- package/data/baseSettingsUser.js +9 -9
- package/data/baseUser.js +28 -28
- package/data/index.js +24 -24
- package/data/named.js +20 -20
- package/errors/tokenExpired.js +7 -7
- package/license.md +8 -8
- package/openSource.js +66 -66
- package/package.json +38 -38
- package/repository/index.js +182 -182
- package/repository/usageMetrics/devnull.js +16 -16
- package/routes/index.js +76 -76
- package/service/admin/baseNews.js +45 -45
- package/service/admin/index.js +130 -130
- package/service/admin/news.js +6 -6
- package/service/admin/users.js +107 -107
- package/service/baseSecurity.js +183 -183
- package/service/baseUser.js +122 -122
- package/service/communication.js +6 -6
- package/service/config.js +37 -37
- package/service/crypto.js +16 -16
- package/service/discovery/index.js +6 -6
- package/service/discovery/resources/index.js +101 -101
- package/service/external.js +19 -19
- package/service/externalRest.js +19 -19
- package/service/index.js +20 -20
- package/service/monitoring.js +12 -12
- package/service/news/base.js +59 -59
- package/service/news/index.js +6 -6
- package/service/news/validation/index.js +6 -6
- package/service/plans.js +31 -31
- package/service/restCommunication.js +21 -21
- package/service/usageMetrics.js +84 -78
- package/service/utility.js +188 -188
- package/service/version.js +37 -37
- package/utility/injector.js +59 -59
- package/utility/internalIp/index.js +48 -48
- package/utility/list/doubleLinked.js +88 -88
- package/utility/list/priorityQueue.js +109 -109
- package/utility/list/queue.js +72 -72
- package/utility/os.js +20 -20
package/service/version.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
import Service from './index.js';
|
|
5
|
-
|
|
6
|
-
class VersionService extends Service {
|
|
7
|
-
async version(correlationId) {
|
|
8
|
-
try {
|
|
9
|
-
const filePath = path.join(process.cwd(), 'package.json');
|
|
10
|
-
const file = fs.readFileSync(filePath, 'utf8');
|
|
11
|
-
if (String.isNullOrEmpty(file))
|
|
12
|
-
throw Error('Invalid package.json file for versioning; expected in the <app root> folder.');
|
|
13
|
-
|
|
14
|
-
const packageObj = JSON.parse(file);
|
|
15
|
-
if (!packageObj)
|
|
16
|
-
throw Error('Invalid package.json file for versioning.');
|
|
17
|
-
|
|
18
|
-
return this._generate(correlationId, packageObj.version_major, packageObj.version_minor, packageObj.version_patch, packageObj.version_date);
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
return this._error('VersionService', 'version', null, err, null, null, correlationId);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
_generate(correlationId, version_major, version_minor, version_patch, version_date) {
|
|
26
|
-
const response = this._success(correlationId);
|
|
27
|
-
response.results = {
|
|
28
|
-
major: version_major,
|
|
29
|
-
minor: version_minor,
|
|
30
|
-
patch: version_patch,
|
|
31
|
-
date: version_date
|
|
32
|
-
};
|
|
33
|
-
return response;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default VersionService;
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import Service from './index.js';
|
|
5
|
+
|
|
6
|
+
class VersionService extends Service {
|
|
7
|
+
async version(correlationId) {
|
|
8
|
+
try {
|
|
9
|
+
const filePath = path.join(process.cwd(), 'package.json');
|
|
10
|
+
const file = fs.readFileSync(filePath, 'utf8');
|
|
11
|
+
if (String.isNullOrEmpty(file))
|
|
12
|
+
throw Error('Invalid package.json file for versioning; expected in the <app root> folder.');
|
|
13
|
+
|
|
14
|
+
const packageObj = JSON.parse(file);
|
|
15
|
+
if (!packageObj)
|
|
16
|
+
throw Error('Invalid package.json file for versioning.');
|
|
17
|
+
|
|
18
|
+
return this._generate(correlationId, packageObj.version_major, packageObj.version_minor, packageObj.version_patch, packageObj.version_date);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return this._error('VersionService', 'version', null, err, null, null, correlationId);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_generate(correlationId, version_major, version_minor, version_patch, version_date) {
|
|
26
|
+
const response = this._success(correlationId);
|
|
27
|
+
response.results = {
|
|
28
|
+
major: version_major,
|
|
29
|
+
minor: version_minor,
|
|
30
|
+
patch: version_patch,
|
|
31
|
+
date: version_date
|
|
32
|
+
};
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default VersionService;
|
package/utility/injector.js
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
class Injector {
|
|
2
|
-
constructor() {
|
|
3
|
-
this._di = {};
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
addService(key, dependency) {
|
|
7
|
-
if (String.isNullOrEmpty(key))
|
|
8
|
-
throw Error(`Invalid injector key '${key}'.`);
|
|
9
|
-
if (!dependency)
|
|
10
|
-
throw Error('Invalid injector dependency.');
|
|
11
|
-
|
|
12
|
-
if (this._di[key])
|
|
13
|
-
return;
|
|
14
|
-
|
|
15
|
-
this._di[key] = { dependency: dependency };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
addSingleton(key, dependency) {
|
|
19
|
-
if (String.isNullOrEmpty(key))
|
|
20
|
-
throw Error(`Invalid injector key '${key}'.`);
|
|
21
|
-
if (!dependency)
|
|
22
|
-
throw Error('Invalid injector dependency.');
|
|
23
|
-
|
|
24
|
-
if (this._di[key])
|
|
25
|
-
return;
|
|
26
|
-
|
|
27
|
-
this._di[key] = { key: key, singleton: true, dependency: dependency };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
getInjector() {
|
|
31
|
-
return this._di;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
getService(key, args) {
|
|
35
|
-
if (String.isNullOrEmpty(key))
|
|
36
|
-
throw Error(`Invalid injector key '${key}'.`);
|
|
37
|
-
|
|
38
|
-
const result = this._di[key];
|
|
39
|
-
if (!result)
|
|
40
|
-
return null;
|
|
41
|
-
|
|
42
|
-
if (result.singleton)
|
|
43
|
-
return result.dependency;
|
|
44
|
-
|
|
45
|
-
return new result.dependency.prototype.constructor(args);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
getServices() {
|
|
49
|
-
return Object.values(this._di);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getSingletons() {
|
|
53
|
-
return Object.values(this._di).filter(l => l.singleton).map(l => l.dependency);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const singletonInstance = new Injector();
|
|
58
|
-
Object.freeze(singletonInstance);
|
|
59
|
-
export default singletonInstance;
|
|
1
|
+
class Injector {
|
|
2
|
+
constructor() {
|
|
3
|
+
this._di = {};
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
addService(key, dependency) {
|
|
7
|
+
if (String.isNullOrEmpty(key))
|
|
8
|
+
throw Error(`Invalid injector key '${key}'.`);
|
|
9
|
+
if (!dependency)
|
|
10
|
+
throw Error('Invalid injector dependency.');
|
|
11
|
+
|
|
12
|
+
if (this._di[key])
|
|
13
|
+
return;
|
|
14
|
+
|
|
15
|
+
this._di[key] = { dependency: dependency };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addSingleton(key, dependency) {
|
|
19
|
+
if (String.isNullOrEmpty(key))
|
|
20
|
+
throw Error(`Invalid injector key '${key}'.`);
|
|
21
|
+
if (!dependency)
|
|
22
|
+
throw Error('Invalid injector dependency.');
|
|
23
|
+
|
|
24
|
+
if (this._di[key])
|
|
25
|
+
return;
|
|
26
|
+
|
|
27
|
+
this._di[key] = { key: key, singleton: true, dependency: dependency };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getInjector() {
|
|
31
|
+
return this._di;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getService(key, args) {
|
|
35
|
+
if (String.isNullOrEmpty(key))
|
|
36
|
+
throw Error(`Invalid injector key '${key}'.`);
|
|
37
|
+
|
|
38
|
+
const result = this._di[key];
|
|
39
|
+
if (!result)
|
|
40
|
+
return null;
|
|
41
|
+
|
|
42
|
+
if (result.singleton)
|
|
43
|
+
return result.dependency;
|
|
44
|
+
|
|
45
|
+
return new result.dependency.prototype.constructor(args);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getServices() {
|
|
49
|
+
return Object.values(this._di);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getSingletons() {
|
|
53
|
+
return Object.values(this._di).filter(l => l.singleton).map(l => l.dependency);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const singletonInstance = new Injector();
|
|
58
|
+
Object.freeze(singletonInstance);
|
|
59
|
+
export default singletonInstance;
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import {networkInterfaces} from 'os';
|
|
2
|
-
import defaultGateway from 'default-gateway';
|
|
3
|
-
import ip from 'ipaddr.js';
|
|
4
|
-
|
|
5
|
-
function findIp(gateway) {
|
|
6
|
-
const gatewayIp = ip.parse(gateway);
|
|
7
|
-
|
|
8
|
-
// Look for the matching interface in all local interfaces.
|
|
9
|
-
for (const addresses of Object.values(networkInterfaces())) {
|
|
10
|
-
for (const {cidr} of addresses) {
|
|
11
|
-
const net = ip.parseCIDR(cidr);
|
|
12
|
-
|
|
13
|
-
// eslint-disable-next-line unicorn/prefer-regexp-test
|
|
14
|
-
if (net[0] && net[0].kind() === gatewayIp.kind() && gatewayIp.match(net)) {
|
|
15
|
-
return net[0].toString();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function async(family) {
|
|
22
|
-
try {
|
|
23
|
-
const {gateway} = await defaultGateway[family]();
|
|
24
|
-
return findIp(gateway);
|
|
25
|
-
} catch {}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function sync(family) {
|
|
29
|
-
try {
|
|
30
|
-
const {gateway} = defaultGateway[family].sync();
|
|
31
|
-
return findIp(gateway);
|
|
32
|
-
} catch {}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function internalIpV6() {
|
|
36
|
-
return async('v6');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function internalIpV4() {
|
|
40
|
-
return async('v4');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function internalIpV6Sync() {
|
|
44
|
-
return sync('v6');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function internalIpV4Sync() {
|
|
48
|
-
return sync('v4');
|
|
1
|
+
import {networkInterfaces} from 'os';
|
|
2
|
+
import defaultGateway from 'default-gateway';
|
|
3
|
+
import ip from 'ipaddr.js';
|
|
4
|
+
|
|
5
|
+
function findIp(gateway) {
|
|
6
|
+
const gatewayIp = ip.parse(gateway);
|
|
7
|
+
|
|
8
|
+
// Look for the matching interface in all local interfaces.
|
|
9
|
+
for (const addresses of Object.values(networkInterfaces())) {
|
|
10
|
+
for (const {cidr} of addresses) {
|
|
11
|
+
const net = ip.parseCIDR(cidr);
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line unicorn/prefer-regexp-test
|
|
14
|
+
if (net[0] && net[0].kind() === gatewayIp.kind() && gatewayIp.match(net)) {
|
|
15
|
+
return net[0].toString();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function async(family) {
|
|
22
|
+
try {
|
|
23
|
+
const {gateway} = await defaultGateway[family]();
|
|
24
|
+
return findIp(gateway);
|
|
25
|
+
} catch {}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function sync(family) {
|
|
29
|
+
try {
|
|
30
|
+
const {gateway} = defaultGateway[family].sync();
|
|
31
|
+
return findIp(gateway);
|
|
32
|
+
} catch {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function internalIpV6() {
|
|
36
|
+
return async('v6');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function internalIpV4() {
|
|
40
|
+
return async('v4');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function internalIpV6Sync() {
|
|
44
|
+
return sync('v6');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function internalIpV4Sync() {
|
|
48
|
+
return sync('v4');
|
|
49
49
|
}
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
class DoubleLinkedList {
|
|
2
|
-
constructor() {
|
|
3
|
-
this._map = new Map();
|
|
4
|
-
this._head = null;
|
|
5
|
-
this._pointer = null;
|
|
6
|
-
this._tail = null;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
add(processId, proxy) {
|
|
10
|
-
const node = { processId: processId, proxy: proxy };
|
|
11
|
-
this._map.set(processId, node);
|
|
12
|
-
|
|
13
|
-
// no element in list
|
|
14
|
-
if (!this._head) {
|
|
15
|
-
this._head = node;
|
|
16
|
-
this._pointer = node;
|
|
17
|
-
this._tail = node;
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// adding to the tail
|
|
22
|
-
this._tail.next = node;
|
|
23
|
-
node.previous = this._tail;
|
|
24
|
-
this._tail = node;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
decrementPointer() {
|
|
28
|
-
this._pointer = this._pointer.previous ? this._pointer.previous : this._tail;
|
|
29
|
-
return this._pointer;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get(processId) {
|
|
33
|
-
return this._map.get(processId);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
has(processId) {
|
|
37
|
-
return this._map.has(processId);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
incrementPointer() {
|
|
41
|
-
this._pointer = this._pointer.next ? this._pointer.next : this._head;
|
|
42
|
-
|
|
43
|
-
return this._pointer;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
remove(processId) {
|
|
47
|
-
const node = this.get(processId);
|
|
48
|
-
if (!node)
|
|
49
|
-
return;
|
|
50
|
-
|
|
51
|
-
if (node.previous)
|
|
52
|
-
node.previous.next = node.next;
|
|
53
|
-
if (node.next)
|
|
54
|
-
node.next.previous = node.previous;
|
|
55
|
-
|
|
56
|
-
if (this._head === node)
|
|
57
|
-
this._head = node.next;
|
|
58
|
-
if (this._tail === node)
|
|
59
|
-
this._tail = node.previous;
|
|
60
|
-
|
|
61
|
-
if (this._pointer === node) {
|
|
62
|
-
this._pointer = node.next;
|
|
63
|
-
if (!this._pointer)
|
|
64
|
-
this._pointer = this._head;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
this._map.delete(processId);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
setPointer(processId) {
|
|
71
|
-
const node = this._map.get(processId);
|
|
72
|
-
if (!node)
|
|
73
|
-
return;
|
|
74
|
-
|
|
75
|
-
this._pointer = node;
|
|
76
|
-
return this._pointer;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get length() {
|
|
80
|
-
return this._map.size;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get pointer() {
|
|
84
|
-
return this._pointer;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export default DoubleLinkedList;
|
|
1
|
+
class DoubleLinkedList {
|
|
2
|
+
constructor() {
|
|
3
|
+
this._map = new Map();
|
|
4
|
+
this._head = null;
|
|
5
|
+
this._pointer = null;
|
|
6
|
+
this._tail = null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
add(processId, proxy) {
|
|
10
|
+
const node = { processId: processId, proxy: proxy };
|
|
11
|
+
this._map.set(processId, node);
|
|
12
|
+
|
|
13
|
+
// no element in list
|
|
14
|
+
if (!this._head) {
|
|
15
|
+
this._head = node;
|
|
16
|
+
this._pointer = node;
|
|
17
|
+
this._tail = node;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// adding to the tail
|
|
22
|
+
this._tail.next = node;
|
|
23
|
+
node.previous = this._tail;
|
|
24
|
+
this._tail = node;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
decrementPointer() {
|
|
28
|
+
this._pointer = this._pointer.previous ? this._pointer.previous : this._tail;
|
|
29
|
+
return this._pointer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get(processId) {
|
|
33
|
+
return this._map.get(processId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
has(processId) {
|
|
37
|
+
return this._map.has(processId);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
incrementPointer() {
|
|
41
|
+
this._pointer = this._pointer.next ? this._pointer.next : this._head;
|
|
42
|
+
|
|
43
|
+
return this._pointer;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
remove(processId) {
|
|
47
|
+
const node = this.get(processId);
|
|
48
|
+
if (!node)
|
|
49
|
+
return;
|
|
50
|
+
|
|
51
|
+
if (node.previous)
|
|
52
|
+
node.previous.next = node.next;
|
|
53
|
+
if (node.next)
|
|
54
|
+
node.next.previous = node.previous;
|
|
55
|
+
|
|
56
|
+
if (this._head === node)
|
|
57
|
+
this._head = node.next;
|
|
58
|
+
if (this._tail === node)
|
|
59
|
+
this._tail = node.previous;
|
|
60
|
+
|
|
61
|
+
if (this._pointer === node) {
|
|
62
|
+
this._pointer = node.next;
|
|
63
|
+
if (!this._pointer)
|
|
64
|
+
this._pointer = this._head;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this._map.delete(processId);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setPointer(processId) {
|
|
71
|
+
const node = this._map.get(processId);
|
|
72
|
+
if (!node)
|
|
73
|
+
return;
|
|
74
|
+
|
|
75
|
+
this._pointer = node;
|
|
76
|
+
return this._pointer;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get length() {
|
|
80
|
+
return this._map.size;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get pointer() {
|
|
84
|
+
return this._pointer;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default DoubleLinkedList;
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
class PriorityQueue {
|
|
2
|
-
constructor() {
|
|
3
|
-
this._values = [];
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
dequeue() {
|
|
7
|
-
// swap first and last element
|
|
8
|
-
this._swap(0, this._values.length - 1);
|
|
9
|
-
// pop max value off of values
|
|
10
|
-
let poppedNode = this._values.pop();
|
|
11
|
-
// re-adjust heap if length is greater than 1
|
|
12
|
-
if (this._values.length > 1)
|
|
13
|
-
this._bubbleDown();
|
|
14
|
-
|
|
15
|
-
return poppedNode;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// method that pushes new value onto the end and calls the bubble helper
|
|
19
|
-
enqueue(value) {
|
|
20
|
-
this._values.push(value)
|
|
21
|
-
// calculate parent, if parent is greater swap
|
|
22
|
-
// while loop or recurse
|
|
23
|
-
this._bubbleUp();
|
|
24
|
-
return this._values
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
length() {
|
|
28
|
-
return this._values.length;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
_bubbleDown() {
|
|
32
|
-
let parentIndex = 0;
|
|
33
|
-
const length = this._values.length;
|
|
34
|
-
const elementPriority = this._values[0].priority;
|
|
35
|
-
// loop breaks if no swaps are needed
|
|
36
|
-
// eslint-disable-next-line
|
|
37
|
-
while (true) {
|
|
38
|
-
// get indexes of child elements by following formula
|
|
39
|
-
let leftChildIndex = (2 * parentIndex) + 1;
|
|
40
|
-
let rightChildIndex = (2 * parentIndex) + 2;
|
|
41
|
-
let leftChildPriority, rightChildPriority;
|
|
42
|
-
let indexToSwap = null;
|
|
43
|
-
|
|
44
|
-
// if left child exists, and is greater than the element, plan to swap with the left child index
|
|
45
|
-
if (leftChildIndex < length) {
|
|
46
|
-
leftChildPriority = this._values[leftChildIndex].priority;
|
|
47
|
-
if (leftChildPriority < elementPriority)
|
|
48
|
-
indexToSwap = leftChildIndex;
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// if right child exists
|
|
53
|
-
if (rightChildIndex < length) {
|
|
54
|
-
rightChildPriority = this._values[rightChildIndex].priority;
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
// if right child is greater than element and there are no plans to swap
|
|
58
|
-
(rightChildPriority < elementPriority && indexToSwap === null) ||
|
|
59
|
-
// OR if right child is greater than left child and there ARE plans to swap
|
|
60
|
-
(rightChildPriority < leftChildPriority && indexToSwap !== null))
|
|
61
|
-
{
|
|
62
|
-
// plan to swap with the right child
|
|
63
|
-
indexToSwap = rightChildIndex;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// if there are no plans to swap, break out of the loop
|
|
68
|
-
if (indexToSwap === null)
|
|
69
|
-
break;
|
|
70
|
-
|
|
71
|
-
// swap with planned element
|
|
72
|
-
this._swap(parentIndex, indexToSwap);
|
|
73
|
-
// starting index is now index that we swapped with
|
|
74
|
-
parentIndex = indexToSwap;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// helper methods that bubbles up values from end
|
|
79
|
-
_bubbleUp() {
|
|
80
|
-
// get index of inserted element
|
|
81
|
-
let index = this._values.length - 1;
|
|
82
|
-
// loop while index is not 0 or element no loger needs to bubble
|
|
83
|
-
while (index > 0) {
|
|
84
|
-
// get parent index via formula
|
|
85
|
-
let parentIndex = Math.floor((index - 1)/2);
|
|
86
|
-
// if values is greater than parent, swap the two
|
|
87
|
-
if (this._values[parentIndex].priority > this._values[index].priority) {
|
|
88
|
-
// swap with helper method
|
|
89
|
-
this._swap(index, parentIndex);
|
|
90
|
-
// change current index to parent index
|
|
91
|
-
index = parentIndex;
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
_swap(index1, index2) {
|
|
102
|
-
let temp = this._values[index1];
|
|
103
|
-
this._values[index1] = this._values[index2];
|
|
104
|
-
this._values[index2] = temp;
|
|
105
|
-
return this._values;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export default PriorityQueue;
|
|
1
|
+
class PriorityQueue {
|
|
2
|
+
constructor() {
|
|
3
|
+
this._values = [];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
dequeue() {
|
|
7
|
+
// swap first and last element
|
|
8
|
+
this._swap(0, this._values.length - 1);
|
|
9
|
+
// pop max value off of values
|
|
10
|
+
let poppedNode = this._values.pop();
|
|
11
|
+
// re-adjust heap if length is greater than 1
|
|
12
|
+
if (this._values.length > 1)
|
|
13
|
+
this._bubbleDown();
|
|
14
|
+
|
|
15
|
+
return poppedNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// method that pushes new value onto the end and calls the bubble helper
|
|
19
|
+
enqueue(value) {
|
|
20
|
+
this._values.push(value)
|
|
21
|
+
// calculate parent, if parent is greater swap
|
|
22
|
+
// while loop or recurse
|
|
23
|
+
this._bubbleUp();
|
|
24
|
+
return this._values
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
length() {
|
|
28
|
+
return this._values.length;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_bubbleDown() {
|
|
32
|
+
let parentIndex = 0;
|
|
33
|
+
const length = this._values.length;
|
|
34
|
+
const elementPriority = this._values[0].priority;
|
|
35
|
+
// loop breaks if no swaps are needed
|
|
36
|
+
// eslint-disable-next-line
|
|
37
|
+
while (true) {
|
|
38
|
+
// get indexes of child elements by following formula
|
|
39
|
+
let leftChildIndex = (2 * parentIndex) + 1;
|
|
40
|
+
let rightChildIndex = (2 * parentIndex) + 2;
|
|
41
|
+
let leftChildPriority, rightChildPriority;
|
|
42
|
+
let indexToSwap = null;
|
|
43
|
+
|
|
44
|
+
// if left child exists, and is greater than the element, plan to swap with the left child index
|
|
45
|
+
if (leftChildIndex < length) {
|
|
46
|
+
leftChildPriority = this._values[leftChildIndex].priority;
|
|
47
|
+
if (leftChildPriority < elementPriority)
|
|
48
|
+
indexToSwap = leftChildIndex;
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// if right child exists
|
|
53
|
+
if (rightChildIndex < length) {
|
|
54
|
+
rightChildPriority = this._values[rightChildIndex].priority;
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
// if right child is greater than element and there are no plans to swap
|
|
58
|
+
(rightChildPriority < elementPriority && indexToSwap === null) ||
|
|
59
|
+
// OR if right child is greater than left child and there ARE plans to swap
|
|
60
|
+
(rightChildPriority < leftChildPriority && indexToSwap !== null))
|
|
61
|
+
{
|
|
62
|
+
// plan to swap with the right child
|
|
63
|
+
indexToSwap = rightChildIndex;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// if there are no plans to swap, break out of the loop
|
|
68
|
+
if (indexToSwap === null)
|
|
69
|
+
break;
|
|
70
|
+
|
|
71
|
+
// swap with planned element
|
|
72
|
+
this._swap(parentIndex, indexToSwap);
|
|
73
|
+
// starting index is now index that we swapped with
|
|
74
|
+
parentIndex = indexToSwap;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// helper methods that bubbles up values from end
|
|
79
|
+
_bubbleUp() {
|
|
80
|
+
// get index of inserted element
|
|
81
|
+
let index = this._values.length - 1;
|
|
82
|
+
// loop while index is not 0 or element no loger needs to bubble
|
|
83
|
+
while (index > 0) {
|
|
84
|
+
// get parent index via formula
|
|
85
|
+
let parentIndex = Math.floor((index - 1)/2);
|
|
86
|
+
// if values is greater than parent, swap the two
|
|
87
|
+
if (this._values[parentIndex].priority > this._values[index].priority) {
|
|
88
|
+
// swap with helper method
|
|
89
|
+
this._swap(index, parentIndex);
|
|
90
|
+
// change current index to parent index
|
|
91
|
+
index = parentIndex;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_swap(index1, index2) {
|
|
102
|
+
let temp = this._values[index1];
|
|
103
|
+
this._values[index1] = this._values[index2];
|
|
104
|
+
this._values[index2] = temp;
|
|
105
|
+
return this._values;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default PriorityQueue;
|