anote-server-libs 0.9.4 → 0.9.6

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/models/ApiCall.ts CHANGED
@@ -1,40 +1,40 @@
1
- import { ConnectionPool, DateTimeOffset, Request } from 'mssql';
2
- import {Pool} from 'pg';
3
- import {Logger} from 'winston';
4
- import {Model, ModelDao} from './repository/ModelDao';
5
-
6
- export interface ApiCall extends Model<string> {
7
- responseCode: number;
8
- responseJson: string;
9
- expiresAt: Date;
10
- }
11
-
12
- export class ApiCallRepository extends ModelDao<string, ApiCall> {
13
- constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
14
- super(pool, poolMssql, logger, 'api_call', 5, pool ? 'id=$1,"updatedOn"=$2,"responseCode"=$3,"responseJson"=$4,"expiresAt"=$5' :
15
- 'id=@1,"updatedOn"=@2,"responseCode"=@3,"responseJson"=@4,"expiresAt"=@5');
16
- }
17
-
18
- buildObject(q: any): ApiCall {
19
- if(!q) return undefined;
20
- q.id = q.id.trim();
21
- q.updatedOn = q.updatedOn && new Date(q.updatedOn);
22
- q.responseCode = parseInt(q.responseCode, 10);
23
- q.expiresAt = q.expiresAt && new Date(q.expiresAt);
24
- return q;
25
- }
26
-
27
- serialize(instance: ApiCall, request?: Request) {
28
- if(request) {
29
- request.input('1', instance.id);
30
- request.input('2', DateTimeOffset, instance.updatedOn);
31
- request.input('3', instance.responseCode);
32
- request.input('4', instance.responseJson);
33
- request.input('5', DateTimeOffset, instance.expiresAt);
34
- return undefined;
35
- } else {
36
- return [instance.id, instance.updatedOn, instance.responseCode, instance.responseJson, instance.expiresAt];
37
- }
38
- }
39
-
40
- }
1
+ import { ConnectionPool, DateTimeOffset, Request } from 'mssql';
2
+ import {Pool} from 'pg';
3
+ import {Logger} from 'winston';
4
+ import {Model, ModelDao} from './repository/ModelDao';
5
+
6
+ export interface ApiCall extends Model<string> {
7
+ responseCode: number;
8
+ responseJson: string;
9
+ expiresAt: Date;
10
+ }
11
+
12
+ export class ApiCallRepository extends ModelDao<string, ApiCall> {
13
+ constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
14
+ super(pool, poolMssql, logger, 'api_call', 5, pool ? 'id=$1,"updatedOn"=$2,"responseCode"=$3,"responseJson"=$4,"expiresAt"=$5' :
15
+ 'id=@1,"updatedOn"=@2,"responseCode"=@3,"responseJson"=@4,"expiresAt"=@5');
16
+ }
17
+
18
+ buildObject(q: any): ApiCall {
19
+ if(!q) return undefined;
20
+ q.id = q.id.trim();
21
+ q.updatedOn = q.updatedOn && new Date(q.updatedOn);
22
+ q.responseCode = parseInt(q.responseCode, 10);
23
+ q.expiresAt = q.expiresAt && new Date(q.expiresAt);
24
+ return q;
25
+ }
26
+
27
+ serialize(instance: ApiCall, request?: Request) {
28
+ if(request) {
29
+ request.input('1', instance.id);
30
+ request.input('2', DateTimeOffset, instance.updatedOn);
31
+ request.input('3', instance.responseCode);
32
+ request.input('4', instance.responseJson);
33
+ request.input('5', DateTimeOffset, instance.expiresAt);
34
+ return undefined;
35
+ } else {
36
+ return [instance.id, instance.updatedOn, instance.responseCode, instance.responseJson, instance.expiresAt];
37
+ }
38
+ }
39
+
40
+ }
@@ -1,43 +1,43 @@
1
- import { ConnectionPool, Request } from 'mssql';
2
- import {Pool} from 'pg';
3
- import {Logger} from 'winston';
4
- import {ModelDao} from './repository/ModelDao';
5
-
6
- export interface Migration {
7
- id: number;
8
- hash: string;
9
- sqlUp: string;
10
- sqlDown: string;
11
- state: number;
12
- skip: boolean;
13
- }
14
-
15
- export class MigrationRepository extends ModelDao<number, Migration> {
16
- constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
17
- super(pool, poolMssql, logger, 'migration', 6, pool ? 'id=$1,hash=$2,"sqlUp"=$3,"sqlDown"=$4,state=$5,skip=$6' :
18
- 'id=@1,hash=@2,"sqlUp"=@3,"sqlDown"=@4,state=@5,skip=@6');
19
- }
20
-
21
- buildObject(q: any): Migration {
22
- if(!q) return undefined;
23
- q.id = parseInt(q.id, 10);
24
- q.hash = q.hash.trim();
25
- q.state = parseInt(q.state, 10);
26
- q.skip = q.skip ? true : false;
27
- return q;
28
- }
29
-
30
- serialize(instance: Migration, request?: Request) {
31
- if(request) {
32
- request.input('1', instance.id);
33
- request.input('2', instance.hash);
34
- request.input('3', instance.sqlUp);
35
- request.input('4', instance.sqlDown);
36
- request.input('5', instance.state);
37
- request.input('6', instance.skip ? 1 : 0);
38
- return undefined;
39
- } else {
40
- return [instance.id, instance.hash, instance.sqlUp, instance.sqlDown, instance.state, instance.skip];
41
- }
42
- }
43
- }
1
+ import { ConnectionPool, Request } from 'mssql';
2
+ import {Pool} from 'pg';
3
+ import {Logger} from 'winston';
4
+ import {ModelDao} from './repository/ModelDao';
5
+
6
+ export interface Migration {
7
+ id: number;
8
+ hash: string;
9
+ sqlUp: string;
10
+ sqlDown: string;
11
+ state: number;
12
+ skip: boolean;
13
+ }
14
+
15
+ export class MigrationRepository extends ModelDao<number, Migration> {
16
+ constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
17
+ super(pool, poolMssql, logger, 'migration', 6, pool ? 'id=$1,hash=$2,"sqlUp"=$3,"sqlDown"=$4,state=$5,skip=$6' :
18
+ 'id=@1,hash=@2,"sqlUp"=@3,"sqlDown"=@4,state=@5,skip=@6');
19
+ }
20
+
21
+ buildObject(q: any): Migration {
22
+ if(!q) return undefined;
23
+ q.id = parseInt(q.id, 10);
24
+ q.hash = q.hash.trim();
25
+ q.state = parseInt(q.state, 10);
26
+ q.skip = q.skip ? true : false;
27
+ return q;
28
+ }
29
+
30
+ serialize(instance: Migration, request?: Request) {
31
+ if(request) {
32
+ request.input('1', instance.id);
33
+ request.input('2', instance.hash);
34
+ request.input('3', instance.sqlUp);
35
+ request.input('4', instance.sqlDown);
36
+ request.input('5', instance.state);
37
+ request.input('6', instance.skip ? 1 : 0);
38
+ return undefined;
39
+ } else {
40
+ return [instance.id, instance.hash, instance.sqlUp, instance.sqlDown, instance.state, instance.skip];
41
+ }
42
+ }
43
+ }
@@ -23,7 +23,7 @@ class BaseModelRepository {
23
23
  this.Migration = new Migration_1.MigrationRepository(db, dbMssql, logger);
24
24
  this.ApiCall = new ApiCall_1.ApiCallRepository(db, dbMssql, logger);
25
25
  }
26
- migrate(migrationsPath, callback, onlyAboveOrEquals = 0) {
26
+ migrate(migrationsPath, callback, onlyAboveOrEquals = 0, onlyBelow) {
27
27
  (this.db ? Promise.all([
28
28
  this.db.query(`CREATE TABLE IF NOT EXISTS migration (
29
29
  id integer PRIMARY KEY,
@@ -70,16 +70,22 @@ END`)
70
70
  hash: crypto.createHash('sha256').update(content).digest('hex')
71
71
  };
72
72
  });
73
- if (migrationsAvailable.length === 0
74
- || migrationsAvailable.length
75
- !== migrationsAvailable[migrationsAvailable.length - 1].id)
73
+ migrations = migrations.filter(m => m.id >= onlyAboveOrEquals);
74
+ if (onlyBelow)
75
+ migrations = migrations.filter(m => m.id < onlyBelow);
76
+ if (migrationsAvailable.length === 0 && migrations.length === 0)
76
77
  process.exit(5);
77
- let highestCommon = onlyAboveOrEquals;
78
- while (highestCommon < migrations.length && highestCommon < migrationsAvailable.length
78
+ if (migrationsAvailable.length && migrationsAvailable.length !== (migrationsAvailable[migrationsAvailable.length - 1].id - migrationsAvailable[0].id + 1))
79
+ process.exit(5);
80
+ let highestCommon = 0;
81
+ while (highestCommon < migrations.length
82
+ && highestCommon < migrationsAvailable.length
83
+ && migrations[highestCommon]
84
+ && migrationsAvailable[highestCommon]
79
85
  && migrations[highestCommon].hash === migrationsAvailable[highestCommon].hash)
80
86
  highestCommon++;
81
- this.applyDownUntil(migrations, migrations.length, highestCommon).then(highestCommon => {
82
- this.applyUpUntil(migrationsAvailable, Math.min(highestCommon, migrations.length), migrationsAvailable.length).then(callback, process.exit);
87
+ this.applyDownUntil(migrations, migrations.length, highestCommon).then(appliedId => {
88
+ this.applyUpUntil(migrationsAvailable, Math.min(appliedId, migrations.length), migrationsAvailable.length).then(callback, process.exit);
83
89
  }, process.exit);
84
90
  });
85
91
  }, () => process.exit(3));
@@ -91,13 +97,15 @@ END`)
91
97
  return Promise.all(tables.map(t => client.request().query('SELECT id FROM ' + t.table + ' WITH (UPDLOCK)')));
92
98
  }
93
99
  applyUpUntil(migrations, current, until) {
94
- if (current < until)
100
+ if (current < until) {
101
+ console.log('Applying migration ' + migrations[current].id);
95
102
  return this.applyUp(migrations[current]).then(() => this.applyUpUntil(migrations, current + 1, until));
103
+ }
96
104
  return Promise.resolve();
97
105
  }
98
106
  applyUp(migration) {
99
107
  return new Promise((resolve, reject) => {
100
- const sqlParts = migration.content.split('----');
108
+ const sqlParts = migration.content.split(/-{4,}/);
101
109
  this.Migration.create({
102
110
  id: migration.id,
103
111
  hash: migration.hash,
@@ -126,6 +134,7 @@ END`)
126
134
  applyDownUntil(migrations, current, until) {
127
135
  if (current > until && !migrations[current - 1]?.skip) {
128
136
  current--;
137
+ console.log('Reverting migration ' + migrations[current].id);
129
138
  return this.applyDown(migrations[current]).then(() => this.applyDownUntil(migrations, current, until));
130
139
  }
131
140
  return Promise.resolve(current);
@@ -26,7 +26,7 @@ export class BaseModelRepository {
26
26
  }
27
27
 
28
28
  // TODO: alter table migration if exists without ok column
29
- migrate(migrationsPath: string, callback: (() => void), onlyAboveOrEquals = 0) {
29
+ migrate(migrationsPath: string, callback: (() => void), onlyAboveOrEquals = 0, onlyBelow?: number) {
30
30
  (this.db ? Promise.all([
31
31
  this.db.query(`CREATE TABLE IF NOT EXISTS migration (
32
32
  id integer PRIMARY KEY,
@@ -71,15 +71,19 @@ END`)])).then(() => {
71
71
  hash: crypto.createHash('sha256').update(content).digest('hex')
72
72
  };
73
73
  });
74
- if(migrationsAvailable.length === 0
75
- || migrationsAvailable.length
76
- !== migrationsAvailable[migrationsAvailable.length - 1].id) process.exit(5); // Did not use OK files
77
- let highestCommon = onlyAboveOrEquals;
78
- while(highestCommon < migrations.length && highestCommon < migrationsAvailable.length
79
- && migrations[highestCommon].hash === migrationsAvailable[highestCommon].hash)
74
+ migrations = migrations.filter(m => m.id >= onlyAboveOrEquals);
75
+ if(onlyBelow) migrations = migrations.filter(m => m.id < onlyBelow);
76
+ if(migrationsAvailable.length === 0 && migrations.length === 0) process.exit(5);
77
+ if(migrationsAvailable.length && migrationsAvailable.length !== (migrationsAvailable[migrationsAvailable.length - 1].id - migrationsAvailable[0].id + 1)) process.exit(5);
78
+ let highestCommon = 0;
79
+ while(highestCommon < migrations.length
80
+ && highestCommon < migrationsAvailable.length
81
+ && migrations[highestCommon]
82
+ && migrationsAvailable[highestCommon]
83
+ && migrations[highestCommon].hash === migrationsAvailable[highestCommon].hash)
80
84
  highestCommon++;
81
- this.applyDownUntil(migrations, migrations.length, highestCommon).then(highestCommon => {
82
- this.applyUpUntil(migrationsAvailable, Math.min(highestCommon, migrations.length), migrationsAvailable.length).then(callback, process.exit);
85
+ this.applyDownUntil(migrations, migrations.length, highestCommon).then(appliedId => {
86
+ this.applyUpUntil(migrationsAvailable, Math.min(appliedId, migrations.length), migrationsAvailable.length).then(callback, process.exit);
83
87
  }, process.exit);
84
88
  });
85
89
  }, () => process.exit(3));
@@ -93,14 +97,16 @@ END`)])).then(() => {
93
97
  }
94
98
 
95
99
  private applyUpUntil(migrations: {id: number, content: string, hash: string}[], current: number, until: number): Promise<void> {
96
- if(current < until)
100
+ if(current < until) {
101
+ console.log('Applying migration ' + migrations[current].id);
97
102
  return this.applyUp(migrations[current]).then(() => this.applyUpUntil(migrations, current + 1, until));
103
+ }
98
104
  return Promise.resolve();
99
105
  }
100
106
 
101
107
  private applyUp(migration: {id: number, content: string, hash: string}): Promise<void> {
102
108
  return new Promise((resolve, reject) => {
103
- const sqlParts = migration.content.split('----');
109
+ const sqlParts = migration.content.split(/-{4,}/);
104
110
  this.Migration.create({
105
111
  id: migration.id,
106
112
  hash: migration.hash,
@@ -127,6 +133,7 @@ END`)])).then(() => {
127
133
  private applyDownUntil(migrations: Migration[], current: number, until: number): Promise<number> {
128
134
  if(current > until && !migrations[current - 1]?.skip) {
129
135
  current--;
136
+ console.log('Reverting migration ' + migrations[current].id);
130
137
  return this.applyDown(migrations[current]).then(() => this.applyDownUntil(migrations, current, until));
131
138
  }
132
139
  return Promise.resolve(current);
@@ -1,87 +1,87 @@
1
- import * as Memcached from 'memcached';
2
-
3
- export class MemoryCache<T> {
4
-
5
- private localCache: {[id: string]: any} = {};
6
-
7
- constructor(private localKey: string, private cache?: Memcached) {
8
- }
9
-
10
- list(): Promise<T[]> {
11
- if(this.cache) return new Promise(resolve => {
12
- let pending = true;
13
- setTimeout(() => {
14
- if(pending) {
15
- pending = false;
16
- resolve([]);
17
- }
18
- }, 250);
19
- this.cache.items((_, data) => {
20
- if(pending) {
21
- pending = false;
22
- resolve(data.map(s => {
23
- const value = <string>s[Object.getOwnPropertyNames(s).find(sname => sname.startsWith(this.localKey))];
24
- return value && JSON.parse(value);
25
- }).filter(x => x));
26
- }
27
- });
28
- });
29
- else return Promise.resolve(Object.getOwnPropertyNames(this.localCache).map(key => this.localCache[key]));
30
- }
31
-
32
- get(key: string | number): Promise<T> {
33
- if(this.cache) return new Promise(resolve => {
34
- let pending = true;
35
- setTimeout(() => {
36
- if(pending) {
37
- pending = false;
38
- resolve(undefined);
39
- }
40
- }, 250);
41
- this.cache.get(this.localKey + key, (_, data) => {
42
- if(pending) {
43
- pending = false;
44
- resolve(data && JSON.parse(data));
45
- }
46
- });
47
- });
48
- else return Promise.resolve(this.localCache[key]);
49
- }
50
-
51
- set(key: string | number, val: T, time = 15 * 60): Promise<void> {
52
- if(this.cache) return new Promise(resolve => this.cache.set(this.localKey + key, JSON.stringify(val), time, resolve));
53
- else {
54
- this.localCache[key] = val;
55
- return Promise.resolve();
56
- }
57
- }
58
-
59
- delete(key: string | number): Promise<void> {
60
- if(this.cache) {
61
- return new Promise(resolve => {
62
- let fired = false;
63
- const handler = setTimeout(() => {
64
- fired = true;
65
- resolve();
66
- }, 50);
67
- this.cache.del(this.localKey + key, () => {
68
- if(!fired) {
69
- clearTimeout(handler);
70
- resolve();
71
- }
72
- });
73
- });
74
- } else {
75
- this.localCache[key] = undefined;
76
- return Promise.resolve();
77
- }
78
- }
79
-
80
- clear() {
81
- if(this.cache) {
82
- this.localKey = this.localKey + '_';
83
- if(this.localKey.length > 40)
84
- this.localKey = this.localKey.replace(/_+$/, '');
85
- } else this.localCache = {};
86
- }
87
- }
1
+ import * as Memcached from 'memcached';
2
+
3
+ export class MemoryCache<T> {
4
+
5
+ private localCache: {[id: string]: any} = {};
6
+
7
+ constructor(private localKey: string, private cache?: Memcached) {
8
+ }
9
+
10
+ list(): Promise<T[]> {
11
+ if(this.cache) return new Promise(resolve => {
12
+ let pending = true;
13
+ setTimeout(() => {
14
+ if(pending) {
15
+ pending = false;
16
+ resolve([]);
17
+ }
18
+ }, 250);
19
+ this.cache.items((_, data) => {
20
+ if(pending) {
21
+ pending = false;
22
+ resolve(data.map(s => {
23
+ const value = <string>s[Object.getOwnPropertyNames(s).find(sname => sname.startsWith(this.localKey))];
24
+ return value && JSON.parse(value);
25
+ }).filter(x => x));
26
+ }
27
+ });
28
+ });
29
+ else return Promise.resolve(Object.getOwnPropertyNames(this.localCache).map(key => this.localCache[key]));
30
+ }
31
+
32
+ get(key: string | number): Promise<T> {
33
+ if(this.cache) return new Promise(resolve => {
34
+ let pending = true;
35
+ setTimeout(() => {
36
+ if(pending) {
37
+ pending = false;
38
+ resolve(undefined);
39
+ }
40
+ }, 250);
41
+ this.cache.get(this.localKey + key, (_, data) => {
42
+ if(pending) {
43
+ pending = false;
44
+ resolve(data && JSON.parse(data));
45
+ }
46
+ });
47
+ });
48
+ else return Promise.resolve(this.localCache[key]);
49
+ }
50
+
51
+ set(key: string | number, val: T, time = 15 * 60): Promise<void> {
52
+ if(this.cache) return new Promise(resolve => this.cache.set(this.localKey + key, JSON.stringify(val), time, resolve));
53
+ else {
54
+ this.localCache[key] = val;
55
+ return Promise.resolve();
56
+ }
57
+ }
58
+
59
+ delete(key: string | number): Promise<void> {
60
+ if(this.cache) {
61
+ return new Promise(resolve => {
62
+ let fired = false;
63
+ const handler = setTimeout(() => {
64
+ fired = true;
65
+ resolve();
66
+ }, 50);
67
+ this.cache.del(this.localKey + key, () => {
68
+ if(!fired) {
69
+ clearTimeout(handler);
70
+ resolve();
71
+ }
72
+ });
73
+ });
74
+ } else {
75
+ this.localCache[key] = undefined;
76
+ return Promise.resolve();
77
+ }
78
+ }
79
+
80
+ clear() {
81
+ if(this.cache) {
82
+ this.localKey = this.localKey + '_';
83
+ if(this.localKey.length > 40)
84
+ this.localKey = this.localKey.replace(/_+$/, '');
85
+ } else this.localCache = {};
86
+ }
87
+ }