nesoi 3.4.21 → 3.4.24

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 (48) hide show
  1. package/lib/bundler/browser/browser.bundler.js +1 -1
  2. package/lib/bundler/monolyth/monolyth.bundler.d.ts +2 -2
  3. package/lib/bundler/monolyth/monolyth.bundler.js +9 -6
  4. package/lib/bundler/monolyth/stages/2_build_typescript_stage.js +5 -6
  5. package/lib/bundler/monolyth/stages/3_copy_types_stage.js +2 -3
  6. package/lib/compiler/compiler.d.ts +10 -1
  7. package/lib/compiler/compiler.js +54 -5
  8. package/lib/compiler/elements/controller.element.d.ts +1 -1
  9. package/lib/compiler/elements/controller.element.js +8 -0
  10. package/lib/compiler/progressive.js +2 -2
  11. package/lib/compiler/stages/4_build_schemas_stage.js +1 -1
  12. package/lib/compiler/stages/5_inject_ts_stage.js +2 -0
  13. package/lib/compiler/stages/6_build_elements_stage.js +2 -0
  14. package/lib/compiler/stages/7_dump_stage.js +4 -2
  15. package/lib/elements/edge/controller/adapters/cli.controller_adapter.d.ts +3 -6
  16. package/lib/elements/edge/controller/adapters/cli.controller_adapter.js +4 -4
  17. package/lib/elements/edge/controller/adapters/controller_adapter.d.ts +16 -6
  18. package/lib/elements/edge/controller/adapters/controller_adapter.js +20 -23
  19. package/lib/elements/edge/controller/adapters/fetch.controller_adapter.d.ts +27 -0
  20. package/lib/elements/edge/controller/adapters/fetch.controller_adapter.js +83 -0
  21. package/lib/elements/edge/controller/controller.schema.d.ts +9 -0
  22. package/lib/elements/edge/controller/controller.schema.js +41 -0
  23. package/lib/elements/entities/bucket/adapters/memory.bucket_adapter.js +2 -2
  24. package/lib/elements/entities/bucket/adapters/memory.nql.js +33 -2
  25. package/lib/elements/entities/bucket/bucket.js +2 -2
  26. package/lib/elements/entities/bucket/model/bucket_model.js +1 -1
  27. package/lib/elements/entities/bucket/query/nql_compiler.js +10 -0
  28. package/lib/elements/entities/constants/constants.d.ts +1 -1
  29. package/lib/elements/entities/constants/constants.js +1 -1
  30. package/lib/elements/entities/message/template/message_template_parser.js +1 -1
  31. package/lib/engine/app/app.config.d.ts +5 -1
  32. package/lib/engine/app/app.d.ts +11 -0
  33. package/lib/engine/app/app.js +30 -0
  34. package/lib/engine/app/inline.app.js +2 -1
  35. package/lib/engine/builder.d.ts +4 -2
  36. package/lib/engine/builder.js +65 -9
  37. package/lib/engine/data/error.d.ts +8 -0
  38. package/lib/engine/data/error.js +8 -0
  39. package/lib/engine/data/tree.js +4 -1
  40. package/lib/engine/dependency.d.ts +1 -0
  41. package/lib/engine/transaction/nodes/controller.trx_node.d.ts +17 -0
  42. package/lib/engine/transaction/nodes/controller.trx_node.js +60 -0
  43. package/lib/engine/transaction/trx_node.d.ts +2 -0
  44. package/lib/engine/transaction/trx_node.js +5 -0
  45. package/lib/engine/treeshake.js +1 -1
  46. package/lib/engine/util/deep.js +2 -2
  47. package/package.json +1 -1
  48. package/tsconfig.build.tsbuildinfo +1 -1
@@ -107,6 +107,7 @@ class $Controller {
107
107
  $t = 'controller';
108
108
  '#authn';
109
109
  '#input';
110
+ '#path';
110
111
  constructor(module, name, alias, auth, input, domains = {}, topics = {}) {
111
112
  this.module = module;
112
113
  this.name = name;
@@ -116,5 +117,45 @@ class $Controller {
116
117
  this.domains = domains;
117
118
  this.topics = topics;
118
119
  }
120
+ static endpoints(schema) {
121
+ const endpoints = {};
122
+ const _endpoint = (endpoint, path) => {
123
+ const path_str = this.makePath(schema, path, endpoint);
124
+ endpoints[path_str] = {
125
+ path,
126
+ endpoint
127
+ };
128
+ };
129
+ const _group = (group, path) => {
130
+ for (const g in group.groups) {
131
+ _group(group.groups[g], [...path, group]);
132
+ }
133
+ for (const e in group.endpoints) {
134
+ _endpoint(group.endpoints[e], [...path, group]);
135
+ }
136
+ };
137
+ const _domain = (domain) => {
138
+ for (const g in domain.groups) {
139
+ _group(domain.groups[g], [domain]);
140
+ }
141
+ for (const e in domain.endpoints) {
142
+ _endpoint(domain.endpoints[e], [domain]);
143
+ }
144
+ };
145
+ for (const d in schema.domains) {
146
+ _domain(schema.domains[d]);
147
+ }
148
+ return endpoints;
149
+ }
150
+ static makePath(schema, path, endpoint) {
151
+ const domain = path[0];
152
+ const root = `${domain.name ?? schema.name}@${domain.version}`;
153
+ const list = [
154
+ root,
155
+ ...path.slice(1).map(node => node.name),
156
+ endpoint.name
157
+ ];
158
+ return list.join('/');
159
+ }
119
160
  }
120
161
  exports.$Controller = $Controller;
@@ -92,13 +92,13 @@ class MemoryBucketAdapter extends bucket_adapter_1.BucketAdapter {
92
92
  throw new Error(`Object with id ${obj.id} not found for patch`);
93
93
  }
94
94
  const data = this.data[obj.id];
95
- const keys = Object.entries(obj).filter(([_, val]) => val !== undefined).map(([key]) => key);
95
+ const keys = Object.entries(obj).filter(([_, val]) => val != null).map(([key]) => key);
96
96
  const input = this.model.copy(obj, 'save', undefined, keys);
97
97
  for (const key in input) {
98
98
  if (input[key] === null) {
99
99
  delete data[key];
100
100
  }
101
- else if (input[key] !== undefined) {
101
+ else if (input[key] != null) {
102
102
  data[key] = input[key];
103
103
  }
104
104
  }
@@ -5,6 +5,7 @@ const nql_engine_1 = require("../query/nql_engine");
5
5
  const tree_1 = require("../../../../engine/data/tree");
6
6
  const datetime_1 = require("../../../../engine/data/datetime");
7
7
  const bucket_model_1 = require("../model/bucket_model");
8
+ const date_1 = require("../../../../engine/data/date");
8
9
  /**
9
10
  * @category NQL
10
11
  * */
@@ -114,7 +115,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
114
115
  if (pagination.returnTotal) {
115
116
  totalItems = output.length;
116
117
  }
117
- if (pagination.page !== undefined || pagination.perPage !== undefined) {
118
+ if (pagination.page != null || pagination.perPage != null) {
118
119
  const a = ((pagination.page || 1) - 1) * (pagination.perPage ?? 10);
119
120
  const b = a + (pagination.perPage ?? 10);
120
121
  output = output.slice(a, b);
@@ -278,7 +279,7 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
278
279
  ? tree_1.Tree.get(obj, rule.fieldpath)
279
280
  : obj[rule.fieldpath];
280
281
  // Value is undefined, only 'present' rule applies
281
- if (fieldValue === undefined) {
282
+ if (fieldValue == null) {
282
283
  if (rule.op === 'present') {
283
284
  return false;
284
285
  }
@@ -296,12 +297,30 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
296
297
  // Check each operation
297
298
  // (Compatible operations and types have already been validated)
298
299
  if (rule.op === '<') {
300
+ if (fieldValue instanceof date_1.NesoiDate) {
301
+ return fieldValue.compare(date_1.NesoiDate.from(queryValue)) < 0;
302
+ }
303
+ if (fieldValue instanceof datetime_1.NesoiDatetime) {
304
+ return fieldValue.epoch < datetime_1.NesoiDatetime.parse(queryValue).epoch;
305
+ }
299
306
  return fieldValue < queryValue;
300
307
  }
301
308
  if (rule.op === '<=') {
309
+ if (fieldValue instanceof date_1.NesoiDate) {
310
+ return fieldValue.compare(date_1.NesoiDate.from(queryValue)) <= 0;
311
+ }
312
+ if (fieldValue instanceof datetime_1.NesoiDatetime) {
313
+ return fieldValue.epoch <= datetime_1.NesoiDatetime.parse(queryValue).epoch;
314
+ }
302
315
  return fieldValue <= queryValue;
303
316
  }
304
317
  if (rule.op === '==') {
318
+ if (fieldValue instanceof date_1.NesoiDate) {
319
+ return fieldValue.compare(date_1.NesoiDate.from(queryValue)) == 0;
320
+ }
321
+ if (fieldValue instanceof datetime_1.NesoiDatetime) {
322
+ return fieldValue.epoch == datetime_1.NesoiDatetime.parse(queryValue).epoch;
323
+ }
305
324
  if (rule.case_i) {
306
325
  return fieldValue?.toLowerCase() === queryValue?.toLowerCase();
307
326
  }
@@ -310,9 +329,21 @@ class MemoryNQLRunner extends nql_engine_1.NQLRunner {
310
329
  }
311
330
  }
312
331
  if (rule.op === '>') {
332
+ if (fieldValue instanceof date_1.NesoiDate) {
333
+ return fieldValue.compare(date_1.NesoiDate.from(queryValue)) > 0;
334
+ }
335
+ if (fieldValue instanceof datetime_1.NesoiDatetime) {
336
+ return fieldValue.epoch > datetime_1.NesoiDatetime.parse(queryValue).epoch;
337
+ }
313
338
  return fieldValue > queryValue;
314
339
  }
315
340
  if (rule.op === '>=') {
341
+ if (fieldValue instanceof date_1.NesoiDate) {
342
+ return fieldValue.compare(date_1.NesoiDate.from(queryValue)) >= 0;
343
+ }
344
+ if (fieldValue instanceof datetime_1.NesoiDatetime) {
345
+ return fieldValue.epoch >= datetime_1.NesoiDatetime.parse(queryValue).epoch;
346
+ }
316
347
  return fieldValue >= queryValue;
317
348
  }
318
349
  if (rule.op === 'in') {
@@ -804,7 +804,7 @@ class Bucket {
804
804
  if (field.crypto) {
805
805
  const key = trx.value(field.crypto.value.short);
806
806
  const val = tree_1.Tree.get(obj, field.path);
807
- if (val !== undefined) {
807
+ if (val != null) {
808
808
  const encrypted = await crypto_1.NesoiCrypto.encrypt(val, key);
809
809
  tree_1.Tree.set(obj, field.path, () => encrypted);
810
810
  }
@@ -820,7 +820,7 @@ class Bucket {
820
820
  if (field.crypto) {
821
821
  const key = trx.value(field.crypto.value.short);
822
822
  const val = tree_1.Tree.get(obj, field.path);
823
- if (val !== undefined) {
823
+ if (val != null) {
824
824
  const encrypted = await crypto_1.NesoiCrypto.decrypt(val, key);
825
825
  tree_1.Tree.set(obj, field.path, () => encrypted);
826
826
  }
@@ -123,7 +123,7 @@ class BucketModel {
123
123
  runCopyCmd(op, cmd, modelpath, as_json = false) {
124
124
  const next = [];
125
125
  const value = cmd.obj[cmd.key];
126
- if (value === undefined || value === null) {
126
+ if (value == null) {
127
127
  if (cmd.field.path !== 'id' && cmd.field.required) {
128
128
  throw error_1.NesoiError.Bucket.Model.FieldRequired({ bucket: this.alias, field: cmd.field.path, indexes: cmd.modelpath?.asterisk_values });
129
129
  }
@@ -5,6 +5,8 @@ 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");
7
7
  const dependency_1 = require("../../../../engine/dependency");
8
+ const date_1 = require("../../../../engine/data/date");
9
+ const datetime_1 = require("../../../../engine/data/datetime");
8
10
  /**
9
11
  * @category NQL
10
12
  * */
@@ -70,6 +72,8 @@ class NQL_RuleTree {
70
72
  for (const key in query) {
71
73
  const value = query[key];
72
74
  const parsedKey = await this.parseKey(meta, key);
75
+ if (value == null)
76
+ continue;
73
77
  // Fieldpath term -> Condition
74
78
  if (parsedKey.type === 'fieldpath') {
75
79
  const parsed = await this.parseValue(value, parsedKey, meta, select);
@@ -268,6 +272,12 @@ class NQL_RuleTree {
268
272
  }
269
273
  }
270
274
  else {
275
+ if (value instanceof date_1.NesoiDate) {
276
+ return { static: value.toISO() };
277
+ }
278
+ if (value instanceof datetime_1.NesoiDatetime) {
279
+ return { static: value.toISO() };
280
+ }
271
281
  // Parameter
272
282
  if ('.' in value) {
273
283
  return { param: value['.'], param_is_deep: value['.'].includes('.') };
@@ -7,5 +7,5 @@ export declare class Enum<$ extends $ConstantEnum> {
7
7
  private schema;
8
8
  constructor(schema: $);
9
9
  keys<K extends keyof $['options']>(): K[];
10
- get<K extends keyof $['options']>(key: K): $['options'][K]['value'];
10
+ get<K extends keyof $['options']>(key: K): $['options'][K]['value'] | undefined;
11
11
  }
@@ -14,7 +14,7 @@ class Enum {
14
14
  return Object.keys(this.schema.options);
15
15
  }
16
16
  get(key) {
17
- return this.schema.options[key].value;
17
+ return this.schema.options[key]?.value;
18
18
  }
19
19
  }
20
20
  exports.Enum = Enum;
@@ -184,7 +184,7 @@ function sanitize(field, path, value) {
184
184
  * 2: {}, [] or ''
185
185
  */
186
186
  function isEmpty(value) {
187
- if (value === null || value === undefined) {
187
+ if (value == null) {
188
188
  return 1;
189
189
  }
190
190
  if (Array.isArray(value)) {
@@ -1,4 +1,4 @@
1
- import type { $Space, ModuleName } from "../../schema";
1
+ import type { $Module, $Space, ModuleName } from "../../schema";
2
2
  import type { BucketConfig } from "../../elements/entities/bucket/bucket.config";
3
3
  import type { AuthnProvider } from '../auth/authn';
4
4
  import type { ControllerConfig } from "../../elements/edge/controller/controller.config";
@@ -14,11 +14,14 @@ import type { Overlay } from '../util/type';
14
14
  import type { TrxStatus } from '../transaction/trx';
15
15
  import type { NesoiObj } from '../data/obj';
16
16
  import type { MessageTemplateDef } from "../../elements/entities/message/template/message_template.builder";
17
+ type ModuleElementTag<M extends $Module> = `message:${keyof M['messages'] & string}` | `bucket:${keyof M['buckets'] & string}` | `job:${keyof M['jobs'] & string}` | `resource:${keyof M['resources'] & string}` | `machine:${keyof M['machines'] & string}` | `controller:${keyof M['controllers'] & string}` | `queue:${keyof M['queues'] & string}` | `topic:${keyof M['topics'] & string}`;
17
18
  export type AppModuleConfig<S extends $Space, M extends ModuleName<S>, Services extends Record<string, IService>> = {
18
19
  buckets?: AppBucketConfig<S, M, Services>;
19
20
  trash?: AppTrashConfig<Services>;
20
21
  controllers?: AppControllerConfig<S, M, Services>;
21
22
  trx?: TrxEngineConfig<S, S['modules'][M], any, Services>;
23
+ include?: ModuleElementTag<S['modules'][M]>[];
24
+ exclude?: ModuleElementTag<S['modules'][M]>[];
22
25
  };
23
26
  export type AppConfig<S extends $Space, Modules extends ModuleName<S>, Services extends Record<string, IService>> = {
24
27
  env?: $Message;
@@ -80,3 +83,4 @@ export declare class AppConfigBuilder<S extends $Space, Modules extends string =
80
83
  cli(config: CLIConfig<Services>): _App;
81
84
  compiler(config: CompilerConfig): _App;
82
85
  }
86
+ export {};
@@ -5,6 +5,7 @@ import type { AnyAppConfig } from './app.config';
5
5
  import type { IService } from './service';
6
6
  import { Space } from '../space';
7
7
  import { AppConfigBuilder } from './app.config';
8
+ import { Tag } from '../dependency';
8
9
  /**
9
10
  * @category App
10
11
  */
@@ -66,5 +67,15 @@ export declare abstract class App<S extends $Space, Modules extends string = Mod
66
67
  config: AnyAppConfig;
67
68
  nesoiNpmPkg: string;
68
69
  };
70
+ /**
71
+ * Get a list of included/excluded tags per module, used by the builder
72
+ * to avoid including specific tags on the app.
73
+ */
74
+ static getIncludeExcludeTags(app: AnyApp): {
75
+ [module: string]: {
76
+ include?: Tag[];
77
+ exclude?: Tag[];
78
+ };
79
+ };
69
80
  }
70
81
  export type AnyApp = App<any, any>;
@@ -4,6 +4,7 @@ exports.App = void 0;
4
4
  const module_1 = require("../module");
5
5
  const space_1 = require("../space");
6
6
  const app_config_1 = require("./app.config");
7
+ const dependency_1 = require("../dependency");
7
8
  /*
8
9
  App
9
10
  */
@@ -112,5 +113,34 @@ class App {
112
113
  nesoiNpmPkg: app._nesoiNpmPkg,
113
114
  };
114
115
  }
116
+ /**
117
+ * Get a list of included/excluded tags per module, used by the builder
118
+ * to avoid including specific tags on the app.
119
+ */
120
+ static getIncludeExcludeTags(app) {
121
+ if (!app._config.modules)
122
+ return {};
123
+ const tags = {};
124
+ for (const m in app._config.modules) {
125
+ const module = app._config.modules[m];
126
+ if (module.include) {
127
+ tags[m] ??= {};
128
+ tags[m].include ??= [];
129
+ for (const ref of module.include) {
130
+ const [type, name] = ref.split(':');
131
+ tags[m].include.push(new dependency_1.Tag(m, type, name));
132
+ }
133
+ }
134
+ if (module.exclude) {
135
+ tags[m] ??= {};
136
+ tags[m].exclude ??= [];
137
+ for (const ref of module.exclude) {
138
+ const [type, name] = ref.split(':');
139
+ tags[m].exclude.push(new dependency_1.Tag(m, type, name));
140
+ }
141
+ }
142
+ }
143
+ return tags;
144
+ }
115
145
  }
116
146
  exports.App = App;
@@ -45,6 +45,7 @@ class InlineApp extends app_1.App {
45
45
  const tree = new tree_1.ModuleTree(this._modules, {
46
46
  exclude: ['*.test.ts']
47
47
  });
48
+ const tags = app_1.App.getIncludeExcludeTags(this);
48
49
  await tree.resolve();
49
50
  await tree.traverse('Building', async (node) => {
50
51
  // Inline nodes are built by their root builder
@@ -52,7 +53,7 @@ class InlineApp extends app_1.App {
52
53
  return;
53
54
  }
54
55
  const module = this._modules[node.tag.module];
55
- await builder_1.Builder.buildNode(module, node, tree);
56
+ await builder_1.Builder.buildNode(module, node, tree, tags);
56
57
  });
57
58
  }
58
59
  /**
@@ -1,6 +1,7 @@
1
- import type { ResolvedBuilderNode } from './dependency';
1
+ import { type ResolvedBuilderNode } from './dependency';
2
2
  import type { ModuleTree } from './tree';
3
3
  import type { AnyModule } from './module';
4
+ import type { Compiler } from "../compiler";
4
5
  export declare class Builder {
5
6
  /**
6
7
  * Build a resolved builder node, then merge the
@@ -10,7 +11,8 @@ export declare class Builder {
10
11
  * @param node A resolved builder node
11
12
  * @param tree A module tree
12
13
  */
13
- static buildNode(module: AnyModule, node: ResolvedBuilderNode, tree: ModuleTree): void;
14
+ static buildNode(module: AnyModule, node: ResolvedBuilderNode, tree: ModuleTree, tags?: Compiler['tags']): void;
15
+ static filterNode(module: string, node: ResolvedBuilderNode, tags?: Compiler['tags']): boolean;
14
16
  /**
15
17
  * Merge inline message schemas into the module.
16
18
  *
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Builder = void 0;
4
+ const dependency_1 = require("./dependency");
4
5
  const log_1 = require("./util/log");
5
6
  const error_1 = require("./data/error");
6
7
  const message_builder_1 = require("../elements/entities/message/message.builder");
@@ -23,8 +24,9 @@ class Builder {
23
24
  * @param node A resolved builder node
24
25
  * @param tree A module tree
25
26
  */
26
- static buildNode(module, node, tree) {
27
+ static buildNode(module, node, tree, tags) {
27
28
  log_1.Log.trace('builder', 'module', `Building ${module.name}::${(0, log_1.scopeTag)(node.builder.$b, node.builder.name)}`);
29
+ const add_root = this.filterNode(module.name, node, tags);
28
30
  if (node.builder.$b === 'constants') {
29
31
  module.schema.constants = constants_builder_1.ConstantsBuilder.build(node);
30
32
  }
@@ -32,45 +34,99 @@ class Builder {
32
34
  module.schema.externals = externals_builder_1.ExternalsBuilder.build(node, tree);
33
35
  }
34
36
  else if (node.builder.$b === 'bucket') {
35
- module.schema.buckets[node.tag.name] = bucket_builder_1.BucketBuilder.build(node, tree);
37
+ if (add_root) {
38
+ module.schema.buckets[node.tag.name] = bucket_builder_1.BucketBuilder.build(node, tree);
39
+ }
36
40
  }
37
41
  else if (node.builder.$b === 'message') {
38
- module.schema.messages[node.tag.name] = message_builder_1.MessageBuilder.build(node, tree, module.schema);
42
+ if (add_root) {
43
+ module.schema.messages[node.tag.name] = message_builder_1.MessageBuilder.build(node, tree, module.schema);
44
+ }
39
45
  }
40
46
  else if (node.builder.$b === 'job') {
41
47
  const { schema, inlineMessages } = job_builder_1.JobBuilder.build(node, tree, module.schema);
42
- module.schema.jobs[node.tag.name] = schema;
48
+ if (add_root) {
49
+ module.schema.jobs[node.tag.name] = schema;
50
+ }
43
51
  this.mergeInlineMessages(module, inlineMessages);
44
52
  }
45
53
  else if (node.builder.$b === 'resource') {
46
54
  const { schema, inlineMessages, inlineJobs } = resource_builder_1.ResourceBuilder.build(node, tree, module.schema);
47
- module.schema.resources[schema.name] = schema;
55
+ if (add_root) {
56
+ module.schema.resources[schema.name] = schema;
57
+ }
48
58
  this.mergeInlineMessages(module, inlineMessages);
49
59
  this.mergeInlineJobs(module, inlineJobs);
50
60
  }
51
61
  else if (node.builder.$b === 'machine') {
52
62
  const { schema, inlineMessages, inlineJobs } = machine_builder_1.MachineBuilder.build(node, tree, module.schema);
53
- module.schema.machines[schema.name] = schema;
63
+ if (add_root) {
64
+ module.schema.machines[schema.name] = schema;
65
+ }
54
66
  this.mergeInlineMessages(module, inlineMessages);
55
67
  this.mergeInlineJobs(module, inlineJobs);
56
68
  }
57
69
  else if (node.builder.$b === 'controller') {
58
- module.schema.controllers[node.tag.name] = controller_builder_1.ControllerBuilder.build(node);
70
+ if (add_root) {
71
+ module.schema.controllers[node.tag.name] = controller_builder_1.ControllerBuilder.build(node);
72
+ }
59
73
  }
60
74
  else if (node.builder.$b === 'queue') {
61
75
  const { schema, inlineMessages } = queue_builder_1.QueueBuilder.build(node, tree, module.schema);
62
- module.schema.queues[node.tag.name] = schema;
76
+ if (add_root) {
77
+ module.schema.queues[node.tag.name] = schema;
78
+ }
63
79
  this.mergeInlineMessages(module, inlineMessages);
64
80
  }
65
81
  else if (node.builder.$b === 'topic') {
66
82
  const { schema, inlineMessages } = topic_builder_1.TopicBuilder.build(node, tree, module.schema);
67
- module.schema.topics[node.tag.name] = schema;
83
+ if (add_root) {
84
+ module.schema.topics[node.tag.name] = schema;
85
+ }
68
86
  this.mergeInlineMessages(module, inlineMessages);
69
87
  }
70
88
  else {
71
89
  throw error_1.NesoiError.Module.UnknownBuilderType(module, node.filepath.toString(), node.tag.name, node.builder.$b);
72
90
  }
73
91
  }
92
+ static filterNode(module, node, tags) {
93
+ let add_root = true;
94
+ // Filter elements with include/exclude
95
+ const module_tags = tags?.[module];
96
+ if (module_tags?.include) {
97
+ if (!module_tags.include.some(t => dependency_1.Tag.matches(t, node.tag))) {
98
+ node.filtered = true;
99
+ add_root = false;
100
+ }
101
+ for (const type of ['message', 'job']) {
102
+ if (node.inlines[type]) {
103
+ for (const name in node.inlines[type]) {
104
+ if (!module_tags.include.some(t => dependency_1.Tag.matches(t, node.inlines[type][name].tag))) {
105
+ node.inlines[type][name].filtered = true;
106
+ delete node.inlines[type][name];
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ if (module_tags?.exclude) {
113
+ if (module_tags.exclude.some(t => dependency_1.Tag.matches(t, node.tag))) {
114
+ node.filtered = true;
115
+ add_root = false;
116
+ }
117
+ for (const type of ['message', 'job']) {
118
+ if (node.inlines[type]) {
119
+ for (const name in node.inlines[type]) {
120
+ if (module_tags.exclude.some(t => dependency_1.Tag.matches(t, node.inlines[type][name].tag))) {
121
+ node.inlines[type][name].filtered = true;
122
+ delete node.inlines[type][name];
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+ return add_root;
129
+ }
74
130
  /**
75
131
  * Merge inline message schemas into the module.
76
132
  *
@@ -337,6 +337,14 @@ export declare namespace NesoiError {
337
337
  function UnmetCondition(alias: string, msg: string): BaseError;
338
338
  }
339
339
  namespace Controller {
340
+ function DomainNotFound($: {
341
+ domain: string;
342
+ controller: string;
343
+ }): BaseError;
344
+ function EndpointNotFound($: {
345
+ endpoint: string;
346
+ controller: string;
347
+ }): BaseError;
340
348
  function SubscribeFailed($: {
341
349
  topic: string;
342
350
  }): BaseError;
@@ -507,6 +507,14 @@ var NesoiError;
507
507
  */
508
508
  let Controller;
509
509
  (function (Controller) {
510
+ function DomainNotFound($) {
511
+ return new BaseError('Controller.DomainNotFound', `Domain '${$.domain}' not found on controller '${$.controller}'`, Status.BAD_REQUEST, $);
512
+ }
513
+ Controller.DomainNotFound = DomainNotFound;
514
+ function EndpointNotFound($) {
515
+ return new BaseError('Controller.DomainNotFound', `Endpoint '${$.endpoint}' not found on controller '${$.controller}'`, Status.BAD_REQUEST, $);
516
+ }
517
+ Controller.EndpointNotFound = EndpointNotFound;
510
518
  function SubscribeFailed($) {
511
519
  return new BaseError('Controller.SubscribeFailed', `Failed to subscribe to topic '${$.topic}'`, Status.BAD_REQUEST, $);
512
520
  }
@@ -30,6 +30,9 @@ class Tree {
30
30
  if (ref === undefined) {
31
31
  return undefined;
32
32
  }
33
+ if (ref === null) {
34
+ return null;
35
+ }
33
36
  }
34
37
  // When reading from a TypeAsObj,
35
38
  // advance on unions
@@ -103,7 +106,7 @@ class Tree {
103
106
  else {
104
107
  ref.walk(path);
105
108
  }
106
- if (ref.get() === undefined) {
109
+ if (ref.get() == null) {
107
110
  ref.replace(replacer, __index);
108
111
  return;
109
112
  }
@@ -102,6 +102,7 @@ export type ResolvedBuilderNode = Overlay<BuilderNode, {
102
102
  };
103
103
  root?: ResolvedBuilderNode;
104
104
  layered?: boolean;
105
+ filtered?: boolean;
105
106
  schema?: AnyElementSchema;
106
107
  bridge?: {
107
108
  imports?: string[];
@@ -0,0 +1,17 @@
1
+ import type { $Module, $Space } from "../../../schema";
2
+ import type { $Controller } from "../../../elements/edge/controller/controller.schema";
3
+ import { TrxNode } from '../trx_node';
4
+ import { Tag } from "../../dependency";
5
+ /**
6
+ * @category Engine
7
+ * @subcategory Transaction
8
+ */
9
+ export declare class ControllerTrxNode<S extends $Space, M extends $Module, $ extends $Controller> {
10
+ private trx;
11
+ private tag;
12
+ private external;
13
+ private controller?;
14
+ constructor(trx: TrxNode<any, M, any>, tag: Tag);
15
+ private wrap;
16
+ invoke<Path extends keyof $['#path']>(path: Path, raw: $['#path'][Path]['#raw']): Promise<void>;
17
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ControllerTrxNode = void 0;
4
+ const trx_node_1 = require("../trx_node");
5
+ const external_trx_node_1 = require("./external.trx_node");
6
+ const dependency_1 = require("../../dependency");
7
+ const error_1 = require("../../data/error");
8
+ /**
9
+ * @category Engine
10
+ * @subcategory Transaction
11
+ */
12
+ class ControllerTrxNode {
13
+ trx;
14
+ tag;
15
+ external;
16
+ controller;
17
+ constructor(trx, tag) {
18
+ this.trx = trx;
19
+ this.tag = tag;
20
+ const module = trx_node_1.TrxNode.getModule(trx);
21
+ this.external = tag.module !== module.name;
22
+ if (!this.external) {
23
+ this.controller = dependency_1.Tag.element(tag, trx);
24
+ if (!this.controller) {
25
+ throw error_1.NesoiError.Trx.NodeNotFound(this.tag.full, trx.globalId);
26
+ }
27
+ }
28
+ }
29
+ /*
30
+ Wrap
31
+ */
32
+ async wrap(action, input, fn, fmtTrxOut) {
33
+ const wrapped = async (parentTrx, controller) => {
34
+ const trx = trx_node_1.TrxNode.makeChildNode(parentTrx, controller.schema.module, 'controller', controller.schema.name);
35
+ trx_node_1.TrxNode.open(trx, action, input);
36
+ let out;
37
+ try {
38
+ out = await fn(trx, controller);
39
+ }
40
+ catch (e) {
41
+ throw trx_node_1.TrxNode.error(trx, e);
42
+ }
43
+ trx_node_1.TrxNode.ok(trx, fmtTrxOut ? fmtTrxOut(out) : out);
44
+ return out;
45
+ };
46
+ if (this.external) {
47
+ const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
48
+ return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
49
+ }
50
+ else {
51
+ return wrapped(this.trx, this.controller);
52
+ }
53
+ }
54
+ async invoke(path, raw) {
55
+ return this.wrap('invoke', raw, (_, controller) => {
56
+ return controller.adapter.invoke(path, raw);
57
+ });
58
+ }
59
+ }
60
+ exports.ControllerTrxNode = ControllerTrxNode;
@@ -14,6 +14,7 @@ import { ResourceTrxNode } from './nodes/resource.trx_node';
14
14
  import { MachineTrxNode } from './nodes/machine.trx_node';
15
15
  import { Enum } from "../../elements/entities/constants/constants";
16
16
  import { TopicTrxNode } from './nodes/topic.trx_node';
17
+ import { ControllerTrxNode } from './nodes/controller.trx_node';
17
18
  export type TrxNodeBlock = 'bucket' | 'message' | 'job' | 'resource' | 'machine' | 'queue' | 'topic' | 'controller' | 'externals';
18
19
  export type TrxNodeState = 'open' | 'hold' | 'ok' | 'error';
19
20
  export type TrxNodeStatus = {
@@ -70,6 +71,7 @@ export declare class TrxNode<Space extends $Space, M extends $Module, AuthUsers
70
71
  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>;
71
72
  resource<Name extends keyof M['resources'], Resource extends M['resources'][Name]>(name: Name): ResourceTrxNode<M, Resource>;
72
73
  machine<Name extends keyof M['machines'], Machine extends M['machines'][Name]>(name: Name): MachineTrxNode<M, Machine>;
74
+ controller<Name extends keyof M['controllers'], Controller extends M['controllers'][Name]>(name: Name): ControllerTrxNode<Space, M, Controller>;
73
75
  queue<Name extends keyof M['queues'], Queue extends M['queues'][Name]>(name: Name): QueueTrxNode<M, Queue>;
74
76
  topic<Name extends keyof M['topics'], topic extends M['topics'][Name]>(name: Name): TopicTrxNode<Space, M, topic>;
75
77
  authenticate(tokens: AuthRequest<keyof AuthUsers>): Promise<TrxNode<$Space, $Module, AuthUsers>>;