1
1
/* eslint-disable no-await-in-loop */
2
- import { Connection , ConnectionOptions , createConnection , getConnectionOptions , In } from 'typeorm' ;
2
+ import { Connection , ConnectionOptions , EntitySchema , getConnectionOptions , In } from 'typeorm' ;
3
3
import { MarkovCorpusEntry } from './entity/MarkovCorpusEntry' ;
4
4
import { MarkovFragment } from './entity/MarkovFragment' ;
5
5
import { MarkovInputData } from './entity/MarkovInputData' ;
@@ -8,6 +8,14 @@ import { MarkovRoot } from './entity/MarkovRoot';
8
8
import { Importer } from './importer' ;
9
9
import { MarkovImportExport as MarkovV3ImportExport } from './v3-types' ;
10
10
11
+ const ALL_ENTITIES = [
12
+ MarkovCorpusEntry ,
13
+ MarkovRoot ,
14
+ MarkovOptions ,
15
+ MarkovInputData ,
16
+ MarkovFragment ,
17
+ ] ;
18
+
11
19
/**
12
20
* Data to build the Markov instance
13
21
*/
@@ -100,14 +108,36 @@ export default class Markov {
100
108
101
109
public options : MarkovOptions | MarkovDataMembers ;
102
110
103
- public connection : Connection ;
104
-
105
111
public id : string ;
106
112
107
113
private defaultOptions : MarkovDataMembers = {
108
114
stateSize : 2 ,
109
115
} ;
110
116
117
+ /**
118
+ * If you're connecting the Markov DB with your parent project's DB, you'll need to extend it to add the Markov entities to the connection.
119
+ * @param connectionOptions Your TypeORM connection options. If not provided, it will load the ormconfig from a file.
120
+ * @returns ConnectionOptions that should be passed into a createConnection() call.
121
+ */
122
+ public static async extendConnectionOptions (
123
+ connectionOptions ?: ConnectionOptions
124
+ ) : Promise < ConnectionOptions > {
125
+ let baseConnectionOpts : ConnectionOptions ;
126
+ if ( connectionOptions ) {
127
+ baseConnectionOpts = connectionOptions ;
128
+ } else {
129
+ baseConnectionOpts = await getConnectionOptions ( ) ;
130
+ }
131
+
132
+ // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
133
+ const appendedEntities : ( Function | string | EntitySchema < any > ) [ ] = ALL_ENTITIES ;
134
+ if ( baseConnectionOpts . entities ) appendedEntities . push ( ...baseConnectionOpts . entities ) ;
135
+ return {
136
+ ...baseConnectionOpts ,
137
+ entities : appendedEntities ,
138
+ } ;
139
+ }
140
+
111
141
/**
112
142
* Creates an instance of Markov generator.
113
143
*/
@@ -119,19 +149,12 @@ export default class Markov {
119
149
}
120
150
121
151
/**
122
- * Connects this instance to your database. You should setup an ormconfig, or pass it in as an object.
152
+ * If you have a non-default connection (you probably don't), pass it in here.
153
+ * Otherwise, setup() is called implicitly on any async function.
154
+ * @param connection A non-default connection to be used by Markov's entities
123
155
*/
124
- public async connect ( connectionOptions ?: ConnectionOptions ) : Promise < Connection > {
125
- let baseConnectionOpts : ConnectionOptions ;
126
- if ( connectionOptions ) {
127
- baseConnectionOpts = connectionOptions ;
128
- } else {
129
- baseConnectionOpts = await getConnectionOptions ( ) ;
130
- }
131
- this . connection = await createConnection ( {
132
- ...baseConnectionOpts ,
133
- entities : [ MarkovCorpusEntry , MarkovRoot , MarkovOptions , MarkovInputData , MarkovFragment ] ,
134
- } ) ;
156
+ public async setup ( connection ?: Connection ) : Promise < void > {
157
+ if ( connection ) ALL_ENTITIES . forEach ( ( e ) => e . useConnection ( connection ) ) ;
135
158
136
159
let db = await MarkovRoot . findOne ( {
137
160
id : this . id ,
@@ -151,13 +174,10 @@ export default class Markov {
151
174
this . db = db ;
152
175
this . id = this . db . id ;
153
176
this . options = options ;
154
- return this . connection ;
155
177
}
156
178
157
- public async disconnect ( ) : Promise < void > {
158
- if ( this . connection ) {
159
- await this . connection . close ( ) ;
160
- }
179
+ private async ensureSetup ( ) : Promise < void > {
180
+ if ( ! this . db ) await this . setup ( ) ;
161
181
}
162
182
163
183
/**
@@ -183,12 +203,13 @@ export default class Markov {
183
203
* Supports imports from markov-strings v3, as well as exports from this version.
184
204
*/
185
205
public async import ( data : MarkovRoot | MarkovV3ImportExport ) : Promise < void > {
206
+ await this . ensureSetup ( ) ;
186
207
if ( 'id' in data ) {
187
- const options = MarkovOptions . create ( data . options ) ;
188
- await MarkovOptions . save ( options ) ;
189
208
this . db = new MarkovRoot ( ) ;
190
209
this . db . id = this . id ;
210
+ const options = MarkovOptions . create ( data . options ) ;
191
211
this . db . options = options ;
212
+ await MarkovOptions . save ( options ) ;
192
213
193
214
const importer = new Importer ( this . db ) ;
194
215
const startWords = await importer . saveImportFragments ( data . startWords , 'startWordMarkov' ) ;
@@ -228,6 +249,7 @@ export default class Markov {
228
249
* Exports all the data in the database associated with this Markov instance as a JSON object.
229
250
*/
230
251
public async export ( ) : Promise < MarkovRoot > {
252
+ await this . ensureSetup ( ) ;
231
253
const db = await MarkovRoot . findOneOrFail ( {
232
254
where : { id : this . id } ,
233
255
relations : [
@@ -251,6 +273,7 @@ export default class Markov {
251
273
* It's possible to store custom JSON-like data of your choice next to the string by passing in objects of `{ string: 'foo', custom: 'attachment' }`. This data will be returned in the `refs` of the result.
252
274
*/
253
275
public async addData ( rawData : AddDataProps [ ] | string [ ] ) {
276
+ await this . ensureSetup ( ) ;
254
277
// Format data if necessary
255
278
let input : AddDataProps [ ] = [ ] ;
256
279
if ( typeof rawData [ 0 ] === 'string' ) {
@@ -270,6 +293,7 @@ export default class Markov {
270
293
* Builds the corpus. You must call this before generating sentences.
271
294
*/
272
295
private async buildCorpus ( data : AddDataProps [ ] ) : Promise < void > {
296
+ await this . ensureSetup ( ) ;
273
297
const { options } = this . db ;
274
298
275
299
// Loop through all sentences
@@ -412,6 +436,7 @@ export default class Markov {
412
436
* @param rawData A list of full strings
413
437
*/
414
438
public async removeData ( rawData : string [ ] ) : Promise < void > {
439
+ await this . ensureSetup ( ) ;
415
440
const inputData = await MarkovInputData . find ( {
416
441
relations : [ 'fragment' , 'fragment.corpusEntry' ] ,
417
442
where : [
@@ -447,15 +472,14 @@ export default class Markov {
447
472
public async generate < CustomData = any > ( // eslint-disable-line @typescript-eslint/no-explicit-any
448
473
options ?: MarkovGenerateOptions < CustomData >
449
474
) : Promise < MarkovResult < CustomData > > {
450
- // const corpusSize = await CorpusEntry.count({markov: this.db} );
475
+ await this . ensureSetup ( ) ;
451
476
const corpusSize = await MarkovCorpusEntry . count ( { markov : this . db } ) ;
452
477
if ( corpusSize <= 0 ) {
453
478
throw new Error (
454
479
'Corpus is empty. There is either no data, or the data is not sufficient to create markov chains.'
455
480
) ;
456
481
}
457
482
458
- // const corpus = cloneDeep(this.corpus)
459
483
const maxTries = options ?. maxTries ? options . maxTries : 10 ;
460
484
461
485
let tries : number ;
0 commit comments