@keltoi/hydra 1.2.2 → 2.0.0

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/index.js CHANGED
@@ -1 +1,878 @@
1
- "use strict";var e=require("knex"),t=require("axios");class AppError{#e;#t;constructor({code:e=0,message:t=""}){this.#e=e,this.#t=t}get view(){return{code:this.code,message:this.message}}get code(){return this.#e}get message(){return this.#t}}class Model{#s;constructor(e={}){this.#s=e}get key(){return this.#s}set key(e={}){this.#s=e}get entity(){return{}}static build(e={}){return new Model(e)}}var runWhenFalse=(e=Promise.resolve(!0),t=async()=>{})=>e.then((async e=>{e||await t()}));class Logged extends Model{#n=new Date;constructor({key:e={},createdAt:t=new Date}){super(e),this.#n=t}get createdAt(){return this.#n}set createdAt(e=new Date){this.createdAt=e}static makeMe(t=e(),s=Logged,n=(t=new e.TableBuilder)=>{}){return runWhenFalse(t.schema.hasTable(s.name),(()=>t.schema.createTable(s.name,(e=>{n(e),e.dateTime("createdAt").notNullable().defaultTo(t.fn.now())}))))}}class Traced extends Logged{#r=void 0|new Date;#i=!0;constructor({key:e={},createdAt:t=new Date,updatedAt:s=void 0|new Date,active:n=!0}){super({key:e,createdAt:t}),this.#i=n,this.#r=s}get updatedAt(){return this.#r}set updatedAt(e=new Date){this.#r=e}get active(){return this.#i}set active(e=!0){this.#i=e}tickUpdateNow(){this.#r=new Date}static makeMe(t=e(),s=Traced,n=(t=new e.TableBuilder)=>{}){return super.makeMe(t,s,(e=>{n(e),e.dateTime("updatedAt").nullable(),e.boolean("active").defaultTo(!0)}))}}class Linking{#a=new Model;#o=new Model;#c=Model;#d=Model;get Abscissa(){return this.#c}get Ordinate(){return this.#d}constructor(e=Model,t=Model,{abscissa:s=new e,ordinate:n=new t}){this.#c=e,this.#d=t,this.#a=s,this.#o=n}static build=({AbscissaModel:e=Model,OrdinateModel:t=Model,abscissa:s=new Model,ordinate:n=new Model})=>new Linking(e,t,{abscissa:s,ordinate:n});static makeMe(t=e(),s=Model,n=Model,r=(t=new e.TableBuilder)=>{}){const i=`${s.name}${n.name}`;return runWhenFalse(t.schema.hasTable(i),(()=>t.schema.createTable(i,(e=>{r(e)}))))}get abscissaKey(){return{idAbscissa:this.#a.key}}get ordinateKey(){return{idOrdinate:this.#o.key}}get key(){return{...this.abscissaKey,...this.ordinateKey}}get entity(){}get abscissa(){return this.#a}set abscissa(e=this.Abscissa.build()){this.#a=e}get ordinate(){return this.#o}set ordinate(e=this.Ordinate.build()){this.ordinate=e}}class Thing extends Model{#h;constructor({key:e={},name:t=""}){super(e),this.#h=t}get name(){return this.#h}set name(e=""){this.#h=e}get entity(){return{name:this.#h}}static makeMe(t=e(),s=Thing,n=255,r=(t=new e.TableBuilder)=>{}){return runWhenFalse(t.schema.hasTable(s.name),(()=>t.schema.createTable(s.name,(e=>{r(e),e.string(n).notNullable()}))))}}let s=class Context{#y;constructor(t=e()){this.#y=t}get db(){return this.#y}unitOfWork(...e){return this.#y.transaction().then((t=>{e.forEach((e=>e.context=t));const clean=()=>e.forEach((e=>e.resetContext()));return{done:()=>t.commit().then(clean),rollback:()=>t.rollback().then(clean)}}))}static instance(t=e()){return new Context(t)}async terraform(e=[]){const t=e.map((async e=>e.makeMe(this.#y)));await Promise.all(t)}},n=class Repository{#h="";myContext;Entity=Model;static anyOrError(e,t={code:0,message:""}){if(e)return e;throw new AppError(t)}static setOrEmpty(e=[],t=e=>e){return e.length?e.map(t):[]}constructor(e=Model,t=new s){this.#h=e.name,this.myContext=()=>t.db(this.#h),this.resetContext=()=>{this.myContext=()=>t.db(this.#h)},this.Entity=e}set context(t=e()){this.myContext=()=>t(this.#h)}create=(e=new Model)=>this.myContext().insert({...e.key,...e.entity}).then((()=>e));insert=(e=new Model)=>this.myContext().insert(e.entity,Object.keys(e.key)).then((t=>(e.key=t[0],e)));update=(e=new Model)=>this.myContext().where(e.key).update(e.entity).then((e=>e>0));delete=(e=new Model)=>this.myContext().where(e.key).del().then((e=>e>0));get=(e=new Model)=>this.myContext().where(e.key).first().then((e=>Repository.anyOrError(e,{code:404,message:"Not found"}))).then(this.Entity.build);list=()=>this.myContext().select().then((e=>Repository.setOrEmpty(e,this.Entity.build)))};class Context{#l;constructor(e=t.create({})){this.#l=e}get http(){return this.#l}}class Repository{#m;constructor(e=Model,t=new Context){this.#m=t,this.modelInstance=(t={})=>new e(t)}static queryString(e={}){return"?"+Object.entries(e).map((([e,t])=>`${e}=${t}`)).join("&")}get context(){return this.#m}}exports.ApiContext=Context,exports.ApiRepository=Repository,exports.ApiRestRepository=class RestRepository extends Repository{constructor(e=Model,t=new Context){super(e,t)}#u=(e="",t=void 0|{})=>this.context.http.get(t?`${e}${Repository.queryString(t)}`:e);get=(e="",t=void 0|{})=>this.#u(e,t).then((e=>this.modelInstance(e)));list=(e="",t=void 0|{})=>this.#u(e,t).then(((e=[])=>e.map((e=>this.modelInstance(e)))));create=(e="",t=new Model)=>this.context.http.post(e,t.entity);update=(e="",t=new Model)=>this.context.http.put(e,t.entity);change=(e="",t=new Model)=>this.context.http.patch(e,t.entity);delete=(e,t=new Model)=>this.context.http.delete(`/${e}`)},exports.AppError=AppError,exports.DbContext=s,exports.DbLinked=class DbLinked{#p;#h="";myContext;constructor(e=Linking,t=new s){this.#h=e.name,this.myContext=()=>t.db(this.#h),this.#p=e}createBatch=(e=[new Linking])=>this.myContext().insert(e.map((e=>({...e.key,...e.entity})))).then((()=>e));create=(e=new Linking)=>this.myContext().insert({...e.key,...e.entity}).then((()=>e));insertOrdinatesByAbscissa=({abscissa:e=new Model,ordinates:t=[new Model]})=>{const s=t.map((t=>this.#p.build({abscissa:e,ordinate:t})));return this.createBatch(s)};insertAbscissasByOrdinate=({ordinate:e=new Model,abscissas:t=[new Model]})=>{const s=t.map((t=>this.#p.build({abscissa:t,ordinate:e})));return this.createBatch(s)};delete=(e=new Linking)=>this.myContext().where(e.key).del().then((e=>e>0));getAbscissasByOrdinate(e=new Linking){const t=e.Abscissa,s=e.Ordinate,n=Object.keys(e.abscissaKey),r=Object.keys(e.abscissa.key),i=n.map((e=>`${t.name}${s.name}.${e}`)),a=r.map((e=>`${t.name}.${e}`));return this.myContext().where(e.ordinateKey).select(`${t.name}.*`).join(t.name,(e=>i.forEach(((t,s)=>{e.on(t,a[s])})))).then((e=>e.map((e=>t.build(e)))))}getOrdinatesByAbscissa(e=new Linking){const t=e.Ordinate,s=e.Abscissa,n=Object.keys(e.ordinateKey),r=Object.keys(e.ordinate.key),i=n.map((e=>`${s.name}${t.name}.${e}`)),a=r.map((e=>`${t.name}.${e}`));return this.myContext().where(e.abscissaKey).select(`${t.name}.*`).join(t.name,(e=>i.forEach(((t,s)=>{e.on(t,a[s])})))).then((e=>e.map((e=>t.build(e)))))}},exports.DbLoggedRepository=class LoggedRepository extends n{constructor(e=Logged,t=new s){super(e,t)}get=(e=new Logged)=>this.myContext().where({...e.key}).first().then((e=>n.anyOrError(e,{code:404,message:"Not found"}))).then(this.Entity.build);before=(e=new Date,t="asc")=>this.myContext().where("createdAt","<",e.toISOString()).select().orderBy("createdAt",t).then((e=>n.setOrEmpty(e,this.Entity.build)));after=(e=new Date,t="asc")=>this.myContext().where("createdAt",">",e.toISOString()).select().orderBy("createdAt",t).then((e=>n.setOrEmpty(e,this.Entity.build)));list=(e="asc")=>this.myContext().select().orderBy("createdAt",e).then((e=>n.setOrEmpty(e,this.Entity.build)));insert=(e=new Logged)=>this.myContext().insert({...e.entity,createdAt:(new Date).toISOString()},Object.keys(e.key)).then((t=>e.key=t[0])).then((()=>e));create=(e=new Logged)=>this.myContext().insert({...e.entity,createdAt:(new Date).toISOString()}).then((()=>e));update=()=>Promise.reject(new AppError({code:400,message:"Cannot update a logged object"}));delete=()=>Promise.reject(new AppError({code:400,message:"Cannot delete a logged object"}))},exports.DbRepository=n,exports.DbThingRepository=class ThingRepository extends n{constructor(e=Thing,t=new s){super(e,t)}getByName=(e="")=>this.myContext().where({name:e}).select().then((e=>n.setOrEmpty(e,this.Entity.build)))},exports.DbTracedRepository=class TracedRepository extends n{constructor(e=Traced,t=new s){super(e,t)}deceased=(e="asc")=>this.myContext().where({active:!1}).select().orderBy(["createdAt","updatedAt"],e).then((e=>n.setOrEmpty(e,this.Entity.build)));before=(e=new Date,t="asc")=>this.myContext().where("createdAt","<",e.toISOString()).where({active:!0}).select().orderBy(["createdAt","updatedAt"],t).then((e=>n.setOrEmpty(e,this.Entity.build)));after=(e=new Date,t="asc")=>this.myContext().where("createdAt",">",e.toISOString()).where({active:!0}).select().orderBy(["createdAt","updatedAt"],t).then((e=>n.setOrEmpty(e,this.Entity.build)));list=(e="asc")=>this.myContext().where({active:!0}).select().orderBy(["createdAt","updatedAt"],e).then((e=>n.setOrEmpty(e,this.Entity.build)));last=()=>this.myContext().where({active:!0}).first().orderBy("createdAt","desc").then((e=>n.anyOrError(e,{code:404,message:"Not found"})));first=()=>this.myContext().where({active:!0}).first().orderBy("createdAt","asc").then((e=>n.anyOrError(e,{code:404,message:"Not found"})));insert=(e=new Traced)=>this.myContext().insert({...e.entity,createdAt:(new Date).toISOString()},Object.keys(e.key)).then((t=>e.key=t[0])).then((()=>e));create=(e=new Traced)=>this.myContext().insert({...e.key,...e.entity,createdAt:(new Date).toISOString()}).then((()=>e));update=(e=new Traced)=>this.myContext().where(e.key).update({...e.entity,updatedAt:(new Date).toISOString()}).then((e=>e>0));delete=(e=new Traced)=>this.myContext().where(e.key).update({active:!1,updatedAt:(new Date).toISOString()}).then((e=>e>0))},exports.Handler=class Handler{#m;constructor({context:e=new s}){this.#m=e}get context(){return this.#m}handle(){}handleError({code:e,message:t}){return Promise.reject(new AppError({code:e,message:t}))}},exports.Linking=Linking,exports.Logged=Logged,exports.Model=Model,exports.Service=class Service{#m;constructor(e=new s){this.#m=e}get context(){return this.#m}handleError=(e,t)=>Promise.reject(new AppError({code:e,message:t}));handleFailure=e=>this.handleError({code:500,message:e.message})},exports.Thing=Thing,exports.Traced=Traced,exports.runWhenFalse=runWhenFalse,exports.runWhenTrue=(e=Promise.resolve(!0),t=async()=>{})=>e.then((async e=>{e&&await t()}));
1
+ import knex from 'knex';
2
+ import axios from 'axios';
3
+
4
+ var runWhenFalse = (
5
+ cond = Promise.resolve(true),
6
+ execute = async () => {},
7
+ )=>cond
8
+ .then(async isTrue=>{
9
+ if (!isTrue) await execute();
10
+ });
11
+
12
+ var runWhenTrue = (
13
+ cond = Promise.resolve(true),
14
+ execute = async () => {},
15
+ )=>cond
16
+ .then(async isTrue=>{
17
+ if (isTrue) await execute();
18
+ });
19
+
20
+ class Result {
21
+ #code
22
+ #message
23
+ #data
24
+
25
+ constructor({ code=0, message='', data={} }) {
26
+ this.#code = code;
27
+ this.#message = message;
28
+ this.#data = data;
29
+ }
30
+
31
+ get isError() {
32
+ return this.#code > 299
33
+ }
34
+
35
+ get error() {
36
+ return {
37
+ code: this.#code,
38
+ message: this.#message
39
+ }
40
+ }
41
+
42
+ get ok() {
43
+ return {
44
+ code: this.#code,
45
+ data: this.#data
46
+ }
47
+ }
48
+
49
+ sendError(res) {
50
+ res
51
+ .status(this.#code)
52
+ .send(this.#message);
53
+ }
54
+
55
+ sendOk(res) {
56
+ res
57
+ .status(this.#code)
58
+ .json(this.#data);
59
+ }
60
+ }
61
+
62
+ class Entity{
63
+ #key
64
+ #data
65
+
66
+ constructor(key={},data={}){
67
+ this.#data = data;
68
+ this.#key = key;
69
+ }
70
+
71
+ get key(){ return this.#key }
72
+ get data(){ return this.#data }
73
+
74
+ get $(){
75
+ return { ...this.#key, ...this.#data }
76
+ }
77
+
78
+ static migrations(){ return [] }
79
+
80
+ static structMe(db=knex()){
81
+ throw new Error('Abstract class cant be instantiated')
82
+ }
83
+
84
+ static build({ }){
85
+ throw new Error('Abstract class cant be instantiated')
86
+ }
87
+
88
+ static fromResult(result=new Result()){
89
+ if(result.isError) return Promise.reject(result)
90
+ }
91
+ }
92
+
93
+ class Model {
94
+ constructor({}) {
95
+
96
+ }
97
+
98
+ static fromEntity(entity = new Entity()) {
99
+ return new Model(entity.$)
100
+ }
101
+
102
+ validate(){}
103
+ }
104
+
105
+ class Linking{
106
+ #abscissa=new Entity()
107
+ #ordinate=new Entity()
108
+ #AbscissaEntity=Entity
109
+ #OrdinateEntity=Entity
110
+
111
+
112
+ get Abscissa(){
113
+ return this.#AbscissaEntity
114
+ }
115
+
116
+ get Ordinate(){
117
+ return this.#OrdinateEntity
118
+ }
119
+
120
+ constructor(
121
+ AbscissaEntity=Entity,
122
+ OrdinateEntity=Entity,
123
+ {
124
+ abscissa=new AbscissaEntity(),
125
+ ordinate=new OrdinateEntity()
126
+ })
127
+ {
128
+ this.#AbscissaEntity = AbscissaEntity;
129
+ this.#OrdinateEntity = OrdinateEntity;
130
+
131
+ this.#abscissa = abscissa;
132
+ this.#ordinate = ordinate;
133
+ }
134
+
135
+ static build=({
136
+ AbscissaEntity=Entity,
137
+ OrdinateEntity=Entity,
138
+ abscissa=new Entity(),
139
+ ordinate=new Entity()
140
+ })=>new Linking(AbscissaEntity,OrdinateEntity,{abscissa,ordinate})
141
+
142
+ static structMe(
143
+ db=knex(),
144
+ abscissa=Entity,
145
+ ordinate=Entity,
146
+ schema=(t)=>{}
147
+ ){
148
+ const tableName = `${abscissa.name}${ordinate.name}`;
149
+
150
+ return runWhenFalse(
151
+ db.schema.hasTable(tableName),
152
+ () => Promise.resolve(
153
+ db.schema.createTable(tableName, table=>{ schema(table); })
154
+ )
155
+ )
156
+ }
157
+
158
+
159
+ get abscissaKey(){
160
+ return { idAbscissa: this.#abscissa.key }
161
+ }
162
+
163
+ get ordinateKey(){
164
+ return { idOrdinate: this.#ordinate.key }
165
+ }
166
+
167
+ get $(){
168
+ return {
169
+ ...this.abscissaKey,
170
+ ...this.ordinateKey
171
+ }
172
+ }
173
+
174
+ get entity(){}
175
+
176
+ get abscissa(){ return this.#abscissa }
177
+ set abscissa(value = this.Abscissa.build()){ this.#abscissa = value; }
178
+
179
+ get ordinate(){ return this.#ordinate }
180
+ set ordinate(value = this.Ordinate.build()){ this.ordinate = value; }
181
+
182
+ }
183
+
184
+ class Traceable extends Entity{
185
+ constructor({
186
+ key={},
187
+ struct={},
188
+ createdAt=new Date()
189
+ }){
190
+ super(key,{...struct,createdAt});
191
+ }
192
+
193
+ get createdAt(){ return this.data.createdAt }
194
+
195
+ static structMe(
196
+ db=knex(),
197
+ model=Traceable,
198
+ schema=(t)=>{}
199
+ ){
200
+ return runWhenFalse(
201
+ db.schema.hasTable(model.name),
202
+ async ()=>Promise.resolve(
203
+ db.schema.createTable(
204
+ model.name,
205
+ table=>{
206
+ schema(table);
207
+
208
+ table.dateTime('createdAt')
209
+ .notNullable()
210
+ .defaultTo(db.fn.now());
211
+ }
212
+ )
213
+ )
214
+ )
215
+ }
216
+ }
217
+
218
+ class Status extends Entity{
219
+ static build=({ id=1,description='' })=>new Status({id,description})
220
+
221
+ static structMe(
222
+ db=knex(),
223
+ model=Status,
224
+ schema=(t)=>{}
225
+ ){
226
+ return runWhenFalse(
227
+ db.schema.hasTable(model.name),
228
+ ()=>Promise.resolve(
229
+ db.schema.createTable(
230
+ model.name,
231
+ table=>{
232
+ table.increments();
233
+
234
+ table
235
+ .string('status',50)
236
+ .notNullable()
237
+ .unique();
238
+
239
+ schema(table);
240
+ }
241
+ )
242
+ )
243
+ )
244
+ }
245
+
246
+ constructor({ id=1, description=''}){
247
+ super({ id }, { status:description });
248
+ }
249
+
250
+ get description(){ return this.data.status }
251
+ set description( value='' ){ this.data.status = value;}
252
+ }
253
+
254
+ class Thing extends Entity{
255
+ constructor({
256
+ key={},
257
+ name='',
258
+ struct={}
259
+ }){
260
+ super(key,{ name, ...struct });
261
+ }
262
+
263
+ get name(){ return this.data.name }
264
+ set name(value=''){ this.data.name = value; }
265
+
266
+ static structMe(
267
+ db=knex(),
268
+ thing=Thing,
269
+ size = 255,
270
+ schema=(t)=>{}
271
+ ){
272
+ return runWhenFalse(
273
+ db.schema.hasTable(thing.name),
274
+ ()=>Promise.resolve(
275
+ db.schema.createTable(
276
+ thing.name,
277
+ table=>{
278
+ schema(table);
279
+
280
+ table.string('name',size)
281
+ .notNullable();
282
+ }
283
+ )
284
+ )
285
+ )
286
+ }
287
+ }
288
+
289
+ class Changeable extends Entity{
290
+ constructor({
291
+ key={},
292
+ struct = {},
293
+ createdAt=new Date(),
294
+ updatedAt=new Date()|undefined,
295
+ active=true
296
+ }){
297
+ super(
298
+ key,
299
+ {
300
+ ...struct,
301
+ createdAt,
302
+ updatedAt,
303
+ active
304
+ }
305
+ );
306
+ }
307
+
308
+ get createdAt(){ return this.data.createdAt }
309
+ get updatedAt(){ return this.data.updatedAt }
310
+ get active(){ return this.data.active }
311
+
312
+ static structMe(
313
+ db=knex(),
314
+ model=Changeable,
315
+ schema=(t)=>{}
316
+ ){
317
+ return runWhenFalse(
318
+ db.schema.hasTable(model.name),
319
+ ()=>Promise.resolve(
320
+ db.schema.createTable(model.name,table=>{
321
+ schema(table);
322
+
323
+ table.dateTime('createdAt')
324
+ .notNullable()
325
+ .defaultTo(db.fn.now());
326
+
327
+ table.dateTime('updatedAt')
328
+ .nullable();
329
+
330
+ table.boolean('active')
331
+ .defaultTo(true);
332
+ })
333
+ )
334
+ )
335
+ }
336
+ }
337
+
338
+ class Migration{
339
+ #db
340
+ constructor(db = knex()) {
341
+ this.#db = db;
342
+ }
343
+
344
+ #get = ({ name='' })=>this
345
+ .#db('migration')
346
+ .where({ name })
347
+ .first('iteration')
348
+ .then(result=>!!result?result:{ iteration:0 })
349
+
350
+
351
+ #update = ({ iteration=0,name='' })=>this
352
+ .#db('migration')
353
+ .where({ name })
354
+ .update({ iteration })
355
+
356
+ async runMigrations({ entity = Entity, migrations=[async ()=>{}] }){
357
+ const name = entity.name;
358
+
359
+ const { iteration } = await this.#get(name);
360
+
361
+ const listSize = migrations.length;
362
+
363
+ if (iteration >= listSize) return
364
+
365
+ for (let index = iteration; index < listSize; index++) {
366
+ await migrations[index]();
367
+ }
368
+
369
+ await this.#update({ iteration:listSize,name });
370
+ }
371
+
372
+ static structMe(db=knex()){
373
+ return runWhenFalse(
374
+ db.schema.hasTable('migration'),
375
+ ()=>Promise.resolve(
376
+ db.schema.createTable('migration', table => {
377
+ table.string('name',100)
378
+ .notNullable()
379
+ .unique();
380
+
381
+ table.integer('iteration')
382
+ .notNullable()
383
+ .unsigned()
384
+ .defaultTo(0);
385
+ })
386
+ )
387
+ )
388
+ }
389
+ }
390
+
391
+ let Context$2 = class Context{
392
+ #db
393
+
394
+ constructor(database=knex()){
395
+ this.#db= database;
396
+ }
397
+
398
+ get db(){return this.#db}
399
+
400
+ unitOfWork(...repositories){
401
+ return this.#db.transaction().then(trx=>{
402
+ repositories.forEach(repo=>repo.context = trx);
403
+
404
+ const clean =()=>repositories.forEach(repo=>
405
+ repo.resetContext()
406
+ );
407
+
408
+ return {
409
+ done:()=>trx.commit().then(clean),
410
+ rollback:()=>trx.rollback().then(clean)
411
+ }
412
+ })
413
+ }
414
+
415
+ static instance(database=knex()){ return new Context(database) }
416
+
417
+ async terraform(models=[Model]){
418
+ await Migration.structMe(this.#db);
419
+
420
+ const migration = new Migration(this.#db);
421
+
422
+ const promises = models.map(model=>
423
+ model.structMe(this.#db)
424
+ .then(()=>migration
425
+ .runMigrations({ entity: model, migrations: model.migrations(this.#db) })
426
+ )
427
+ );
428
+
429
+ await Promise.all(promises);
430
+ }
431
+ };
432
+
433
+ let Repository$1 = class Repository{
434
+ #name='';
435
+
436
+ myContext
437
+
438
+ constructor(entity=Entity,context=new Context$2())
439
+ {
440
+ this.#name = entity.name;
441
+
442
+ this.myContext=()=>context.db(this.#name);
443
+
444
+ this.resetContext=()=>{
445
+ this.myContext=()=>context.db(this.#name);
446
+ };
447
+ }
448
+
449
+ set context(value=knex()){ this.myContext=()=>value(this.#name); }
450
+
451
+ create = (entity = new Entity())=>
452
+ this.myContext()
453
+ .insert(entity.$)
454
+ .then(()=>new Result({data:entity}))
455
+ .catch(err=>Promise.reject( new Result({code:500,message:err}) ))
456
+
457
+ insert = (entity = new Entity())=>
458
+ this.myContext()
459
+ .insert(entity.data,Object.keys(entity.key))
460
+ .then(ids=>new Result({
461
+ data:{ key: ids[0] }
462
+ }))
463
+ .catch(err=>Promise.reject(
464
+ new Result({code:500,message:err})
465
+ ))
466
+
467
+ update = (entity = new Entity())=>
468
+ this.myContext()
469
+ .where(entity.key)
470
+ .update(entity.data)
471
+ .then(affected=>new Result({ data:affected }))
472
+ .catch(err=>Promise.reject(
473
+ new Result({code:500,message:err})
474
+ ))
475
+
476
+ delete = (entity = new Entity())=>
477
+ this.myContext()
478
+ .where(entity.key)
479
+ .del()
480
+ .then(affected=>new Result({ data:affected }))
481
+ .catch(err=>Promise.reject(
482
+ new Result({code:500,message:err})
483
+ ))
484
+
485
+ get = (entity = new Entity())=>
486
+ this.myContext()
487
+ .where(entity.key)
488
+ .first()
489
+ .then(model=>{
490
+ if (!!model) return new Result({ data:model })
491
+
492
+ const error = new Result({code:404,message:'Not found'});
493
+
494
+ return Promise.reject(error)
495
+ })
496
+
497
+ list = ()=>
498
+ this.myContext()
499
+ .select()
500
+ .then(models=>new Result({ data:models }))
501
+ };
502
+
503
+ class ChangeableRepository extends Repository$1{
504
+ constructor(entity = Changeable,context=new Context$2()){
505
+ super(entity,context);
506
+ }
507
+
508
+ deceased = (order = 'asc') =>
509
+ this.myContext()
510
+ .where({active:false})
511
+ .select()
512
+ .orderBy(['createdAt','updatedAt'],order)
513
+ .then(result => new Result({data:result}))
514
+
515
+ before = (date = new Date(), order = 'asc') =>
516
+ this.myContext()
517
+ .where('createdAt','<',date.toISOString())
518
+ .where({active:true})
519
+ .select()
520
+ .orderBy(['createdAt','updatedAt'],order)
521
+ .then(result => new Result({data:result}))
522
+
523
+ after = (date=new Date(), order = 'asc') =>
524
+ this.myContext()
525
+ .where('createdAt','>',date.toISOString())
526
+ .where({active:true})
527
+ .select()
528
+ .orderBy(['createdAt','updatedAt'],order)
529
+ .then(result => new Result({data:result}))
530
+
531
+ list = (order = 'asc') =>
532
+ this.myContext()
533
+ .where({active:true})
534
+ .select()
535
+ .orderBy(['createdAt','updatedAt'],order)
536
+ .then(result => new Result({data:result}))
537
+
538
+ last = () =>
539
+ this.myContext()
540
+ .where({active:true})
541
+ .first()
542
+ .orderBy('createdAt',"desc")
543
+ .then(result => {
544
+ if (!!result) return result
545
+
546
+ const error = new Result({code:404,message:'Not found'});
547
+
548
+ return Promise.reject(error)
549
+ })
550
+
551
+ first = () =>
552
+ this.myContext()
553
+ .where({active:true})
554
+ .first()
555
+ .orderBy('createdAt',"asc")
556
+ .then(result => {
557
+ if (!!result) return result
558
+
559
+ const error = new Result({code:404,message:'Not found'});
560
+
561
+ return Promise.reject(error)
562
+ })
563
+ }
564
+
565
+ class TraceableRepository extends Repository$1{
566
+ constructor(entity=Traceable,context=new Context$2()){
567
+ super(entity,context);
568
+ }
569
+
570
+ get = (traceable = new Traceable()) =>
571
+ this.myContext()
572
+ .where(traceable.key)
573
+ .first()
574
+ .then(model => {
575
+ if (!!model) return model
576
+
577
+ const error = new Result({code:404,message:'Not found'});
578
+
579
+ return Promise.reject(error)
580
+ })
581
+
582
+ before = (date = new Date(), order = 'asc') =>
583
+ this.myContext()
584
+ .where('createdAt','<',date.toISOString())
585
+ .select()
586
+ .orderBy('createdAt',order)
587
+ .then(result => new Result({data:result}))
588
+
589
+ after = (date = new Date(), order = 'asc') =>
590
+ this.myContext()
591
+ .where('createdAt','>',date.toISOString())
592
+ .select()
593
+ .orderBy('createdAt',order)
594
+ .then(result => new Result({data:result}))
595
+
596
+ list = (order='asc') =>
597
+ this.myContext()
598
+ .select()
599
+ .orderBy('createdAt',order)
600
+ .then(result => new Result({data:result}))
601
+
602
+ update = () => Promise.reject(new Result({code:400,message:'Cannot update a logged object'}))
603
+
604
+ delete = () => Promise.reject(new Result({code:400,message:'Cannot delete a logged object'}))
605
+
606
+ }
607
+
608
+ class ThingRepository extends Repository$1{
609
+ constructor(entity = Thing,context=new Context()){
610
+ super(entity,context);
611
+ }
612
+
613
+ getByName = (name='') =>
614
+ this.myContext()
615
+ .where({name})
616
+ .first()
617
+ .then(result=>!!result
618
+ ?new Result({data:result})
619
+ :new Result({code:404,message:'Not found'})
620
+ )
621
+ .catch(err=>Promise.reject(new Result({code:500,message:err})))
622
+ }
623
+
624
+ class DbLinked {
625
+ #linking
626
+ #name=''
627
+
628
+ myContext
629
+
630
+ constructor(link=Linking,context=new Context$2){
631
+ this.#name = link.name;
632
+ this.myContext = () => context.db(this.#name);
633
+ this.#linking = link;
634
+ }
635
+
636
+ createBatch = (linkings=[ new Linking() ])=>
637
+ this.myContext()
638
+ .insert(
639
+ linkings.map(l => (
640
+ {
641
+ ...l.key,
642
+ ...l.entity
643
+ })
644
+ )
645
+ )
646
+ .then(()=>new Result({data:linkings}))
647
+ .catch(err=>Promise.reject(new Result({code:500,message:err})));
648
+
649
+ create = (linked=new Linking())=>
650
+ this.myContext()
651
+ .insert({
652
+ ...linked.key,
653
+ ...linked.entity
654
+ })
655
+ .then(()=>new Result({data:linked}))
656
+ .catch(err=>Promise.reject(new Result({code:500,message:err})));
657
+
658
+
659
+ insertOrdinatesByAbscissa = ({ abscissa=new Entity(),ordinates=[new Entity()] })=>{
660
+ const batch = ordinates
661
+ .map(o=>this.#linking
662
+ .build({abscissa,ordinate:o})
663
+ );
664
+
665
+ return this.createBatch(batch);
666
+ }
667
+
668
+ insertAbscissasByOrdinate = ({ ordinate=new Entity(),abscissas=[new Entity()] })=>{
669
+ const batch = abscissas
670
+ .map(a=>this.#linking
671
+ .build({abscissa:a,ordinate})
672
+ );
673
+
674
+ return this.createBatch(batch)
675
+ }
676
+
677
+ delete = (linked=new Linking())=>
678
+ this.myContext()
679
+ .where(linked.key)
680
+ .del()
681
+ .then(affected=>new Result({data:affected}))
682
+ .catch(err=>Promise.reject(new Result({code:500,message:err})))
683
+
684
+
685
+ getAbscissasByOrdinate(linked=new Linking()){
686
+ const Abscissa = linked.Abscissa;
687
+ const Ordinate = linked.Ordinate;
688
+ const keys = Object.keys(linked.abscissaKey);
689
+ const abscissaKey = Object.keys(linked.abscissa.key);
690
+
691
+ const fields = keys.map(key=>`${Abscissa.name}${Ordinate.name}.${key}`);
692
+ const abscissas = abscissaKey.map(key=>`${Abscissa.name}.${key}`);
693
+
694
+ return this.myContext()
695
+ .where(linked.ordinateKey)
696
+ .select(`${Abscissa.name}.*`)
697
+ .join(Abscissa.name,clause=>
698
+ fields.forEach((field,i)=>{
699
+ clause.on(field,abscissas[i]);
700
+ })
701
+ )
702
+ .then(result=>new Result({data:result}))
703
+ }
704
+
705
+ getOrdinatesByAbscissa(linked=new Linking()){
706
+ const Ordinate = linked.Ordinate;
707
+ const Abscissa = linked.Abscissa;
708
+ const keys = Object.keys(linked.ordinateKey);
709
+ const ordinateKeys = Object.keys(linked.ordinate.key);
710
+
711
+ const fields = keys.map(key=>`${Abscissa.name}${Ordinate.name}.${key}`);
712
+ const ordinates = ordinateKeys.map(key=>`${Ordinate.name}.${key}`);
713
+
714
+ return this.myContext()
715
+ .where(linked.abscissaKey)
716
+ .select(`${Ordinate.name}.*`)
717
+ .join(Ordinate.name,clause=>
718
+ fields.forEach((field,i)=>{
719
+ clause.on(field,ordinates[i]);
720
+ })
721
+ )
722
+ .then(result=>new Result({data:result}))
723
+ }
724
+
725
+ }
726
+
727
+ const DbRepository = Repository$1;
728
+ const DbContext = Context$2;
729
+ const DbChangeableRepository = ChangeableRepository;
730
+ const DbTraceableRepository = TraceableRepository;
731
+ const DbThingRepository = ThingRepository;
732
+
733
+ class Service {
734
+ #context
735
+ constructor(context=new DbContext()){
736
+ this.#context = context;
737
+ }
738
+
739
+ get context(){return this.#context}
740
+
741
+ handleError = (code,message)=>Promise.reject(new Result({code,message}))
742
+ handleFailure = (err)=> this.handleError({code:500,message:err.message})
743
+ }
744
+
745
+ class Handler {
746
+ #context
747
+ constructor({ context = new DbContext }) {
748
+ this.#context = context;
749
+ }
750
+
751
+ get context(){
752
+ return this.#context
753
+ }
754
+
755
+ handle(){}
756
+ handleError({ code, message }) {
757
+ return Promise.reject(new Result({ code, message }));
758
+ }
759
+ }
760
+
761
+ let Context$1 = class Context{
762
+ #http
763
+
764
+ constructor(config=axios.create({})){
765
+ this.#http = config;
766
+ }
767
+
768
+ get http(){ return this.#http }
769
+ };
770
+
771
+ class Repository {
772
+ #context
773
+
774
+ constructor(entity=Entity,context=new Context$1()){
775
+ this.#context = context;
776
+ }
777
+
778
+ static queryString(param={}){
779
+ return '?' + Object.entries(param)
780
+ .map(([k,v])=>`${k}=${v}`)
781
+ .join('&')
782
+ }
783
+
784
+ get context(){ return this.#context }
785
+ }
786
+
787
+ class RestfulRepository extends Repository{
788
+ constructor(entity = Entity,context=new Context$1()){
789
+ super(entity,context);
790
+ }
791
+
792
+ #keysAsParams(route='',key={}){
793
+ const params = Object.keys(key);
794
+
795
+ params.forEach(param=>
796
+ route = route.replace(`:${param}`,key[param])
797
+ );
798
+
799
+ return route
800
+ }
801
+
802
+ #httpGet=(route='',query={}|undefined)=>this.context
803
+ .http
804
+ .get(!! query ? `${route}${Repository.queryString(query)}` : route)
805
+ .then(value=>{
806
+ value.status === 200
807
+ ? new Result({data:value.data})
808
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
809
+ })
810
+
811
+ get=(route='',query={}|undefined)=>this.#httpGet(route,query)
812
+ .then(value=>{
813
+ value.status === 200
814
+ ? new Result({data:value.data})
815
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
816
+ })
817
+
818
+ list=(route='',query={}|undefined)=>this.#httpGet(route,query)
819
+ .then(value=>{
820
+ value.status === 200
821
+ ? new Result({data:value.data})
822
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
823
+ })
824
+
825
+ create=(route='',entity=new Entity())=>this.context
826
+ .http
827
+ .post(route,entity.data)
828
+ .then(value=>{
829
+ value.status === 201
830
+ ? new Result({data:value.data})
831
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
832
+ })
833
+
834
+ update=(route='',entity=new Entity())=>{
835
+ const url = this.#keysAsParams(route,entity.key);
836
+
837
+ return this.context
838
+ .http
839
+ .put(url,model.entity)
840
+ .then(value=>{
841
+ value.status === 200
842
+ ? new Result({data:value.data})
843
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
844
+ })
845
+ }
846
+
847
+ change=(route='',entity=new Entity())=>{
848
+ const url = this.#keysAsParams(route,entity.key);
849
+
850
+ return this.context
851
+ .http
852
+ .patch(url,model.entity)
853
+ .then(value=>{
854
+ value.status === 200
855
+ ? new Result({data:value.data})
856
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
857
+ })
858
+ }
859
+
860
+ delete=(id,entity = new Entity())=>{
861
+ const url = this.#keysAsParams(route,entity.key);
862
+
863
+ return this.context
864
+ .http
865
+ .delete(url)
866
+ .then(value=>{
867
+ value.status === 200
868
+ ? new Result({data:value.data})
869
+ : Promise.reject(new Result({code:value.status, message:value.statusText}));
870
+ })
871
+ }
872
+ }
873
+
874
+ const ApiRepository = Repository;
875
+ const ApiContext = Context$1;
876
+ const ApiRestfulRepository = RestfulRepository;
877
+
878
+ export { ApiContext, ApiRepository, ApiRestfulRepository, Changeable, DbChangeableRepository, DbContext, DbLinked, DbRepository, DbThingRepository, DbTraceableRepository, Entity, Handler, Linking, Migration, Model, Result, Service, Status, Thing, Traceable, runWhenFalse, runWhenTrue };