nesoi 3.3.7 → 3.3.9

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.
Files changed (31) hide show
  1. package/lib/bundler/distributed/stages/6_dump_cli_stage.js +0 -1
  2. package/lib/bundler/monolyth/stages/6_dump_cli_stage.js +0 -1
  3. package/lib/elements/blocks/resource/resource.js +9 -0
  4. package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.js +19 -16
  5. package/lib/elements/entities/bucket/adapters/memory.nql.js +2 -4
  6. package/lib/elements/entities/bucket/bucket.js +10 -6
  7. package/lib/elements/entities/bucket/bucket.schema.d.ts +1 -1
  8. package/lib/elements/entities/bucket/graph/bucket_graph.js +27 -28
  9. package/lib/elements/entities/bucket/model/bucket_model.d.ts +4 -1
  10. package/lib/elements/entities/bucket/model/bucket_model.js +22 -2
  11. package/lib/engine/app/app.config.d.ts +7 -1
  12. package/lib/engine/app/app.config.js +20 -0
  13. package/lib/engine/app/app.d.ts +3 -1
  14. package/lib/engine/app/inline.app.d.ts +8 -2
  15. package/lib/engine/app/inline.app.js +33 -34
  16. package/lib/engine/app/native/browser.app.d.ts +1 -0
  17. package/lib/engine/app/native/browser.app.js +1 -1
  18. package/lib/engine/app/native/distributed_node.app.js +1 -6
  19. package/lib/engine/app/native/monolyth.app.d.ts +1 -0
  20. package/lib/engine/app/native/monolyth.app.js +1 -1
  21. package/lib/engine/app/service.d.ts +4 -10
  22. package/lib/engine/app/service.js +1 -3
  23. package/lib/engine/cli/script.d.ts +97 -0
  24. package/lib/engine/cli/script.js +422 -0
  25. package/lib/engine/transaction/nodes/bucket_query.trx_node.js +1 -1
  26. package/lib/engine/util/dotenv.d.ts +5 -6
  27. package/lib/engine/util/dotenv.js +14 -12
  28. package/package.json +1 -1
  29. package/tsconfig.build.tsbuildinfo +1 -1
  30. package/tools/dotenv.d.ts +0 -1
  31. package/tools/dotenv.js +0 -4
@@ -20,7 +20,6 @@
20
20
  // Log.info('compiler', 'monolyth', 'Dumping cli.js file to build/bin folder...')
21
21
  // const { dirs } = this.monolyth;
22
22
  // let str = '';
23
- // str += 'require("nesoi/tools/dotenv");\n';
24
23
  // str += 'const app = require(\'../app\').default\n';
25
24
  // str += 'const { Log } = require(\'nesoi/lib/engine/util/log\');\n';
26
25
  // str += 'Log.level = \'debug\';\n'
@@ -53,7 +53,6 @@ class DumpCLIStage {
53
53
  log_1.Log.info('compiler', 'monolyth', 'Dumping cli.js file to build/bin folder...');
54
54
  const { dirs } = this.bundler;
55
55
  let str = '';
56
- str += 'require("nesoi/tools/dotenv");\n';
57
56
  str += 'const app = require(\'../app\').default\n';
58
57
  str += 'const { Log } = require(\'nesoi/lib/engine/util/log\');\n';
59
58
  str += 'Log.level = \'debug\';\n';
@@ -4,6 +4,8 @@ exports.Resource = void 0;
4
4
  const block_1 = require("../block");
5
5
  const trx_node_1 = require("../../../engine/transaction/trx_node");
6
6
  const error_1 = require("../../../engine/data/error");
7
+ const dependency_1 = require("../../../engine/dependency");
8
+ const daemon_1 = require("../../../engine/daemon");
7
9
  /**
8
10
  * @category Elements
9
11
  * @subcategory Block
@@ -83,6 +85,13 @@ class Resource extends block_1.Block {
83
85
  }
84
86
  static query($) {
85
87
  const scope = $.job.scope;
88
+ // Default sorting
89
+ if (!('#sort' in $.msg.query) || !$.msg.query['#sort']?.length) {
90
+ const module = trx_node_1.TrxNode.getModule($.trx);
91
+ const tag = dependency_1.Tag.fromNameOrShort(scope.module, 'bucket', scope.bucket);
92
+ const { meta } = daemon_1.Daemon.getBucketMetadata(module.daemon, tag);
93
+ $.msg.query['#sort'] = `${meta.updated_at}@desc`;
94
+ }
86
95
  return $.trx.bucket(scope.bucket)
87
96
  .viewQuery($.msg.query, $.msg.view).page({
88
97
  page: $.msg.page,
@@ -38,23 +38,26 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
38
38
  }
39
39
  /* Read operations */
40
40
  index(trx) {
41
- const objs = Object.values(this.data);
41
+ const objs = Object.values(this.data).map(obj => this.model.copy(obj, { date: 'parse', datetime: 'parse' }));
42
42
  return Promise.resolve(objs);
43
43
  }
44
44
  get(trx, id) {
45
- return Promise.resolve(this.data[id]);
45
+ if (!(id in this.data))
46
+ return Promise.resolve(undefined);
47
+ const output = this.model.copy(this.data[id], { date: 'parse', datetime: 'parse' });
48
+ return Promise.resolve(output);
46
49
  }
47
50
  /* Write Operations */
48
51
  async create(trx, obj) {
49
- const input = this.model.copy(obj);
52
+ const input = this.model.copy(obj, { date: 'dump', datetime: 'dump' });
50
53
  if (!input.id) {
51
- const lastId = (await this.index(trx))
54
+ const lastId = Object.values(this.data)
52
55
  .map((_obj) => parseInt(_obj.id))
53
56
  .sort((a, b) => b - a)[0] || 0;
54
57
  input.id = lastId + 1;
55
58
  }
56
59
  this.data[input.id] = input;
57
- const output = this.model.copy(input);
60
+ const output = this.model.copy(input, { date: 'parse', datetime: 'parse' });
58
61
  return Promise.resolve(output);
59
62
  }
60
63
  async createMany(trx, objs) {
@@ -68,9 +71,9 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
68
71
  if (!obj.id || !this.data[obj.id]) {
69
72
  throw new Error(`Object with id ${obj.id} not found for replace`);
70
73
  }
71
- const input = this.model.copy(obj);
74
+ const input = this.model.copy(obj, { date: 'dump', datetime: 'dump' });
72
75
  this.data[input.id] = input;
73
- const output = this.model.copy(input);
76
+ const output = this.model.copy(input, { date: 'parse', datetime: 'parse' });
74
77
  return Promise.resolve(output);
75
78
  }
76
79
  async replaceMany(trx, objs) {
@@ -86,7 +89,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
86
89
  throw new Error(`Object with id ${obj.id} not found for patch`);
87
90
  }
88
91
  const data = this.data[obj.id];
89
- const input = this.model.copy(obj);
92
+ const input = this.model.copy(obj, { date: 'dump', datetime: 'dump' });
90
93
  for (const key in input) {
91
94
  if (input[key] === null) {
92
95
  delete data[key];
@@ -95,7 +98,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
95
98
  data[key] = input[key];
96
99
  }
97
100
  }
98
- const output = this.model.copy(data);
101
+ const output = this.model.copy(data, { date: 'parse', datetime: 'parse' });
99
102
  return Promise.resolve(output);
100
103
  }
101
104
  async patchMany(trx, objs) {
@@ -107,30 +110,30 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
107
110
  return Promise.resolve(out);
108
111
  }
109
112
  async put(trx, obj) {
110
- const input = this.model.copy(obj);
113
+ const input = this.model.copy(obj, { date: 'dump', datetime: 'dump' });
111
114
  if (!input.id) {
112
- const lastId = (await this.index(trx))
115
+ const lastId = Object.values(this.data)
113
116
  .map((_obj) => parseInt(_obj.id))
114
117
  .sort((a, b) => b - a)[0] || 0;
115
118
  input.id = lastId + 1;
116
119
  }
117
120
  this.data[input.id] = input;
118
- const output = this.model.copy(input);
121
+ const output = this.model.copy(input, { date: 'parse', datetime: 'parse' });
119
122
  return Promise.resolve(output);
120
123
  }
121
124
  async putMany(trx, objs) {
122
- const lastId = (await this.index(trx))
125
+ const lastId = Object.values(this.data)
123
126
  .map((obj) => parseInt(obj.id))
124
127
  .sort((a, b) => b - a)[0] || 0;
125
128
  let id = lastId + 1;
126
129
  const out = [];
127
130
  for (const obj of objs) {
128
- const input = this.model.copy(obj);
131
+ const input = this.model.copy(obj, { date: 'dump', datetime: 'dump' });
129
132
  if (!input.id) {
130
133
  input.id = id;
131
134
  }
132
135
  this.data[input.id] = input;
133
- const output = this.model.copy(input);
136
+ const output = this.model.copy(input, { date: 'parse', datetime: 'parse' });
134
137
  out.push(output);
135
138
  id++;
136
139
  }
@@ -200,7 +203,7 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
200
203
  // 2. If hash changed, return a reset sync with all objects
201
204
  if (hash !== lastHash) {
202
205
  let updateEpoch = 0;
203
- const sync = (await this.index(trx))
206
+ const sync = Object.values(this.data)
204
207
  .map(obj => {
205
208
  const epoch = this.getUpdateEpoch(obj);
206
209
  if (epoch > updateEpoch) {
@@ -28,10 +28,8 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
28
28
  response = await this.filter(part, data, params, param_templates);
29
29
  }
30
30
  let output = Object.values(response);
31
- if (part.union.sort) {
32
- const sort = part.union.sort.length
33
- ? part.union.sort
34
- : [{ key: this.adapter.config.meta.updated_at, dir: 'desc' }];
31
+ if (part.union.sort?.length) {
32
+ const sort = part.union.sort;
35
33
  output.sort((a, b) => {
36
34
  for (let i = 0; i < sort.length; i++) {
37
35
  const s = sort[i];
@@ -180,7 +180,7 @@ class Bucket {
180
180
  throw error_1.NesoiError.Bucket.InvalidId({ bucket: this.schema.alias, id });
181
181
  }
182
182
  // Read object
183
- const obj = await this.readOne(trx, id);
183
+ const obj = await this.readOne(trx, id, options);
184
184
  // Empty response
185
185
  if (!obj) {
186
186
  const schema = this.schema.graph.links[link];
@@ -217,7 +217,7 @@ class Bucket {
217
217
  // Read object
218
218
  const objs = await this.query(trx, {
219
219
  'id in': ids
220
- }).then(res => res.data);
220
+ }, undefined, undefined, options).then(res => res.data);
221
221
  // Empty response
222
222
  if (!objs.length) {
223
223
  const schema = this.schema.graph.links[link];
@@ -251,7 +251,7 @@ class Bucket {
251
251
  throw error_1.NesoiError.Bucket.InvalidId({ bucket: this.schema.alias, id });
252
252
  }
253
253
  // Read object
254
- const obj = await this.readOne(trx, id);
254
+ const obj = await this.readOne(trx, id, options);
255
255
  // Empty response
256
256
  if (!obj) {
257
257
  const schema = this.schema.graph.links[link];
@@ -283,7 +283,7 @@ class Bucket {
283
283
  async hasLink(trx, id, link, options) {
284
284
  log_1.Log.debug('bucket', this.schema.name, `Has Link, id=${id} l=${link}`);
285
285
  // Read Object
286
- const obj = await this.readOne(trx, id);
286
+ const obj = await this.readOne(trx, id, options);
287
287
  if (!obj) {
288
288
  return undefined;
289
289
  }
@@ -599,10 +599,12 @@ class Bucket {
599
599
  // If safe, avoid reading the object again inside readLink.
600
600
  // Instead, use graph's readLink which takes the object.
601
601
  ? await this.graph.readLink(trx, result.data[0], { name: link.name, index: [] }, {
602
+ no_tenancy: options?.no_tenancy,
602
603
  silent: true
603
604
  })
604
605
  // If unsafe, read the link base by id.
605
606
  : await this.readLink(trx, id, link.name, {
607
+ no_tenancy: options?.no_tenancy,
606
608
  silent: true
607
609
  });
608
610
  if (!linked)
@@ -655,7 +657,7 @@ class Bucket {
655
657
  if (link.keyOwner !== 'other')
656
658
  continue;
657
659
  for (const id of ids) {
658
- const linked = await this.readLink(trx, id, link.name, { silent: true });
660
+ const linked = await this.readLink(trx, id, link.name, { no_tenancy: options?.no_tenancy, silent: true });
659
661
  if (!linked)
660
662
  continue;
661
663
  if (link.many) {
@@ -678,7 +680,7 @@ class Bucket {
678
680
  if (link.keyOwner !== 'self')
679
681
  continue;
680
682
  for (const id of ids) {
681
- const linked = await this.readLink(trx, id, link.name, { silent: true });
683
+ const linked = await this.readLink(trx, id, link.name, { no_tenancy: options?.no_tenancy, silent: true });
682
684
  if (!linked)
683
685
  continue;
684
686
  if (link.many) {
@@ -807,6 +809,8 @@ class Bucket {
807
809
  if (field.type !== 'file')
808
810
  return;
809
811
  const file = tree_1.Tree.get(obj, field.path);
812
+ if (!file)
813
+ return;
810
814
  const remoteFile = await this.drive.upload(file);
811
815
  tree_1.Tree.set(obj, field.path, () => remoteFile);
812
816
  });
@@ -29,7 +29,7 @@ export declare class $Bucket {
29
29
  optional: boolean;
30
30
  }>;
31
31
  '#modelpath': {};
32
- '#querypath': Record<never, any>;
32
+ '#querypath': {};
33
33
  '#defaults': Record<string, any>;
34
34
  constructor(module: string, name: string, alias: string, model: $BucketModel, graph: $BucketGraph, views: $BucketViews, tenancy?: $BucketTenancy<any, any> | undefined, extendsFrom?: Tag | undefined);
35
35
  }
@@ -28,16 +28,7 @@ class BucketGraph {
28
28
  async readLink(trx, obj, link, options) {
29
29
  log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
30
30
  const schema = this.schema.links[link.name];
31
- // Make tenancy query
32
- const tenancy = (options?.no_tenancy)
33
- ? undefined
34
- : this.bucket.getTenancyQuery(trx);
35
- // Query
36
31
  const module = trx_node_1.TrxNode.getModule(trx);
37
- const query = {
38
- ...schema.query,
39
- '#and __tenancy__': tenancy
40
- };
41
32
  const page = {
42
33
  perPage: schema.many ? undefined : 1,
43
34
  };
@@ -51,7 +42,7 @@ class BucketGraph {
51
42
  let links;
52
43
  if (schema.bucket.module !== module.name) {
53
44
  links = await trx.bucket(schema.bucket.short)
54
- .query(query)
45
+ .query(schema.query)
55
46
  .params(params)
56
47
  .param_templates(param_templates)
57
48
  .page(page);
@@ -59,6 +50,14 @@ class BucketGraph {
59
50
  // Internal
60
51
  else {
61
52
  const otherBucket = dependency_1.Tag.element(schema.bucket, trx);
53
+ // Make tenancy query
54
+ const tenancy = (options?.no_tenancy)
55
+ ? undefined
56
+ : otherBucket.getTenancyQuery(trx);
57
+ const query = {
58
+ ...schema.query,
59
+ '#and __tenancy__': tenancy
60
+ };
62
61
  const adapter = otherBucket.cache || otherBucket.adapter;
63
62
  links = await adapter.query(trx, query, page, params, param_templates ? [param_templates] : undefined);
64
63
  }
@@ -93,16 +92,8 @@ class BucketGraph {
93
92
  async readManyLinks(trx, objs, link, options) {
94
93
  log_1.Log.trace('bucket', this.bucketName, `Read link ${link.name}`);
95
94
  const schema = this.schema.links[link.name];
96
- // Make tenancy query
97
- const tenancy = (options?.no_tenancy)
98
- ? undefined
99
- : this.bucket.getTenancyQuery(trx);
100
95
  // 1st Query
101
96
  const module = trx_node_1.TrxNode.getModule(trx);
102
- const query = {
103
- ...schema.query,
104
- '#and __tenancy__': tenancy
105
- };
106
97
  const params = objs.map(obj => ({ ...obj }));
107
98
  const param_templates = link.indexes.length
108
99
  ? link.indexes.map(index => Object.fromEntries(index
@@ -111,7 +102,7 @@ class BucketGraph {
111
102
  // External
112
103
  if (schema.bucket.module !== module.name) {
113
104
  const allLinks = await trx.bucket(schema.bucket.short)
114
- .query(query)
105
+ .query(schema.query)
115
106
  .params(params)
116
107
  .param_templates(param_templates)
117
108
  .all();
@@ -124,6 +115,14 @@ class BucketGraph {
124
115
  // Internal
125
116
  else {
126
117
  const otherBucket = dependency_1.Tag.element(schema.bucket, trx);
118
+ // Make tenancy query
119
+ const tenancy = (options?.no_tenancy)
120
+ ? undefined
121
+ : otherBucket.getTenancyQuery(trx);
122
+ const query = {
123
+ ...schema.query,
124
+ '#and __tenancy__': tenancy
125
+ };
127
126
  if (otherBucket.adapter instanceof memory_bucket_adapter_1.MemoryBucketAdapter) {
128
127
  tempAdapter = otherBucket.cache || otherBucket.adapter;
129
128
  }
@@ -211,16 +210,8 @@ class BucketGraph {
211
210
  async hasLink(trx, link, obj, options) {
212
211
  log_1.Log.trace('bucket', this.bucketName, `Has link ${link}`);
213
212
  const schema = this.schema.links[link];
214
- // Make tenancy query
215
- const tenancy = (options?.no_tenancy)
216
- ? undefined
217
- : this.bucket.getTenancyQuery(trx);
218
213
  // Query
219
214
  const module = trx_node_1.TrxNode.getModule(trx);
220
- const query = {
221
- ...schema.query,
222
- '#and__tenancy__': tenancy
223
- };
224
215
  const params = [{ ...obj }];
225
216
  const page = {
226
217
  perPage: 1,
@@ -229,13 +220,21 @@ class BucketGraph {
229
220
  let links;
230
221
  if (schema.bucket.module !== module.name) {
231
222
  links = await trx.bucket(schema.bucket.short)
232
- .query(query)
223
+ .query(schema.query)
233
224
  .params(params)
234
225
  .page(page);
235
226
  }
236
227
  // Internal
237
228
  else {
238
229
  const otherBucket = dependency_1.Tag.element(schema.bucket, trx);
230
+ // Make tenancy query
231
+ const tenancy = (options?.no_tenancy)
232
+ ? undefined
233
+ : otherBucket.getTenancyQuery(trx);
234
+ const query = {
235
+ ...schema.query,
236
+ '#and__tenancy__': tenancy
237
+ };
239
238
  const adapter = otherBucket.cache || otherBucket.adapter;
240
239
  links = await adapter.query(trx, query, page, params);
241
240
  }
@@ -9,5 +9,8 @@ export declare class BucketModel<M extends $Module, $ extends $Bucket> {
9
9
  private alias;
10
10
  private schema;
11
11
  constructor(bucket: $Bucket, config?: BucketAdapterConfig | undefined);
12
- copy<T extends Record<string, any>>(obj: T): T;
12
+ copy<T extends Record<string, any>>(obj: T, serial?: {
13
+ date?: 'parse' | 'dump';
14
+ datetime?: 'parse' | 'dump';
15
+ }): T;
13
16
  }
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BucketModel = void 0;
4
4
  const error_1 = require("../../../../engine/data/error");
5
+ const date_1 = require("../../../../engine/data/date");
6
+ const datetime_1 = require("../../../../engine/data/datetime");
5
7
  /**
6
8
  * @category Elements
7
9
  * @subcategory Entity
@@ -12,7 +14,7 @@ class BucketModel {
12
14
  this.alias = bucket.alias;
13
15
  this.schema = bucket.model;
14
16
  }
15
- copy(obj) {
17
+ copy(obj, serial) {
16
18
  const meta = this.config?.meta || {
17
19
  created_at: 'created_at',
18
20
  created_by: 'created_by',
@@ -78,7 +80,25 @@ class BucketModel {
78
80
  entry.copy[entry.path] = entry.obj[entry.path];
79
81
  }
80
82
  else {
81
- entry.copy[entry.path] = entry.obj[entry.path];
83
+ if (entry.field.type === 'date') {
84
+ if (serial?.date === 'parse')
85
+ entry.copy[entry.path] = date_1.NesoiDate.fromISO(entry.obj[entry.path]);
86
+ else if (serial?.date === 'dump')
87
+ entry.copy[entry.path] = entry.obj[entry.path].toISO();
88
+ else
89
+ entry.copy[entry.path] = entry.obj[entry.path];
90
+ }
91
+ else if (entry.field.type === 'datetime') {
92
+ if (serial?.datetime === 'parse')
93
+ entry.copy[entry.path] = datetime_1.NesoiDatetime.fromISO(entry.obj[entry.path]);
94
+ else if (serial?.datetime === 'dump')
95
+ entry.copy[entry.path] = entry.obj[entry.path].toISO();
96
+ else
97
+ entry.copy[entry.path] = entry.obj[entry.path];
98
+ }
99
+ else {
100
+ entry.copy[entry.path] = entry.obj[entry.path];
101
+ }
82
102
  }
83
103
  }
84
104
  poll = next;
@@ -8,10 +8,12 @@ import { IService } from './service';
8
8
  import { CLIConfig } from '../cli/cli';
9
9
  import { BucketAdapter } from "../../elements/entities/bucket/adapters/bucket_adapter";
10
10
  import { $TrashBucket } from '../data/trash';
11
- import { $Bucket } from "../../elements";
11
+ import { $Bucket } from "../../elements/entities/bucket/bucket.schema";
12
+ import { $Message } from "../../elements/entities/message/message.schema";
12
13
  import { Overlay } from '../util/type';
13
14
  import { TrxStatus } from '../transaction/trx';
14
15
  import { NesoiObj } from '../data/obj';
16
+ import { MessageTemplateDef } from "../../elements/entities/message/template/message_template.builder";
15
17
  export type AppModuleConfig<S extends $Space, M extends ModuleName<S>, Services extends Record<string, IService>> = {
16
18
  buckets?: AppBucketConfig<S, M, Services>;
17
19
  trash?: AppTrashConfig<Services>;
@@ -19,6 +21,8 @@ export type AppModuleConfig<S extends $Space, M extends ModuleName<S>, Services
19
21
  trx?: TrxEngineConfig<S, S['modules'][M], any, Services>;
20
22
  };
21
23
  export type AppConfig<S extends $Space, Modules extends ModuleName<S>, Services extends Record<string, IService>> = {
24
+ env?: $Message;
25
+ dotenv?: string;
22
26
  auth?: AppAuthConfig<S>;
23
27
  modules?: Partial<{
24
28
  [M in (Modules & keyof S['modules'])]: AppModuleConfig<S, M, Services>;
@@ -67,6 +71,8 @@ export declare class AppConfigBuilder<S extends $Space, Modules extends string =
67
71
  private app;
68
72
  private config;
69
73
  constructor(app: _App);
74
+ env(def: MessageTemplateDef<S, any, '__env__'>): _App;
75
+ dotenv(filename?: string): _App;
70
76
  auth(config: AppAuthConfig<S>): _App;
71
77
  module<M extends Modules>(name: M, config: AppModuleConfig<S, M, Services>): _App;
72
78
  audit(config: AppI18nConfig): _App;
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AppConfigBuilder = void 0;
4
+ const message_builder_1 = require("../../elements/entities/message/message.builder");
5
+ const dependency_1 = require("../dependency");
6
+ const tree_1 = require("../tree");
4
7
  /**
5
8
  * Factory
6
9
  */
@@ -12,6 +15,23 @@ class AppConfigBuilder {
12
15
  this.app = app;
13
16
  this.config = app._config;
14
17
  }
18
+ env(def) {
19
+ const builder = new message_builder_1.MessageBuilder('__app__', '__env__')
20
+ .template(def);
21
+ const schema = message_builder_1.MessageBuilder.build({
22
+ builder,
23
+ dependencies: [],
24
+ filepath: '',
25
+ inlines: {},
26
+ tag: new dependency_1.Tag('__app__', 'message', '__env__'),
27
+ }, new tree_1.ModuleTree({}), {});
28
+ this.config.env = schema;
29
+ return this.app;
30
+ }
31
+ dotenv(filename = '.env') {
32
+ this.config.dotenv = filename;
33
+ return this.app;
34
+ }
15
35
  auth(config) {
16
36
  this.config.auth = config;
17
37
  return this.app;
@@ -31,7 +31,9 @@ export declare abstract class App<S extends $Space, Modules extends string = Mod
31
31
  /**
32
32
  * Spawn a daemon for this app.
33
33
  */
34
- abstract daemon(): Promise<Daemon<S, Modules>>;
34
+ abstract daemon($?: {
35
+ dotenv?: string;
36
+ }): Promise<Daemon<S, Modules>>;
35
37
  /**
36
38
  * Specifies which `Space` modules to include on this App.
37
39
  *
@@ -24,14 +24,20 @@ export declare class InlineApp<S extends $Space, ModuleNames extends string = Mo
24
24
  * Build the application, start services and trx engines.
25
25
  * Returns references to start a daemon.
26
26
  */
27
- protected make(): Promise<{
27
+ protected make(dotenv?: string): Promise<{
28
28
  modules: Record<string, AnyModule>;
29
29
  services: Record<string, any>;
30
30
  trxEngines: Record<ModuleNames, AnyTrxEngine>;
31
31
  }>;
32
- daemon(): Promise<Daemon<S, ModuleNames>>;
32
+ daemon($?: {
33
+ dotenv?: string;
34
+ }): Promise<Daemon<S, ModuleNames>>;
33
35
  protected makeDaemon(trxEngines: Record<ModuleNames, AnyTrxEngine>, services: Record<string, IService>): AnyDaemon;
34
36
  package(_package: Record<string, any>): this;
37
+ /**
38
+ * This method validates the environment using the app env validator.
39
+ */
40
+ protected validateEnv(): Promise<void>;
35
41
  /**
36
42
  * This method injects values from environment variables into each module's
37
43
  * app constants.
@@ -13,6 +13,9 @@ const app_config_1 = require("./app.config");
13
13
  const promise_1 = __importDefault(require("../util/promise"));
14
14
  const dependency_1 = require("../dependency");
15
15
  const builder_1 = require("../builder");
16
+ const message_template_parser_1 = require("../../elements/entities/message/template/message_template_parser");
17
+ const trx_node_1 = require("../transaction/trx_node");
18
+ const dotenv_1 = require("../util/dotenv");
16
19
  /**
17
20
  * @category App
18
21
  */
@@ -53,7 +56,7 @@ class InlineApp extends app_1.App {
53
56
  * Build the application, start services and trx engines.
54
57
  * Returns references to start a daemon.
55
58
  */
56
- async make() {
59
+ async make(dotenv) {
57
60
  if (this.space || this.builders) {
58
61
  await this.boot().bootPromise;
59
62
  }
@@ -62,9 +65,21 @@ class InlineApp extends app_1.App {
62
65
  const mod = this._injectedModules[key];
63
66
  modules[mod.name] = mod;
64
67
  }
68
+ dotenv = dotenv || this._config.dotenv;
69
+ if (dotenv) {
70
+ log_1.Log.debug('app', this.name, `Loading environment variables from ${dotenv}`);
71
+ dotenv_1.DotEnv.load(dotenv);
72
+ }
73
+ if (this._config.env) {
74
+ log_1.Log.debug('app', this.name, 'Validating environment variables');
75
+ await this.validateEnv();
76
+ }
77
+ log_1.Log.debug('app', this.name, 'Linking app values');
78
+ this.linkAppValues(modules);
65
79
  const services = {};
66
80
  for (const key in this._services) {
67
81
  const service = this._services[key];
82
+ service.config = service.configFn();
68
83
  await promise_1.default.solve(service.up({
69
84
  modules
70
85
  }));
@@ -85,21 +100,17 @@ class InlineApp extends app_1.App {
85
100
  }
86
101
  trxEngines[m] = new trx_engine_1.TrxEngine(`app:${this.name}`, module, authnProviders, trxConfig, services);
87
102
  }
88
- // Log.debug('app', this.name, 'Injecting external constants and messages');
89
- // this.linkExternals(modules);
90
- log_1.Log.debug('app', this.name, 'Linking app values');
91
- this.linkAppValues(modules);
92
103
  return {
93
104
  modules,
94
105
  services,
95
106
  trxEngines
96
107
  };
97
108
  }
98
- async daemon() {
109
+ async daemon($) {
99
110
  if (this._daemon) {
100
111
  return this._daemon;
101
112
  }
102
- const app = await this.make();
113
+ const app = await this.make($?.dotenv);
103
114
  log_1.Log.debug('app', this.name, 'Spawning daemon');
104
115
  this._daemon = this.makeDaemon(app.trxEngines, app.services);
105
116
  // Link daemon to modules
@@ -107,12 +118,6 @@ class InlineApp extends app_1.App {
107
118
  const module = app.modules[m];
108
119
  module.daemon = this._daemon;
109
120
  }
110
- // Run init method of services
111
- for (const key in app.services) {
112
- await promise_1.default.solve(app.services[key].init({
113
- daemon: this._daemon
114
- }));
115
- }
116
121
  return this._daemon;
117
122
  }
118
123
  makeDaemon(trxEngines, services) {
@@ -122,27 +127,21 @@ class InlineApp extends app_1.App {
122
127
  this.packageJson = _package;
123
128
  return this;
124
129
  }
125
- // /**
126
- // * This method injects elements flagged as externals by referencing them
127
- // * from the other module directly, given this is a single-threaded App.
128
- // *
129
- // * TODO: allow overriding this behavior with adapters
130
- // */
131
- // protected linkExternals(modules: Record<string, Module<S, $Module>>) {
132
- // Object.values(modules).forEach(module => {
133
- // module.injectDependencies(modules, {
134
- // buckets: Object.values(module.schema.externals.buckets),
135
- // messages: Object.values(module.schema.externals.messages),
136
- // jobs: Object.values(module.schema.externals.jobs),
137
- // machines: Object.values(module.schema.externals.machines),
138
- // enums: Object.values(module.schema.externals.enums)
139
- // })
140
- // const buckets = module.schema.externals.buckets;
141
- // Object.values(buckets).forEach(bucket => {
142
- // module.nql.linkExternal(modules[bucket.module].buckets[bucket.name]);
143
- // })
144
- // })
145
- // }
130
+ /**
131
+ * This method validates the environment using the app env validator.
132
+ */
133
+ async validateEnv() {
134
+ const env = process.env;
135
+ const trxNode = new trx_node_1.TrxNode('root', {}, undefined, { name: '__app__' });
136
+ try {
137
+ const parsed = await (0, message_template_parser_1.MessageTemplateFieldParser)(trxNode, this._config.env.template.fields, env);
138
+ Object.assign(process.env, parsed);
139
+ }
140
+ catch (e) {
141
+ log_1.Log.error('app', this.name, 'Environment variables missing or incorrect.', e);
142
+ throw new Error('Environment variables missing or incorrect.');
143
+ }
144
+ }
146
145
  /**
147
146
  * This method injects values from environment variables into each module's
148
147
  * app constants.
@@ -15,6 +15,7 @@ export declare class BrowserApp<S extends $Space, ModuleNames extends string = M
15
15
  protected _packageJson?: Record<string, any>;
16
16
  daemon($?: {
17
17
  watch?: boolean;
18
+ dotenv?: string;
18
19
  }): Promise<import("../../daemon").Daemon<S, ModuleNames>>;
19
20
  protected makeDaemon(trxEngines: Record<ModuleNames, AnyTrxEngine>, services: Record<string, IService>): BrowserDaemon<$Space, ModuleNames>;
20
21
  modules<M extends ModuleName<S>>(modules: M[]): BrowserApp<S, M & ModuleNames>;