nesoi 3.3.17 → 3.3.19

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.
@@ -8,6 +8,7 @@ const memory_bucket_adapter_1 = require("../adapters/memory.bucket_adapter");
8
8
  const bucket_cache_1 = require("../cache/bucket_cache");
9
9
  const daemon_1 = require("../../../../engine/daemon");
10
10
  const dependency_1 = require("../../../../engine/dependency");
11
+ const trx_1 = require("../../../../engine/transaction/trx");
11
12
  /**
12
13
  * @category Elements
13
14
  * @subcategory Entity
@@ -61,7 +62,7 @@ class BucketGraph {
61
62
  ...schema.query,
62
63
  '#and __tenancy__': tenancy
63
64
  };
64
- const adapter = otherBucket.cache || otherBucket.adapter;
65
+ const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
65
66
  links = await adapter.query(trx, query, page, params, param_templates ? [param_templates] : undefined);
66
67
  }
67
68
  // Empty response
@@ -127,10 +128,10 @@ class BucketGraph {
127
128
  '#and __tenancy__': tenancy
128
129
  };
129
130
  if (otherBucket.adapter instanceof memory_bucket_adapter_1.MemoryBucketAdapter) {
130
- tempAdapter = otherBucket.cache || otherBucket.adapter;
131
+ tempAdapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
131
132
  }
132
133
  else {
133
- const adapter = otherBucket.cache || otherBucket.adapter;
134
+ const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
134
135
  const allLinks = await adapter.query(trx, query, undefined, params, param_templates);
135
136
  const tempData = {};
136
137
  for (const obj of allLinks.data)
@@ -238,7 +239,7 @@ class BucketGraph {
238
239
  ...schema.query,
239
240
  '#and__tenancy__': tenancy
240
241
  };
241
- const adapter = otherBucket.cache || otherBucket.adapter;
242
+ const adapter = await trx_1.Trx.getCache(trx, this.bucket) || otherBucket.cache || otherBucket.adapter;
242
243
  links = await adapter.query(trx, query, page, params);
243
244
  }
244
245
  return !!links.data.length;
@@ -55,3 +55,6 @@ export declare class NQL_CompiledQuery {
55
55
  constructor(parts: NQL_Part[]);
56
56
  describe(): string;
57
57
  }
58
+ export declare class NQL_Decompiler {
59
+ static decompile(part: NQL_Part, params: Record<string, any>[], param_templates: Record<string, string>[]): NQL_AnyQuery;
60
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NQL_CompiledQuery = exports.NQL_Compiler = exports.NQL_RuleTree = void 0;
3
+ exports.NQL_Decompiler = exports.NQL_CompiledQuery = exports.NQL_Compiler = exports.NQL_RuleTree = void 0;
4
4
  const bucket_model_schema_1 = require("../model/bucket_model.schema");
5
5
  const string_1 = require("../../../../engine/util/string");
6
6
  const daemon_1 = require("../../../../engine/daemon");
@@ -708,3 +708,64 @@ class NQL_CompiledQuery {
708
708
  }
709
709
  }
710
710
  exports.NQL_CompiledQuery = NQL_CompiledQuery;
711
+ class NQL_Decompiler {
712
+ static decompile(part, params, param_templates) {
713
+ const _union = (union, param, param_template, target) => {
714
+ for (let i = 0; i < union.inters.length; i++) {
715
+ const inter = union.inters[i];
716
+ const key = '#or' + Array.from({ length: i }).map(i => ' ').join('');
717
+ target[key] = {};
718
+ target = target[key];
719
+ for (let j = 0; j < inter.rules.length; j++) {
720
+ const rule = inter.rules[j];
721
+ if ('fieldpath' in rule) {
722
+ const key = `${rule.fieldpath} ${rule.not ? 'not ' : ''}${rule.op}`;
723
+ let value;
724
+ if ('static' in rule.value) {
725
+ value = rule.value.static;
726
+ }
727
+ else if ('param' in rule.value) {
728
+ value = typeof rule.value.param === 'string'
729
+ ? param[rule.value.param]
730
+ : rule.value.param.map(p => param[p]);
731
+ }
732
+ else if ('param_with_$' in rule.value) {
733
+ let path = rule.value.param_with_$;
734
+ for (const key in param_template) {
735
+ path = path.replace(new RegExp(key.replace('$', '\\$'), 'g'), param_template[key]);
736
+ }
737
+ value = param[path];
738
+ }
739
+ else if ('subquery' in rule.value) {
740
+ const sq = rule.value.subquery;
741
+ const subquery_key = `@${sq.bucket.module}::${sq.bucket.name}.${sq.select}`;
742
+ value = {
743
+ [subquery_key]: {}
744
+ };
745
+ _union(sq.union, param, param_template, value[subquery_key]);
746
+ }
747
+ target[key] = value;
748
+ }
749
+ else {
750
+ const key = '#and' + Array.from({ length: j }).map(i => ' ').join('');
751
+ target[key] = {};
752
+ _union(rule, param, param_template, target[key]);
753
+ }
754
+ }
755
+ }
756
+ };
757
+ const query = {};
758
+ let i = 0;
759
+ for (const param of params) {
760
+ for (const param_template of param_templates) {
761
+ const q = {};
762
+ _union(part.union, param, param_template, q);
763
+ const key = '#or' + Array.from({ length: i }).map(i => ' ').join('');
764
+ query[key] = q;
765
+ i++;
766
+ }
767
+ }
768
+ return query;
769
+ }
770
+ }
771
+ exports.NQL_Decompiler = NQL_Decompiler;
@@ -292,14 +292,16 @@ class BucketView {
292
292
  // Step 1: Read many links from bucket
293
293
  // External
294
294
  if (node.bucket.tag.module !== module.name) {
295
- linksObjs = await trx.bucket(node.bucket.tag.short).readManyLinks(node.data.map(entry => entry.raw.id), meta.path, node.data.map(entry => entry.index.map(i => i.toString())));
295
+ linksObjs = await trx.bucket(node.bucket.tag.short).readManyLinks(node.data.map(entry => entry.raw.id), //ids -> objs -> params
296
+ meta.path, [] // param templates temporarily disabled
297
+ );
296
298
  }
297
299
  // Internal
298
300
  else {
299
301
  const bucket = module.buckets[node.bucket.tag.name];
300
302
  linksObjs = await bucket.graph.readManyLinks(trx, node.data.map(entry => entry.raw), {
301
303
  name: meta.link,
302
- indexes: node.data.map(entry => entry.index.map(i => i.toString()))
304
+ indexes: [] // param templates temporarily disabled
303
305
  }, { silent: true });
304
306
  }
305
307
  // Step 2: Initialize target values
@@ -126,6 +126,10 @@ class Tag {
126
126
  return module.machines[self.name];
127
127
  if (self.type === 'controller')
128
128
  return module.controllers[self.name];
129
+ if (self.type === 'topic')
130
+ return module.topics[self.name];
131
+ if (self.type === 'queue')
132
+ return module.queues[self.name];
129
133
  throw new Error(`Schema with tag ${self.full} not found on module ${module.name}`);
130
134
  }
131
135
  static resolveExternal(self, externals) {
@@ -5,6 +5,8 @@ import { AnyTrxEngine, HeldTrxNode as TrxNodeHold, TrxEngineOrigin } from './trx
5
5
  import { AnyUsers, AuthRequest } from '../auth/authn';
6
6
  import { NesoiDatetime } from '../data/datetime';
7
7
  import { NesoiError } from '../data/error';
8
+ import { AnyBucketCache } from "../../elements/entities/bucket/cache/bucket_cache";
9
+ import { AnyBucket } from "../../elements/entities/bucket/bucket";
8
10
  type TrxOrigin = TrxEngineOrigin | `trx:${string}`;
9
11
  type TrxState = 'open' | 'hold' | 'ok' | 'error';
10
12
  /**
@@ -38,6 +40,8 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
38
40
  start: NesoiDatetime;
39
41
  end?: NesoiDatetime;
40
42
  ctx: Record<string, any>;
43
+ cache_config: Record<string, 'eager'>;
44
+ cache: Record<string, AnyBucketCache>;
41
45
  constructor(engine: AnyTrxEngine, module: Module<S, M>, origin: TrxOrigin, auth?: {
42
46
  tokens: AuthRequest<any>;
43
47
  users: AuthUsers;
@@ -45,6 +49,13 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
45
49
  addNode(node: TrxNode<S, M, AuthUsers>): void;
46
50
  holdNode(node: TrxNodeHold<any>): void;
47
51
  status(): TrxStatus<any>;
52
+ /**
53
+ * Cache
54
+ *
55
+ * This is used internally to initialize and access transaction-level bucket caches.
56
+ * These are configured through the TrxNode.cache method.
57
+ */
58
+ static getCache(node: AnyTrxNode, bucket: AnyBucket): Promise<AnyBucketCache | undefined>;
48
59
  /**
49
60
  * Context Manipulation
50
61
  *
@@ -5,6 +5,8 @@ const trx_node_1 = require("./trx_node");
5
5
  const string_1 = require("../util/string");
6
6
  const log_1 = require("../util/log");
7
7
  const datetime_1 = require("../data/datetime");
8
+ const bucket_cache_1 = require("../../elements/entities/bucket/cache/bucket_cache");
9
+ const dependency_1 = require("../dependency");
8
10
  /*
9
11
  Transaction Status
10
12
  */
@@ -74,6 +76,8 @@ class Trx {
74
76
  start = datetime_1.NesoiDatetime.now();
75
77
  end;
76
78
  ctx = {};
79
+ cache_config = {};
80
+ cache = {};
77
81
  constructor(engine, module, origin, auth, id, root, nodes) {
78
82
  this.engine = engine;
79
83
  this.module = module;
@@ -96,6 +100,35 @@ class Trx {
96
100
  const error = this.root.error;
97
101
  return new TrxStatus(this.id, this.origin, this.start, this.end, state, output, error, this.root.status().nodes);
98
102
  }
103
+ /**
104
+ * Cache
105
+ *
106
+ * This is used internally to initialize and access transaction-level bucket caches.
107
+ * These are configured through the TrxNode.cache method.
108
+ */
109
+ static async getCache(node, bucket) {
110
+ const trx = node.trx;
111
+ const tag = new dependency_1.Tag(bucket.schema.module, 'bucket', bucket.schema.name);
112
+ const config = trx.cache_config[tag.short];
113
+ if (!config)
114
+ return;
115
+ let cache = trx.cache[tag.short];
116
+ if (cache) {
117
+ return cache;
118
+ }
119
+ let mode;
120
+ switch (config) {
121
+ case 'eager':
122
+ mode = { get: 'eager', index: 'eager', query: 'eager' };
123
+ break;
124
+ }
125
+ trx.cache[tag.short] = new bucket_cache_1.BucketCache(bucket, { mode });
126
+ cache = trx.cache[tag.short];
127
+ if (config === 'eager') {
128
+ await cache.sync(node);
129
+ }
130
+ return cache;
131
+ }
99
132
  /**
100
133
  * Context Manipulation
101
134
  *
@@ -56,6 +56,7 @@ export declare class TrxNode<Space extends $Space, M extends $Module, AuthUsers
56
56
  message<Raw extends M['#input']['#raw'], Msg extends $Message = M['messages'][Raw['$'] & keyof M['messages']]>(raw: Raw): Promise<M['#input']['#parsed']>;
57
57
  value<K extends keyof M['constants']['values']>(name: K): M['constants']['values'][K]['value'];
58
58
  enum<EnumName extends keyof M['constants']['enums']>(name: EnumName): Enum<M['constants']['enums'][EnumName]>;
59
+ cache(config: Record<keyof M['buckets'], 'eager'>): this;
59
60
  bucket<Name extends keyof M['buckets'], Bucket extends M['buckets'][Name]>(name: Name): BucketTrxNode<M, Bucket>;
60
61
  job<Name extends keyof M['jobs'], Job extends M['jobs'][Name]>(name: Name): JobTrxNode<M, Job>;
61
62
  static jobWithCustomCtx<M extends $Module, JobName extends keyof M['jobs'], Job extends M['jobs'][JobName]>(node: AnyTrxNode, name: string, ctx?: Record<string, any>): JobTrxNode<M, Job>;
@@ -65,7 +66,7 @@ export declare class TrxNode<Space extends $Space, M extends $Module, AuthUsers
65
66
  topic<Name extends keyof M['topics'], topic extends M['topics'][Name]>(name: Name): TopicTrxNode<M, topic>;
66
67
  authenticate(tokens: AuthRequest<keyof AuthUsers>): Promise<TrxNode<$Space, $Module, AuthUsers>>;
67
68
  token<U extends keyof M['#authn']>(provider: U): Promise<string>;
68
- user<U extends keyof AuthUsers & keyof M['#authn']>(provider: U): Promise<M['#authn'][U]>;
69
+ user<U extends keyof AuthUsers & keyof M['#authn']>(...providers: U[]): Promise<M['#authn'][U]>;
69
70
  virtual<T>(def: VirtualModuleDef, fn: ($: AnyTrxNode) => T | Promise<T>): Promise<T>;
70
71
  status(): TrxNodeStatus;
71
72
  static merge<Space extends $Space, M extends $Module, AuthUsers extends AnyUsers>(to: TrxNode<Space, M, AuthUsers>, from: TrxNode<Space, M, AuthUsers>): void;
@@ -77,6 +78,6 @@ export declare class TrxNode<Space extends $Space, M extends $Module, AuthUsers
77
78
  provider: string;
78
79
  user: any;
79
80
  } | undefined;
80
- static checkAuth(node: AnyTrxNode, options?: $BlockAuth[]): Promise<void>;
81
+ static checkAuth(node: AnyTrxNode, options?: $BlockAuth[]): Promise<string | undefined>;
81
82
  }
82
83
  export type AnyTrxNode = TrxNode<any, any, any>;
@@ -121,6 +121,17 @@ class TrxNode {
121
121
  return new constants_1.Enum(this.module.schema.constants.enums[key]);
122
122
  }
123
123
  // Blocks
124
+ /*
125
+ Cache
126
+ */
127
+ cache(config) {
128
+ this.trx.cache_config = {};
129
+ for (const key in config) {
130
+ const tag = dependency_1.Tag.fromNameOrShort(this.module.name, 'bucket', key);
131
+ this.trx.cache_config[tag.short] = config[key];
132
+ }
133
+ return this;
134
+ }
124
135
  bucket(name) {
125
136
  const tag = dependency_1.Tag.fromNameOrShort(this.module.name, 'bucket', name);
126
137
  return new bucket_trx_node_1.BucketTrxNode(this, tag);
@@ -161,8 +172,8 @@ class TrxNode {
161
172
  async token(provider) {
162
173
  return this.auth?.tokens[provider];
163
174
  }
164
- async user(provider) {
165
- await TrxNode.checkAuth(this, [{ provider: provider }]);
175
+ async user(...providers) {
176
+ const provider = await TrxNode.checkAuth(this, providers.map(p => ({ provider: p })));
166
177
  return this.auth?.users[provider];
167
178
  }
168
179
  // Virtual Module Transaction
@@ -263,7 +274,7 @@ class TrxNode {
263
274
  continue;
264
275
  }
265
276
  log_1.Log.debug('trx', node.globalId, `User from provider '${opt.provider}' pre-authenticated${opt.resolver ? ' and authorized' : ''}`);
266
- return;
277
+ return opt.provider;
267
278
  }
268
279
  // Non-eager providers
269
280
  else if (opt.provider in tokens) {
@@ -282,7 +293,7 @@ class TrxNode {
282
293
  continue;
283
294
  }
284
295
  log_1.Log.debug('trx', node.globalId, `User from provider '${opt.provider}' authenticated${opt.resolver ? ' and authorized' : ''}`);
285
- return;
296
+ return opt.provider;
286
297
  }
287
298
  }
288
299
  throw error_1.NesoiError.Trx.Unauthorized({ providers: options.map(opt => opt.provider) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nesoi",
3
- "version": "3.3.17",
3
+ "version": "3.3.19",
4
4
  "description": "Declarative framework for data-driven applications",
5
5
  "repository": {
6
6
  "type": "git",