@hotmeshio/hotmesh 0.3.5 → 0.3.6

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/build/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { MeshCall } from './services/meshcall';
2
- import { MeshData } from './services/meshdata';
3
- import { MeshFlow } from './services/meshflow';
4
1
  import { HotMesh } from './services/hotmesh';
5
2
  import { HotMeshConfig } from './types/hotmesh';
6
- export { HotMesh, MeshCall, MeshData, MeshFlow, HotMeshConfig };
3
+ import { MeshCall } from './services/meshcall';
4
+ import { MeshFlow } from './services/meshflow';
5
+ import { MeshData } from './services/meshdata';
6
+ import { MeshOS } from './services/meshos';
7
+ export { HotMesh, HotMeshConfig, MeshCall, MeshData, MeshFlow, MeshOS };
7
8
  export * as Types from './types';
package/build/index.js CHANGED
@@ -23,13 +23,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.Types = exports.MeshFlow = exports.MeshData = exports.MeshCall = exports.HotMesh = void 0;
26
+ exports.Types = exports.MeshOS = exports.MeshFlow = exports.MeshData = exports.MeshCall = exports.HotMesh = void 0;
27
+ const hotmesh_1 = require("./services/hotmesh");
28
+ Object.defineProperty(exports, "HotMesh", { enumerable: true, get: function () { return hotmesh_1.HotMesh; } });
27
29
  const meshcall_1 = require("./services/meshcall");
28
30
  Object.defineProperty(exports, "MeshCall", { enumerable: true, get: function () { return meshcall_1.MeshCall; } });
29
- const meshdata_1 = require("./services/meshdata");
30
- Object.defineProperty(exports, "MeshData", { enumerable: true, get: function () { return meshdata_1.MeshData; } });
31
31
  const meshflow_1 = require("./services/meshflow");
32
32
  Object.defineProperty(exports, "MeshFlow", { enumerable: true, get: function () { return meshflow_1.MeshFlow; } });
33
- const hotmesh_1 = require("./services/hotmesh");
34
- Object.defineProperty(exports, "HotMesh", { enumerable: true, get: function () { return hotmesh_1.HotMesh; } });
33
+ const meshdata_1 = require("./services/meshdata");
34
+ Object.defineProperty(exports, "MeshData", { enumerable: true, get: function () { return meshdata_1.MeshData; } });
35
+ const meshos_1 = require("./services/meshos");
36
+ Object.defineProperty(exports, "MeshOS", { enumerable: true, get: function () { return meshos_1.MeshOS; } });
35
37
  exports.Types = __importStar(require("./types"));
@@ -37,3 +37,4 @@ export declare function getValueByPath(obj: {
37
37
  export declare function restoreHierarchy(obj: StringAnyType): StringAnyType;
38
38
  export declare function isValidCron(cronExpression: string): boolean;
39
39
  export declare const s: (input: string) => number;
40
+ export declare const arrayToHash: (response: [number, ...Array<string | string[]>]) => Record<string, string>[];
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.s = exports.isValidCron = exports.restoreHierarchy = exports.getValueByPath = exports.getIndexedHash = exports.getSymVal = exports.getSymKey = exports.formatISODate = exports.getTimeSeries = exports.getSubscriptionTopic = exports.findSubscriptionForTrigger = exports.findTopKey = exports.matchesStatus = exports.matchesStatusCode = exports.identifyRedisTypeFromClass = exports.polyfill = exports.identifyRedisType = exports.XSleepFor = exports.sleepImmediate = exports.sleepFor = exports.guid = exports.deterministicRandom = exports.deepCopy = exports.getSystemHealth = exports.hashOptions = void 0;
6
+ exports.arrayToHash = exports.s = exports.isValidCron = exports.restoreHierarchy = exports.getValueByPath = exports.getIndexedHash = exports.getSymVal = exports.getSymKey = exports.formatISODate = exports.getTimeSeries = exports.getSubscriptionTopic = exports.findSubscriptionForTrigger = exports.findTopKey = exports.matchesStatus = exports.matchesStatusCode = exports.identifyRedisTypeFromClass = exports.polyfill = exports.identifyRedisType = exports.XSleepFor = exports.sleepImmediate = exports.sleepFor = exports.guid = exports.deterministicRandom = exports.deepCopy = exports.getSystemHealth = exports.hashOptions = void 0;
7
7
  const os_1 = __importDefault(require("os"));
8
8
  const crypto_1 = require("crypto");
9
9
  const nanoid_1 = require("nanoid");
@@ -240,3 +240,28 @@ const s = (input) => {
240
240
  return (0, ms_1.default)(input) / 1000;
241
241
  };
242
242
  exports.s = s;
243
+ const arrayToHash = (response) => {
244
+ const results = [];
245
+ let key;
246
+ for (let i = 1; i < response.length; i++) {
247
+ const row = response[i];
248
+ const result = {};
249
+ if (Array.isArray(row)) {
250
+ for (let j = 0; j < row.length; j += 2) {
251
+ const key = row[j];
252
+ const value = row[j + 1];
253
+ result[key] = value;
254
+ }
255
+ if (key) {
256
+ result.$ = key;
257
+ }
258
+ results.push(result);
259
+ key = undefined;
260
+ }
261
+ else {
262
+ key = row;
263
+ }
264
+ }
265
+ return results;
266
+ };
267
+ exports.arrayToHash = arrayToHash;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "Unbreakable Workflows",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/index.test.ts --detectOpenHandles --forceExit --verbose",
29
29
  "test:meshflow": "NODE_ENV=test jest ./tests/meshflow/*/index.test.ts --detectOpenHandles --forceExit --verbose",
30
30
  "test:meshflow:basic": "NODE_ENV=test jest ./tests/meshflow/basic/index.test.ts --detectOpenHandles --forceExit --verbose",
31
- "test:meshflow:collision": "NODE_ENV=test jest ./tests/meshflow/collision/index.test.ts --detectOpenHandles --forceExit --verbose",
31
+ "test:meshflow:collision": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/meshflow/collision/index.test.ts --detectOpenHandles --forceExit --verbose",
32
32
  "test:meshflow:fatal": "NODE_ENV=test jest ./tests/meshflow/fatal/index.test.ts --detectOpenHandles --forceExit --verbose",
33
33
  "test:meshflow:goodbye": "NODE_ENV=test jest ./tests/meshflow/goodbye/index.test.ts --detectOpenHandles --forceExit --verbose",
34
34
  "test:meshflow:hello": "HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/meshflow/helloworld/index.test.ts --detectOpenHandles --forceExit --verbose",
@@ -64,6 +64,7 @@
64
64
  "test:sub:redis": "NODE_ENV=test jest ./tests/functional/sub/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
65
65
  "test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
66
66
  "test:meshdata": "NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshdata/index.test.ts --forceExit --verbose --detectOpenHandles",
67
+ "test:meshos": "NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshos/index.test.ts --forceExit --verbose --detectOpenHandles",
67
68
  "test:meshcall": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/meshcall/index.test.ts --forceExit --verbose --detectOpenHandles",
68
69
  "test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose"
69
70
  },
@@ -25,7 +25,6 @@ declare class Trigger extends Activity {
25
25
  resolveJobId(context: Partial<JobState>): string;
26
26
  resolveJobKey(context: Partial<JobState>): string;
27
27
  setStateNX(status?: number): Promise<void>;
28
- registerJobDependency(multi?: RedisMulti): Promise<void>;
29
28
  setStats(multi?: RedisMulti): Promise<void>;
30
29
  }
31
30
  export { Trigger };
@@ -37,9 +37,6 @@ class Trigger extends activity_1.Activity {
37
37
  if (options?.pending) {
38
38
  await this.setExpired(options?.pending, multi);
39
39
  }
40
- else {
41
- await this.registerJobDependency(multi);
42
- }
43
40
  await collator_1.CollatorService.notarizeInception(this, this.context.metadata.guid, multi);
44
41
  await multi.exec();
45
42
  this.execAdjacentParent();
@@ -228,35 +225,6 @@ class Trigger extends activity_1.Activity {
228
225
  throw new errors_1.DuplicateJobError(jobId);
229
226
  }
230
227
  }
231
- async registerJobDependency(multi) {
232
- const depKey = this.config.stats?.parent ?? this.context.metadata.pj;
233
- let resolvedDepKey = depKey ? pipe_1.Pipe.resolve(depKey, this.context) : '';
234
- const adjKey = this.config.stats?.adjacent;
235
- const resolvedAdjKey = depKey ? pipe_1.Pipe.resolve(adjKey, this.context) : '';
236
- if (!resolvedDepKey) {
237
- resolvedDepKey = this.context.metadata.pj;
238
- }
239
- if (resolvedDepKey) {
240
- const isParentOrigin = resolvedDepKey === this.context.metadata.pj ||
241
- resolvedDepKey === resolvedAdjKey;
242
- let type;
243
- if (isParentOrigin) {
244
- if (this.context.metadata.px) {
245
- type = 'child';
246
- }
247
- else {
248
- type = 'expire-child';
249
- }
250
- }
251
- else {
252
- type = 'expire';
253
- }
254
- await this.store.registerJobDependency(type, resolvedDepKey, this.context.metadata.tpc, this.context.metadata.jid, this.context.metadata.gid, this.context.metadata.pd, multi);
255
- }
256
- if (resolvedAdjKey && resolvedAdjKey !== resolvedDepKey) {
257
- await this.store.registerJobDependency('child', resolvedAdjKey, this.context.metadata.tpc, this.context.metadata.jid, this.context.metadata.gid, this.context.metadata.pd, multi);
258
- }
259
- }
260
228
  async setStats(multi) {
261
229
  const md = this.context.metadata;
262
230
  if (md.key && this.config.stats?.measures) {
@@ -13,14 +13,11 @@ const exporter_1 = require("../exporter");
13
13
  const reporter_1 = require("../reporter");
14
14
  const router_1 = require("../router");
15
15
  const serializer_1 = require("../serializer");
16
- const redis_1 = require("../store/clients/redis");
17
- const ioredis_1 = require("../store/clients/ioredis");
18
- const redis_2 = require("../stream/clients/redis");
19
- const ioredis_2 = require("../stream/clients/ioredis");
20
- const ioredis_3 = require("../sub/clients/ioredis");
21
- const redis_3 = require("../sub/clients/redis");
22
16
  const task_1 = require("../task");
23
17
  const stream_1 = require("../../types/stream");
18
+ const factory_1 = require("../stream/factory");
19
+ const factory_2 = require("../sub/factory");
20
+ const factory_3 = require("../store/factory");
24
21
  class EngineService {
25
22
  constructor() {
26
23
  this.cacheMode = 'cache';
@@ -56,31 +53,13 @@ class EngineService {
56
53
  }
57
54
  }
58
55
  async initStoreChannel(store) {
59
- if ((0, utils_1.identifyRedisType)(store) === 'redis') {
60
- this.store = new redis_1.RedisStoreService(store);
61
- }
62
- else {
63
- this.store = new ioredis_1.IORedisStoreService(store);
64
- }
65
- await this.store.init(this.namespace, this.appId, this.logger);
56
+ this.store = await factory_3.StoreServiceFactory.init(store, this.namespace, this.appId, this.logger);
66
57
  }
67
58
  async initSubChannel(sub) {
68
- if ((0, utils_1.identifyRedisType)(sub) === 'redis') {
69
- this.subscribe = new redis_3.RedisSubService(sub);
70
- }
71
- else {
72
- this.subscribe = new ioredis_3.IORedisSubService(sub);
73
- }
74
- await this.subscribe.init(this.namespace, this.appId, this.guid, this.logger);
59
+ this.subscribe = await factory_2.SubServiceFactory.init(sub, this.namespace, this.appId, this.guid, this.logger);
75
60
  }
76
61
  async initStreamChannel(stream) {
77
- if ((0, utils_1.identifyRedisType)(stream) === 'redis') {
78
- this.stream = new redis_2.RedisStreamService(stream);
79
- }
80
- else {
81
- this.stream = new ioredis_2.IORedisStreamService(stream);
82
- }
83
- await this.stream.init(this.namespace, this.appId, this.logger);
62
+ this.stream = await factory_1.StreamServiceFactory.init(stream, this.namespace, this.appId, this.logger);
84
63
  }
85
64
  async initRouter(config) {
86
65
  const throttle = await this.store.getThrottleRate(':');
@@ -104,7 +104,9 @@ class Search {
104
104
  return value;
105
105
  }
106
106
  catch (error) {
107
- this.hotMeshClient.logger.error('meshflow-search-get-error', { ...error });
107
+ this.hotMeshClient.logger.error('meshflow-search-get-error', {
108
+ ...error,
109
+ });
108
110
  return '';
109
111
  }
110
112
  }
@@ -237,7 +237,7 @@ class WorkerService {
237
237
  isProcessing = true;
238
238
  const workflowInput = data.data;
239
239
  const execIndex = counter.counter - interruptionRegistry.length + 1;
240
- const { workflowId, workflowTopic, workflowDimension, originJobId, expire } = workflowInput;
240
+ const { workflowId, workflowTopic, workflowDimension, originJobId, expire, } = workflowInput;
241
241
  const collatorFlowId = `${(0, utils_1.guid)()}$C`;
242
242
  return {
243
243
  status: stream_1.StreamStatus.SUCCESS,
@@ -116,7 +116,7 @@ class WorkflowService {
116
116
  }
117
117
  return result.$error;
118
118
  }
119
- else {
119
+ else if (!result?.$error) {
120
120
  return result.data;
121
121
  }
122
122
  }
@@ -135,7 +135,7 @@ class WorkflowService {
135
135
  childJobId = options.workflowId;
136
136
  }
137
137
  else if (options.entity) {
138
- childJobId = `${options.entity}-${workflowId.substring(0, 7)}-${(0, utils_1.guid)()}-${workflowDimension}-${execIndex}`;
138
+ childJobId = `${options.entity}-${(0, utils_1.guid)()}-${workflowDimension}-${execIndex}`;
139
139
  }
140
140
  else {
141
141
  childJobId = `-${options.workflowName}-${(0, utils_1.guid)()}-${workflowDimension}-${execIndex}`;
@@ -0,0 +1,81 @@
1
+ import { MeshData } from '../meshdata/index';
2
+ import * as Types from '../../types';
3
+ declare abstract class MeshOS {
4
+ meshData: MeshData;
5
+ connected: boolean;
6
+ namespace: string;
7
+ namespaceType: string;
8
+ static databases: Record<string, Types.DB>;
9
+ static namespaces: Types.Namespaces;
10
+ static entities: Record<string, Types.Entity>;
11
+ static schemas: Record<string, Types.WorkflowSearchSchema>;
12
+ static profiles: Types.Profiles;
13
+ static classes: Record<string, typeof MeshOS>;
14
+ static logger: Types.ILogger;
15
+ constructor(namespace: string, namespaceType: string, config: Types.DBConfig);
16
+ protected abstract getEntity(): string;
17
+ abstract getSearchOptions(): Types.WorkflowSearchOptions;
18
+ protected abstract getTaskQueue(): string;
19
+ private initializeMeshData;
20
+ protected defaultTargetFn(): Promise<string>;
21
+ getNamespace(): string;
22
+ getRedisUrl: (config: Types.DBConfig) => {
23
+ url: string;
24
+ };
25
+ connect(): Promise<void>;
26
+ index(): Promise<void>;
27
+ static shutdown(): Promise<void>;
28
+ getIndexName(): string;
29
+ create(body: Record<string, any>): Promise<Types.StringStringType>;
30
+ retrieve(id: string, sparse?: boolean): Promise<Types.StringStringType>;
31
+ update(id: string, body: Record<string, any>): Promise<Types.StringStringType>;
32
+ delete(id: string): Promise<boolean>;
33
+ find(query?: {
34
+ field: string;
35
+ is: '=' | '[]' | '>=' | '<=';
36
+ value: string;
37
+ }[], start?: number, size?: number): Promise<{
38
+ count: number;
39
+ query: string;
40
+ data: Types.StringStringType[];
41
+ }>;
42
+ count(query: {
43
+ field: string;
44
+ is: '=' | '[]' | '>=' | '<=';
45
+ value: string;
46
+ }[]): Promise<number>;
47
+ aggregate(filter?: {
48
+ field: string;
49
+ is: '=' | '[]' | '>=' | '<=';
50
+ value: string;
51
+ }[], apply?: {
52
+ expression: string;
53
+ as: string;
54
+ }[], rows?: string[], columns?: string[], reduce?: {
55
+ operation: string;
56
+ as: string;
57
+ property?: string;
58
+ }[], sort?: {
59
+ field: string;
60
+ order: 'ASC' | 'DESC';
61
+ }[], start?: number, size?: number): Promise<{
62
+ count: number;
63
+ query: string;
64
+ data: Types.StringStringType[];
65
+ }>;
66
+ private buildAggregateCommand;
67
+ private buildFilterCommand;
68
+ init(search?: boolean): Promise<void>;
69
+ static registerDatabase(id: string, config: Types.DB): void;
70
+ static registerNamespace(id: string, config: Types.Namespace): void;
71
+ static registerEntity(id: string, config: Types.Entity): void;
72
+ static registerSchema(id: string, schema: Types.WorkflowSearchSchema): void;
73
+ static registerProfile(id: string, config: Types.Profile): void;
74
+ static registerClass(id: string, entityClass: typeof MeshOS): void;
75
+ static init(p?: Types.Profiles): Promise<void>;
76
+ static findEntity(database: string, namespace: string, entity: string): Types.EntityInstanceTypes | undefined;
77
+ static findSchemas(database: string, ns: string): Record<string, Types.WorkflowSearchSchema>;
78
+ static toJSON(p?: Types.Profiles): any;
79
+ workflow: {};
80
+ }
81
+ export { MeshOS };
@@ -0,0 +1,339 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.MeshOS = void 0;
27
+ const Redis = __importStar(require("redis"));
28
+ const index_1 = require("../meshdata/index");
29
+ const utils_1 = require("../../modules/utils");
30
+ const logger_1 = require("../logger");
31
+ class MeshOS {
32
+ constructor(namespace, namespaceType, config) {
33
+ this.connected = false;
34
+ this.getRedisUrl = (config) => {
35
+ return {
36
+ url: `redis${config.REDIS_USE_TLS ? 's' : ''}://${config.REDIS_USERNAME ?? ''}:${config.REDIS_PASSWORD}@${config.REDIS_HOST}:${config.REDIS_PORT}`,
37
+ };
38
+ };
39
+ this.workflow = {};
40
+ this.namespace = namespace;
41
+ this.namespaceType = namespaceType;
42
+ this.meshData = this.initializeMeshData(config);
43
+ }
44
+ initializeMeshData(dbConfig) {
45
+ return new index_1.MeshData(Redis, this.getRedisUrl(dbConfig), this.getSearchOptions());
46
+ }
47
+ async defaultTargetFn() {
48
+ return 'OK';
49
+ }
50
+ getNamespace() {
51
+ return this.namespace;
52
+ }
53
+ async connect() {
54
+ this.connected = await this.meshData.connect({
55
+ entity: this.getEntity(),
56
+ target: this.defaultTargetFn,
57
+ options: {
58
+ namespace: this.getNamespace(),
59
+ taskQueue: this.getTaskQueue(),
60
+ },
61
+ });
62
+ }
63
+ async index() {
64
+ await this.meshData.createSearchIndex(this.getEntity(), { namespace: this.getNamespace() }, this.getSearchOptions());
65
+ }
66
+ static async shutdown() {
67
+ await index_1.MeshData.shutdown();
68
+ }
69
+ getIndexName() {
70
+ return this.getSearchOptions().index;
71
+ }
72
+ async create(body) {
73
+ const id = body.id || (0, utils_1.guid)();
74
+ await this.meshData.set(this.getEntity(), id, {
75
+ search: { data: body },
76
+ namespace: this.getNamespace(),
77
+ });
78
+ return this.retrieve(id);
79
+ }
80
+ async retrieve(id, sparse = false) {
81
+ const opts = this.getSearchOptions();
82
+ const fields = sparse ? ['id'] : Object.keys(opts?.schema || {});
83
+ const result = await this.meshData.get(this.getEntity(), id, {
84
+ fields,
85
+ namespace: this.getNamespace(),
86
+ });
87
+ if (!result?.id)
88
+ throw new Error(`${this.getEntity()} not found`);
89
+ return result;
90
+ }
91
+ async update(id, body) {
92
+ await this.retrieve(id);
93
+ await this.meshData.set(this.getEntity(), id, {
94
+ search: { data: body },
95
+ namespace: this.getNamespace(),
96
+ });
97
+ return this.retrieve(id);
98
+ }
99
+ async delete(id) {
100
+ await this.retrieve(id);
101
+ await this.meshData.flush(this.getEntity(), id, this.getNamespace());
102
+ return true;
103
+ }
104
+ async find(query = [], start = 0, size = 100) {
105
+ const opts = this.getSearchOptions();
106
+ return this.meshData.findWhere(this.getEntity(), {
107
+ query,
108
+ return: Object.keys(opts?.schema || {}),
109
+ limit: { start, size },
110
+ options: { namespace: this.getNamespace() },
111
+ });
112
+ }
113
+ async count(query) {
114
+ return this.meshData.findWhere(this.getEntity(), {
115
+ query,
116
+ count: true,
117
+ options: { namespace: this.getNamespace() },
118
+ });
119
+ }
120
+ async aggregate(filter = [], apply = [], rows = [], columns = [], reduce = [], sort = [], start = 0, size = 100) {
121
+ const command = this.buildAggregateCommand(filter, apply, rows, columns, reduce, sort);
122
+ try {
123
+ const results = await this.meshData.find(this.getEntity(), {
124
+ index: this.getIndexName(),
125
+ namespace: this.getNamespace(),
126
+ taskQueue: this.getTaskQueue(),
127
+ search: this.getSearchOptions(),
128
+ }, ...command);
129
+ return {
130
+ count: results[0],
131
+ query: command.join(' '),
132
+ data: (0, utils_1.arrayToHash)(results),
133
+ };
134
+ }
135
+ catch (e) {
136
+ throw e;
137
+ }
138
+ }
139
+ buildAggregateCommand(filter, apply, rows, columns, reduce, sort) {
140
+ const command = ['FT.AGGREGATE', this.getIndexName() || 'default'];
141
+ const opts = this.getSearchOptions();
142
+ command.push(this.buildFilterCommand(filter));
143
+ apply.forEach((a) => command.push('APPLY', a.expression, 'AS', a.as));
144
+ const groupBy = rows.concat(columns);
145
+ if (groupBy.length > 0) {
146
+ command.push('GROUPBY', `${groupBy.length}`, ...groupBy.map((g) => opts?.schema?.[g] ? `@_${g}` : `@${g}`));
147
+ }
148
+ reduce.forEach((r) => {
149
+ const op = r.operation.toUpperCase();
150
+ if (op === 'COUNT') {
151
+ command.push('REDUCE', op, '0', 'AS', r.as ?? 'count');
152
+ }
153
+ else if ([
154
+ 'COUNT_DISTINCT',
155
+ 'COUNT_DISTINCTISH',
156
+ 'SUM',
157
+ 'AVG',
158
+ 'MIN',
159
+ 'MAX',
160
+ 'STDDEV',
161
+ 'TOLIST',
162
+ ].includes(op)) {
163
+ const property = r.property
164
+ ? opts?.schema?.[r.property]
165
+ ? `@_${r.property}`
166
+ : `@${r.property}`
167
+ : '';
168
+ command.push('REDUCE', op, '1', property, 'AS', r.as ?? `${r.operation}_${r.property}`);
169
+ }
170
+ });
171
+ if (sort.length > 0) {
172
+ command.push('SORTBY', `${2 * sort.length}`, ...sort.flatMap((s) => [
173
+ opts?.schema?.[s.field] ? `@_${s.field}` : `@${s.field}`,
174
+ s.order.toUpperCase() || 'DESC',
175
+ ]));
176
+ }
177
+ return command;
178
+ }
179
+ buildFilterCommand(filter) {
180
+ if (filter.length === 0)
181
+ return '*';
182
+ const opts = this.getSearchOptions();
183
+ return filter
184
+ .map((q) => {
185
+ const type = opts?.schema?.[q.field]?.type ?? 'TEXT';
186
+ switch (type) {
187
+ case 'TAG':
188
+ return `@_${q.field}:{${q.value}}`;
189
+ case 'TEXT':
190
+ return `@_${q.field}:${q.value}`;
191
+ case 'NUMERIC':
192
+ return `@_${q.field}:[${q.value}]`;
193
+ }
194
+ })
195
+ .join(' ');
196
+ }
197
+ async init(search = true) {
198
+ await this.connect();
199
+ if (search) {
200
+ await this.index();
201
+ }
202
+ }
203
+ static registerDatabase(id, config) {
204
+ MeshOS.databases[id] = config;
205
+ }
206
+ static registerNamespace(id, config) {
207
+ MeshOS.namespaces[id] = config;
208
+ }
209
+ static registerEntity(id, config) {
210
+ MeshOS.entities[id] = config;
211
+ }
212
+ static registerSchema(id, schema) {
213
+ MeshOS.schemas[id] = schema;
214
+ }
215
+ static registerProfile(id, config) {
216
+ MeshOS.profiles[id] = config;
217
+ }
218
+ static registerClass(id, entityClass) {
219
+ MeshOS.classes[id] = entityClass;
220
+ }
221
+ static async init(p = MeshOS.profiles) {
222
+ for (const key in p) {
223
+ const profile = p[key];
224
+ if (profile.db.config.REDIS_HOST) {
225
+ this.logger.info(`meshos-initializing`, {
226
+ db: profile.db.name,
227
+ key,
228
+ });
229
+ profile.instances = {};
230
+ for (const ns in profile.namespaces) {
231
+ const namespace = profile.namespaces[ns];
232
+ this.logger.info(`meshos-initializing-namespace`, {
233
+ namespace: ns,
234
+ label: namespace.label,
235
+ });
236
+ let pinstances = profile.instances[ns];
237
+ if (!pinstances) {
238
+ pinstances = {};
239
+ profile.instances[ns] = pinstances;
240
+ }
241
+ for (const entity of namespace.entities) {
242
+ this.logger.info(`meshos-initializing-entity`, {
243
+ entity: entity.name,
244
+ label: entity.label,
245
+ });
246
+ const instance = pinstances[entity.name] = new entity.class(ns, namespace.type, profile.db.config);
247
+ await instance.init(profile.db.search);
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ static findEntity(database, namespace, entity) {
254
+ if (!database ||
255
+ !MeshOS.profiles[database] ||
256
+ !MeshOS.profiles[database]?.db?.config?.REDIS_HOST) {
257
+ const activeProfiles = Object.keys(MeshOS.profiles).filter((key) => MeshOS.profiles[key]?.db?.config?.REDIS_HOST);
258
+ throw new Error(`The database query parameter [${database}] was not found. Use one of: ${activeProfiles.join(', ')}`);
259
+ }
260
+ if (!namespace || !MeshOS.profiles[database]?.instances?.[namespace]) {
261
+ const activeNamespaces = Object.keys(MeshOS.profiles[database]?.instances ?? {});
262
+ throw new Error(`The namespace query parameter [${namespace}] was not found. Use one of: ${activeNamespaces.join(', ')}`);
263
+ }
264
+ const entities = MeshOS.profiles[database]?.instances?.[namespace] ?? {};
265
+ if (!entity || entity?.startsWith('-') || entity === '*') {
266
+ entity = Object.keys(entities)[0];
267
+ }
268
+ else if (entity?.endsWith('*')) {
269
+ entity = entity.slice(0, -1);
270
+ }
271
+ const target = MeshOS.profiles[database]?.instances?.[namespace]?.[entity];
272
+ if (!target) {
273
+ this.logger.error(`meshos-entity-not-found`, {
274
+ database,
275
+ namespace,
276
+ entity,
277
+ });
278
+ entity = Object.keys(entities)[0];
279
+ return MeshOS.profiles[database]?.instances?.[namespace]?.[entity];
280
+ }
281
+ return target;
282
+ }
283
+ static findSchemas(database, ns) {
284
+ if (!database ||
285
+ !MeshOS.profiles[database] ||
286
+ !MeshOS.profiles[database]?.db?.config?.REDIS_HOST) {
287
+ const activeProfiles = Object.keys(MeshOS.profiles).filter((key) => MeshOS.profiles[key]?.db?.config?.REDIS_HOST);
288
+ throw new Error(`The database query parameter [${database}] was not found. Use one of: ${activeProfiles.join(', ')}`);
289
+ }
290
+ const profile = MeshOS.profiles[database];
291
+ const namespacedInstance = profile.instances[ns];
292
+ const schemas = {};
293
+ for (const entityName in namespacedInstance) {
294
+ const entityInstance = namespacedInstance[entityName];
295
+ const opts = entityInstance.getSearchOptions();
296
+ schemas[opts.index ?? entityName] = opts.schema;
297
+ }
298
+ return schemas;
299
+ }
300
+ static toJSON(p = MeshOS.profiles) {
301
+ const result = {};
302
+ for (const key in p) {
303
+ const profile = p[key];
304
+ if (!profile.db.config.REDIS_HOST) {
305
+ continue;
306
+ }
307
+ else {
308
+ result[key] = {
309
+ db: { ...profile.db, config: undefined },
310
+ namespaces: {},
311
+ };
312
+ }
313
+ for (const ns in profile.namespaces) {
314
+ const namespace = profile.namespaces[ns];
315
+ result[key].namespaces[ns] = {
316
+ name: namespace.name,
317
+ label: namespace.label,
318
+ entities: [],
319
+ };
320
+ for (const entity of namespace.entities) {
321
+ result[key].namespaces[ns].entities.push({
322
+ name: entity.name,
323
+ label: entity.label,
324
+ schema: entity.schema,
325
+ });
326
+ }
327
+ }
328
+ }
329
+ return result;
330
+ }
331
+ }
332
+ exports.MeshOS = MeshOS;
333
+ MeshOS.databases = {};
334
+ MeshOS.namespaces = {};
335
+ MeshOS.entities = {};
336
+ MeshOS.schemas = {};
337
+ MeshOS.profiles = {};
338
+ MeshOS.classes = {};
339
+ MeshOS.logger = new logger_1.LoggerService('hotmesh', 'meshos');
@@ -4,11 +4,9 @@ exports.QuorumService = void 0;
4
4
  const enums_1 = require("../../modules/enums");
5
5
  const utils_1 = require("../../modules/utils");
6
6
  const compiler_1 = require("../compiler");
7
- const ioredis_1 = require("../store/clients/ioredis");
8
- const redis_1 = require("../store/clients/redis");
9
- const ioredis_2 = require("../sub/clients/ioredis");
10
- const redis_2 = require("../sub/clients/redis");
11
7
  const hotmesh_1 = require("../../types/hotmesh");
8
+ const factory_1 = require("../sub/factory");
9
+ const factory_2 = require("../store/factory");
12
10
  class QuorumService {
13
11
  constructor() {
14
12
  this.profiles = [];
@@ -42,22 +40,10 @@ class QuorumService {
42
40
  }
43
41
  }
44
42
  async initStoreChannel(store) {
45
- if ((0, utils_1.identifyRedisType)(store) === 'redis') {
46
- this.store = new redis_1.RedisStoreService(store);
47
- }
48
- else {
49
- this.store = new ioredis_1.IORedisStoreService(store);
50
- }
51
- await this.store.init(this.namespace, this.appId, this.logger);
43
+ this.store = await factory_2.StoreServiceFactory.init(store, this.namespace, this.appId, this.logger);
52
44
  }
53
45
  async initSubChannel(sub) {
54
- if ((0, utils_1.identifyRedisType)(sub) === 'redis') {
55
- this.subscribe = new redis_2.RedisSubService(sub);
56
- }
57
- else {
58
- this.subscribe = new ioredis_2.IORedisSubService(sub);
59
- }
60
- await this.subscribe.init(this.namespace, this.appId, this.guid, this.logger);
46
+ this.subscribe = await factory_1.SubServiceFactory.init(sub, this.namespace, this.appId, this.guid, this.logger);
61
47
  }
62
48
  subscriptionHandler() {
63
49
  const self = this;
@@ -0,0 +1,7 @@
1
+ import { RedisClient } from '../../types/redis';
2
+ import { ILogger } from '../logger';
3
+ import { StoreService } from './index';
4
+ declare class StoreServiceFactory {
5
+ static init(redisClient: RedisClient, namespace: string, appId: string, logger: ILogger): Promise<StoreService<any, any>>;
6
+ }
7
+ export { StoreServiceFactory };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StoreServiceFactory = void 0;
4
+ const utils_1 = require("../../modules/utils");
5
+ const ioredis_1 = require("./clients/ioredis");
6
+ const redis_1 = require("./clients/redis");
7
+ class StoreServiceFactory {
8
+ static async init(redisClient, namespace, appId, logger) {
9
+ let service;
10
+ if ((0, utils_1.identifyRedisType)(redisClient) === 'redis') {
11
+ service = new redis_1.RedisStoreService(redisClient);
12
+ }
13
+ else {
14
+ service = new ioredis_1.IORedisStoreService(redisClient);
15
+ }
16
+ await service.init(namespace, appId, logger);
17
+ return service;
18
+ }
19
+ }
20
+ exports.StoreServiceFactory = StoreServiceFactory;
@@ -61,7 +61,6 @@ declare abstract class StoreService<T, U extends AbstractRedisClient> {
61
61
  setApp(id: string, version: string): Promise<HotMeshApp>;
62
62
  activateAppVersion(id: string, version: string): Promise<boolean>;
63
63
  registerAppVersion(appId: string, version: string): Promise<any>;
64
- registerJobDependency(depType: WorkListTaskType, originJobId: string, topic: string, jobId: string, gId: string, pd?: string, multi?: U): Promise<any>;
65
64
  setStats(jobKey: string, jobId: string, dateTime: string, stats: StatsType, appVersion: AppVID, multi?: U): Promise<any>;
66
65
  hGetAllResult(result: any): any;
67
66
  getJobStats(jobKeys: string[]): Promise<JobStatsRange>;
@@ -355,8 +355,6 @@ class StoreService {
355
355
  };
356
356
  return await this.redisClient[this.commands.hset](key, payload);
357
357
  }
358
- async registerJobDependency(depType, originJobId, topic, jobId, gId, pd = '', multi) {
359
- }
360
358
  async setStats(jobKey, jobId, dateTime, stats, appVersion, multi) {
361
359
  const params = {
362
360
  appId: appVersion.id,
@@ -0,0 +1,7 @@
1
+ import { RedisClient } from '../../types/redis';
2
+ import { ILogger } from '../logger';
3
+ import { StreamService } from './index';
4
+ declare class StreamServiceFactory {
5
+ static init(redisClient: RedisClient, namespace: string, appId: string, logger: ILogger): Promise<StreamService<any, any>>;
6
+ }
7
+ export { StreamServiceFactory };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StreamServiceFactory = void 0;
4
+ const utils_1 = require("../../modules/utils");
5
+ const ioredis_1 = require("./clients/ioredis");
6
+ const redis_1 = require("./clients/redis");
7
+ class StreamServiceFactory {
8
+ static async init(redisClient, namespace, appId, logger) {
9
+ let service;
10
+ if ((0, utils_1.identifyRedisType)(redisClient) === 'redis') {
11
+ service = new redis_1.RedisStreamService(redisClient);
12
+ }
13
+ else {
14
+ service = new ioredis_1.IORedisStreamService(redisClient);
15
+ }
16
+ await service.init(namespace, appId, logger);
17
+ return service;
18
+ }
19
+ }
20
+ exports.StreamServiceFactory = StreamServiceFactory;
@@ -0,0 +1,7 @@
1
+ import { RedisClient } from '../../types/redis';
2
+ import { ILogger } from '../logger';
3
+ import { SubService } from './index';
4
+ declare class SubServiceFactory {
5
+ static init(redisClient: RedisClient, namespace: string, appId: string, engineId: string, logger: ILogger): Promise<SubService<any, any>>;
6
+ }
7
+ export { SubServiceFactory };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubServiceFactory = void 0;
4
+ const utils_1 = require("../../modules/utils");
5
+ const ioredis_1 = require("./clients/ioredis");
6
+ const redis_1 = require("./clients/redis");
7
+ class SubServiceFactory {
8
+ static async init(redisClient, namespace, appId, engineId, logger) {
9
+ let service;
10
+ if ((0, utils_1.identifyRedisType)(redisClient) === 'redis') {
11
+ service = new redis_1.RedisSubService(redisClient);
12
+ }
13
+ else {
14
+ service = new ioredis_1.IORedisSubService(redisClient);
15
+ }
16
+ await service.init(namespace, appId, engineId, logger);
17
+ return service;
18
+ }
19
+ }
20
+ exports.SubServiceFactory = SubServiceFactory;
@@ -5,14 +5,11 @@ const key_1 = require("../../modules/key");
5
5
  const utils_1 = require("../../modules/utils");
6
6
  const connector_1 = require("../connector");
7
7
  const router_1 = require("../router");
8
- const ioredis_1 = require("../store/clients/ioredis");
9
- const redis_1 = require("../store/clients/redis");
10
- const ioredis_2 = require("../stream/clients/ioredis");
11
- const redis_2 = require("../stream/clients/redis");
12
- const ioredis_3 = require("../sub/clients/ioredis");
13
- const redis_3 = require("../sub/clients/redis");
14
8
  const stream_1 = require("../../types/stream");
15
9
  const enums_1 = require("../../modules/enums");
10
+ const factory_1 = require("../stream/factory");
11
+ const factory_2 = require("../sub/factory");
12
+ const factory_3 = require("../store/factory");
16
13
  class WorkerService {
17
14
  constructor() {
18
15
  this.reporting = false;
@@ -58,31 +55,13 @@ class WorkerService {
58
55
  }
59
56
  }
60
57
  async initStoreChannel(service, store) {
61
- if ((0, utils_1.identifyRedisType)(store) === 'redis') {
62
- service.store = new redis_1.RedisStoreService(store);
63
- }
64
- else {
65
- service.store = new ioredis_1.IORedisStoreService(store);
66
- }
67
- await service.store.init(service.namespace, service.appId, service.logger);
58
+ service.store = await factory_3.StoreServiceFactory.init(store, service.namespace, service.appId, service.logger);
68
59
  }
69
60
  async initSubChannel(service, sub) {
70
- if ((0, utils_1.identifyRedisType)(sub) === 'redis') {
71
- service.subscribe = new redis_3.RedisSubService(sub);
72
- }
73
- else {
74
- service.subscribe = new ioredis_3.IORedisSubService(sub);
75
- }
76
- await service.subscribe.init(service.namespace, service.appId, service.guid, service.logger);
61
+ service.subscribe = await factory_2.SubServiceFactory.init(sub, service.namespace, service.appId, service.guid, service.logger);
77
62
  }
78
63
  async initStreamChannel(service, stream) {
79
- if ((0, utils_1.identifyRedisType)(stream) === 'redis') {
80
- service.stream = new redis_2.RedisStreamService(stream);
81
- }
82
- else {
83
- service.stream = new ioredis_2.IORedisStreamService(stream);
84
- }
85
- await service.stream.init(service.namespace, service.appId, service.logger);
64
+ service.stream = await factory_1.StreamServiceFactory.init(stream, service.namespace, service.appId, service.logger);
86
65
  }
87
66
  async initRouter(worker, logger) {
88
67
  const throttle = await this.store.getThrottleRate(worker.topic);
@@ -9,6 +9,7 @@ export { ActivityAction, DependencyExport, MeshFlowJobExport, ExportCycles, Expo
9
9
  export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal, } from './hook';
10
10
  export { ILogger, LogLevel } from './logger';
11
11
  export { ExtensionType, JobCompletionOptions, JobData, JobsData, JobInterruptOptions, JobMetadata, JobOutput, JobState, JobStatus, PartialJobState, } from './job';
12
+ export { DB, DBConfig, Profile, Namespaces, Entity, EntityInstanceTypes, SubClassInstance, AllSubclassInstances, SubclassType, Namespace, Instance, Instances, Profiles, } from './manifest';
12
13
  export { MappingStatements } from './map';
13
14
  export { Pipe, PipeContext, PipeItem, PipeItems, PipeObject, ReduceObject, } from './pipe';
14
15
  export { HotMesh, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshEngine, RedisConfig, HotMeshGraph, HotMeshManifest, HotMeshSettings, HotMeshWorker, KeyStoreParams, KeyType, } from './hotmesh';
@@ -0,0 +1,49 @@
1
+ import { MeshOS } from '../services/meshos';
2
+ import * as Types from './index';
3
+ export type DBConfig = {
4
+ REDIS_DATABASE: number;
5
+ REDIS_HOST: string | undefined;
6
+ REDIS_PORT: number;
7
+ REDIS_USERNAME: string;
8
+ REDIS_PASSWORD: string;
9
+ REDIS_USE_TLS: boolean;
10
+ };
11
+ export type DB = {
12
+ name: string;
13
+ label: string;
14
+ search: boolean;
15
+ config: DBConfig;
16
+ };
17
+ export type SubClassInstance<T extends typeof MeshOS> = T extends abstract new (...args: any) => infer R ? R : never;
18
+ export type AllSubclassInstances = SubClassInstance<(typeof MeshOS)['classes'][keyof (typeof MeshOS)['classes']]>;
19
+ export type EntityInstanceTypes = MeshOS;
20
+ export type SubclassType<T extends MeshOS = MeshOS> = new (...args: any[]) => T;
21
+ export type Entity = {
22
+ name: string;
23
+ label: string;
24
+ schema: Types.WorkflowSearchSchema;
25
+ class: SubclassType;
26
+ };
27
+ export type Namespace = {
28
+ name: string;
29
+ type: string;
30
+ label: string;
31
+ entities: Entity[];
32
+ };
33
+ export type Namespaces = {
34
+ [key: string]: Namespace;
35
+ };
36
+ export type Instance = {
37
+ [key: string]: EntityInstanceTypes;
38
+ };
39
+ export type Instances = {
40
+ [key: string]: Instance;
41
+ };
42
+ export type Profile = {
43
+ db: DB;
44
+ namespaces: Namespaces;
45
+ instances?: Instances;
46
+ };
47
+ export type Profiles = {
48
+ [key: string]: Profile;
49
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/index.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { MeshCall } from './services/meshcall';
2
- import { MeshData } from './services/meshdata';
3
- import { MeshFlow } from './services/meshflow';
4
1
  import { HotMesh } from './services/hotmesh';
5
2
  import { HotMeshConfig } from './types/hotmesh';
3
+ import { MeshCall } from './services/meshcall';
4
+ import { MeshFlow } from './services/meshflow';
5
+ import { MeshData } from './services/meshdata';
6
+ import { MeshOS } from './services/meshos';
6
7
 
7
- export { HotMesh, MeshCall, MeshData, MeshFlow, HotMeshConfig };
8
+ export { HotMesh, HotMeshConfig, MeshCall, MeshData, MeshFlow, MeshOS };
8
9
 
9
10
  export * as Types from './types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "Unbreakable Workflows",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/index.test.ts --detectOpenHandles --forceExit --verbose",
29
29
  "test:meshflow": "NODE_ENV=test jest ./tests/meshflow/*/index.test.ts --detectOpenHandles --forceExit --verbose",
30
30
  "test:meshflow:basic": "NODE_ENV=test jest ./tests/meshflow/basic/index.test.ts --detectOpenHandles --forceExit --verbose",
31
- "test:meshflow:collision": "NODE_ENV=test jest ./tests/meshflow/collision/index.test.ts --detectOpenHandles --forceExit --verbose",
31
+ "test:meshflow:collision": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/meshflow/collision/index.test.ts --detectOpenHandles --forceExit --verbose",
32
32
  "test:meshflow:fatal": "NODE_ENV=test jest ./tests/meshflow/fatal/index.test.ts --detectOpenHandles --forceExit --verbose",
33
33
  "test:meshflow:goodbye": "NODE_ENV=test jest ./tests/meshflow/goodbye/index.test.ts --detectOpenHandles --forceExit --verbose",
34
34
  "test:meshflow:hello": "HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/meshflow/helloworld/index.test.ts --detectOpenHandles --forceExit --verbose",
@@ -64,6 +64,7 @@
64
64
  "test:sub:redis": "NODE_ENV=test jest ./tests/functional/sub/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
65
65
  "test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
66
66
  "test:meshdata": "NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshdata/index.test.ts --forceExit --verbose --detectOpenHandles",
67
+ "test:meshos": "NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshos/index.test.ts --forceExit --verbose --detectOpenHandles",
67
68
  "test:meshcall": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/meshcall/index.test.ts --forceExit --verbose --detectOpenHandles",
68
69
  "test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose"
69
70
  },
package/typedoc.json CHANGED
@@ -14,6 +14,7 @@
14
14
  "services/meshflow/worker.ts",
15
15
  "services/meshflow/workflow.ts",
16
16
  "services/meshflow/connection.ts",
17
+ "services/meshos/index.ts",
17
18
  "types/*.ts"
18
19
  ],
19
20
  "highlightLanguages": [
package/types/index.ts CHANGED
@@ -91,6 +91,21 @@ export {
91
91
  JobStatus,
92
92
  PartialJobState,
93
93
  } from './job';
94
+ export {
95
+ DB,
96
+ DBConfig,
97
+ Profile,
98
+ Namespaces,
99
+ Entity,
100
+ EntityInstanceTypes,
101
+ SubClassInstance,
102
+ AllSubclassInstances,
103
+ SubclassType,
104
+ Namespace,
105
+ Instance,
106
+ Instances,
107
+ Profiles,
108
+ } from './manifest';
94
109
  export { MappingStatements } from './map';
95
110
  export {
96
111
  Pipe,
@@ -0,0 +1,68 @@
1
+ import { MeshOS } from '../services/meshos';
2
+
3
+ import * as Types from './index';
4
+
5
+ export type DBConfig = {
6
+ REDIS_DATABASE: number;
7
+ REDIS_HOST: string | undefined;
8
+ REDIS_PORT: number;
9
+ REDIS_USERNAME: string;
10
+ REDIS_PASSWORD: string;
11
+ REDIS_USE_TLS: boolean;
12
+ };
13
+
14
+ export type DB = {
15
+ name: string;
16
+ label: string;
17
+ search: boolean;
18
+ config: DBConfig;
19
+ };
20
+
21
+ export type SubClassInstance<T extends typeof MeshOS> = T extends abstract new (
22
+ ...args: any
23
+ ) => infer R
24
+ ? R
25
+ : never;
26
+ export type AllSubclassInstances = SubClassInstance<
27
+ (typeof MeshOS)['classes'][keyof (typeof MeshOS)['classes']]
28
+ >;
29
+
30
+ //export type EntityClassTypes = typeof SubclassType;
31
+ export type EntityInstanceTypes = MeshOS;
32
+
33
+ export type SubclassType<T extends MeshOS = MeshOS> = new (...args: any[]) => T;
34
+ export type Entity = {
35
+ name: string;
36
+ label: string;
37
+ schema: Types.WorkflowSearchSchema;
38
+ class: SubclassType;
39
+ };
40
+
41
+ export type Namespace = {
42
+ name: string;
43
+ type: string;
44
+ label: string;
45
+ entities: Entity[];
46
+ };
47
+
48
+ export type Namespaces = {
49
+ [key: string]: Namespace;
50
+ };
51
+
52
+ export type Instance = {
53
+ [key /*entity name*/ : string]: EntityInstanceTypes;
54
+ };
55
+
56
+ export type Instances = {
57
+ [key /*namespace abbreviation*/ : string]: Instance;
58
+ };
59
+
60
+ export type Profile = {
61
+ db: DB;
62
+ namespaces: Namespaces;
63
+ instances?: Instances;
64
+ };
65
+
66
+ export type Profiles = {
67
+ [key: string]: Profile;
68
+ };
package/types/meshflow.ts CHANGED
@@ -511,7 +511,7 @@ type FindJobsOptions = {
511
511
  /**
512
512
  * application namespace
513
513
  * @default meshflow
514
- */
514
+ */
515
515
  namespace?: string;
516
516
 
517
517
  /** The suggested response limit. Reduce batch size to reduce the likelihood of large overages. */