@hazeljs/data 0.2.0-beta.53 → 0.2.0-beta.55

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 (59) hide show
  1. package/dist/data.module.test.d.ts +2 -0
  2. package/dist/data.module.test.d.ts.map +1 -0
  3. package/dist/data.module.test.js +28 -0
  4. package/dist/decorators/pipeline.decorator.test.d.ts +2 -0
  5. package/dist/decorators/pipeline.decorator.test.d.ts.map +1 -0
  6. package/dist/decorators/pipeline.decorator.test.js +96 -0
  7. package/dist/flink.service.js +1 -1
  8. package/dist/flink.service.test.d.ts +2 -0
  9. package/dist/flink.service.test.d.ts.map +1 -0
  10. package/dist/flink.service.test.js +60 -0
  11. package/dist/pipelines/etl.service.js +1 -1
  12. package/dist/pipelines/etl.service.test.d.ts +2 -0
  13. package/dist/pipelines/etl.service.test.d.ts.map +1 -0
  14. package/dist/pipelines/etl.service.test.js +104 -0
  15. package/dist/pipelines/pipeline.base.test.d.ts +2 -0
  16. package/dist/pipelines/pipeline.base.test.d.ts.map +1 -0
  17. package/dist/pipelines/pipeline.base.test.js +38 -0
  18. package/dist/pipelines/pipeline.builder.js +1 -1
  19. package/dist/pipelines/pipeline.builder.test.d.ts +2 -0
  20. package/dist/pipelines/pipeline.builder.test.d.ts.map +1 -0
  21. package/dist/pipelines/pipeline.builder.test.js +37 -0
  22. package/dist/pipelines/stream.service.js +1 -1
  23. package/dist/pipelines/stream.service.test.d.ts +2 -0
  24. package/dist/pipelines/stream.service.test.d.ts.map +1 -0
  25. package/dist/pipelines/stream.service.test.js +54 -0
  26. package/dist/quality/quality.service.js +1 -1
  27. package/dist/quality/quality.service.test.d.ts +2 -0
  28. package/dist/quality/quality.service.test.d.ts.map +1 -0
  29. package/dist/quality/quality.service.test.js +34 -0
  30. package/dist/schema/schema.test.d.ts +2 -0
  31. package/dist/schema/schema.test.d.ts.map +1 -0
  32. package/dist/schema/schema.test.js +119 -0
  33. package/dist/streaming/flink/flink.client.test.d.ts +2 -0
  34. package/dist/streaming/flink/flink.client.test.d.ts.map +1 -0
  35. package/dist/streaming/flink/flink.client.test.js +59 -0
  36. package/dist/streaming/flink/flink.job.test.d.ts +2 -0
  37. package/dist/streaming/flink/flink.job.test.d.ts.map +1 -0
  38. package/dist/streaming/flink/flink.job.test.js +37 -0
  39. package/dist/streaming/flink/flink.operators.test.d.ts +2 -0
  40. package/dist/streaming/flink/flink.operators.test.d.ts.map +1 -0
  41. package/dist/streaming/flink/flink.operators.test.js +38 -0
  42. package/dist/streaming/stream.builder.test.d.ts +2 -0
  43. package/dist/streaming/stream.builder.test.d.ts.map +1 -0
  44. package/dist/streaming/stream.builder.test.js +59 -0
  45. package/dist/streaming/stream.processor.test.d.ts +2 -0
  46. package/dist/streaming/stream.processor.test.d.ts.map +1 -0
  47. package/dist/streaming/stream.processor.test.js +52 -0
  48. package/dist/transformers/built-in.transformers.test.d.ts +2 -0
  49. package/dist/transformers/built-in.transformers.test.d.ts.map +1 -0
  50. package/dist/transformers/built-in.transformers.test.js +57 -0
  51. package/dist/transformers/transformer.service.js +1 -1
  52. package/dist/transformers/transformer.service.test.d.ts +2 -0
  53. package/dist/transformers/transformer.service.test.d.ts.map +1 -0
  54. package/dist/transformers/transformer.service.test.js +32 -0
  55. package/dist/validators/schema.validator.js +1 -1
  56. package/dist/validators/schema.validator.test.d.ts +2 -0
  57. package/dist/validators/schema.validator.test.d.ts.map +1 -0
  58. package/dist/validators/schema.validator.test.js +42 -0
  59. package/package.json +2 -2
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data.module.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.module.test.d.ts","sourceRoot":"","sources":["../src/data.module.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const data_module_1 = require("./data.module");
4
+ describe('DataModule', () => {
5
+ describe('forRoot', () => {
6
+ it('returns dynamic module structure', () => {
7
+ const result = data_module_1.DataModule.forRoot();
8
+ expect(result).toHaveProperty('module', data_module_1.DataModule);
9
+ expect(result).toHaveProperty('providers');
10
+ expect(result).toHaveProperty('exports');
11
+ expect(Array.isArray(result.providers)).toBe(true);
12
+ });
13
+ it('includes flink config when specified', () => {
14
+ const result = data_module_1.DataModule.forRoot({
15
+ flink: { url: 'http://flink:8081', timeout: 5000 },
16
+ });
17
+ const flinkConfig = result.providers.find((p) => p && typeof p === 'object' && 'provide' in p);
18
+ expect(flinkConfig).toBeDefined();
19
+ });
20
+ });
21
+ describe('getOptions', () => {
22
+ it('returns last forRoot options', () => {
23
+ data_module_1.DataModule.forRoot({ flink: { url: 'http://custom:8081' } });
24
+ const opts = data_module_1.DataModule.getOptions();
25
+ expect(opts.flink?.url).toBe('http://custom:8081');
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,2 @@
1
+ import 'reflect-metadata';
2
+ //# sourceMappingURL=pipeline.decorator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.decorator.test.d.ts","sourceRoot":"","sources":["../../src/decorators/pipeline.decorator.test.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ require("reflect-metadata");
13
+ const pipeline_decorator_1 = require("./pipeline.decorator");
14
+ const transform_decorator_1 = require("./transform.decorator");
15
+ const validate_decorator_1 = require("./validate.decorator");
16
+ const stream_decorator_1 = require("./stream.decorator");
17
+ const schema_1 = require("../schema/schema");
18
+ describe('Pipeline decorator', () => {
19
+ it('applies metadata with string name', () => {
20
+ let TestPipeline = class TestPipeline {
21
+ };
22
+ TestPipeline = __decorate([
23
+ (0, pipeline_decorator_1.Pipeline)('my-pipeline')
24
+ ], TestPipeline);
25
+ const meta = (0, pipeline_decorator_1.getPipelineMetadata)(TestPipeline);
26
+ expect(meta?.name).toBe('my-pipeline');
27
+ expect((0, pipeline_decorator_1.hasPipelineMetadata)(TestPipeline)).toBe(true);
28
+ });
29
+ it('applies metadata with options object', () => {
30
+ let CustomPipeline = class CustomPipeline {
31
+ };
32
+ CustomPipeline = __decorate([
33
+ (0, pipeline_decorator_1.Pipeline)({ name: 'custom' })
34
+ ], CustomPipeline);
35
+ expect((0, pipeline_decorator_1.getPipelineMetadata)(CustomPipeline)?.name).toBe('custom');
36
+ });
37
+ });
38
+ describe('Transform decorator', () => {
39
+ it('applies step metadata', () => {
40
+ class TestClass {
41
+ normalize() { }
42
+ }
43
+ __decorate([
44
+ (0, transform_decorator_1.Transform)({ step: 1, name: 'normalize' }),
45
+ __metadata("design:type", Function),
46
+ __metadata("design:paramtypes", []),
47
+ __metadata("design:returntype", void 0)
48
+ ], TestClass.prototype, "normalize", null);
49
+ const meta = (0, transform_decorator_1.getTransformMetadata)(TestClass.prototype, 'normalize');
50
+ expect(meta?.step).toBe(1);
51
+ expect(meta?.name).toBe('normalize');
52
+ expect(meta?.type).toBe('transform');
53
+ });
54
+ });
55
+ describe('Validate decorator', () => {
56
+ it('applies schema metadata', () => {
57
+ const schema = schema_1.Schema.object({ email: schema_1.Schema.string().email() });
58
+ class TestClass {
59
+ validate() { }
60
+ }
61
+ __decorate([
62
+ (0, validate_decorator_1.Validate)({ step: 2, name: 'validate', schema }),
63
+ __metadata("design:type", Function),
64
+ __metadata("design:paramtypes", []),
65
+ __metadata("design:returntype", void 0)
66
+ ], TestClass.prototype, "validate", null);
67
+ const meta = (0, validate_decorator_1.getValidateMetadata)(TestClass.prototype, 'validate');
68
+ expect(meta?.step).toBe(2);
69
+ expect(meta?.schema).toBe(schema);
70
+ });
71
+ });
72
+ describe('Stream decorator', () => {
73
+ it('applies stream metadata', () => {
74
+ let StreamPipeline = class StreamPipeline {
75
+ };
76
+ StreamPipeline = __decorate([
77
+ (0, stream_decorator_1.Stream)({
78
+ name: 'events',
79
+ source: 'kafka://topic',
80
+ sink: 'kafka://out',
81
+ parallelism: 8,
82
+ })
83
+ ], StreamPipeline);
84
+ const meta = (0, stream_decorator_1.getStreamMetadata)(StreamPipeline);
85
+ expect(meta?.name).toBe('events');
86
+ expect(meta?.source).toBe('kafka://topic');
87
+ expect(meta?.sink).toBe('kafka://out');
88
+ expect(meta?.parallelism).toBe(8);
89
+ expect((0, stream_decorator_1.hasStreamMetadata)(StreamPipeline)).toBe(true);
90
+ });
91
+ it('hasStreamMetadata false for undecorated', () => {
92
+ class Plain {
93
+ }
94
+ expect((0, stream_decorator_1.hasStreamMetadata)(Plain)).toBe(false);
95
+ });
96
+ });
@@ -80,7 +80,7 @@ let FlinkService = class FlinkService {
80
80
  };
81
81
  exports.FlinkService = FlinkService;
82
82
  exports.FlinkService = FlinkService = __decorate([
83
- (0, core_1.Injectable)(),
83
+ (0, core_1.Service)(),
84
84
  __metadata("design:paramtypes", [etl_service_1.ETLService,
85
85
  stream_builder_1.StreamBuilder])
86
86
  ], FlinkService);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flink.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.service.test.d.ts","sourceRoot":"","sources":["../src/flink.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const flink_service_1 = require("./flink.service");
13
+ const etl_service_1 = require("./pipelines/etl.service");
14
+ const stream_builder_1 = require("./streaming/stream.builder");
15
+ const schema_validator_1 = require("./validators/schema.validator");
16
+ const decorators_1 = require("./decorators");
17
+ let TestPipeline = class TestPipeline {
18
+ a(data) {
19
+ return data;
20
+ }
21
+ };
22
+ __decorate([
23
+ (0, decorators_1.Transform)({ step: 1, name: 'a' }),
24
+ __metadata("design:type", Function),
25
+ __metadata("design:paramtypes", [Object]),
26
+ __metadata("design:returntype", void 0)
27
+ ], TestPipeline.prototype, "a", null);
28
+ TestPipeline = __decorate([
29
+ (0, decorators_1.Stream)({ name: 'test', source: 'kafka://in', sink: 'kafka://out', parallelism: 2 })
30
+ ], TestPipeline);
31
+ describe('FlinkService', () => {
32
+ let service;
33
+ beforeEach(() => {
34
+ const etlService = new etl_service_1.ETLService(new schema_validator_1.SchemaValidator());
35
+ const streamBuilder = new stream_builder_1.StreamBuilder(etlService);
36
+ service = new flink_service_1.FlinkService(etlService, streamBuilder);
37
+ });
38
+ it('getClient throws when not configured', () => {
39
+ expect(() => service.getClient()).toThrow('FlinkService not configured');
40
+ });
41
+ it('configure sets up client', () => {
42
+ service.configure({ url: 'http://flink:8081' });
43
+ const client = service.getClient();
44
+ expect(client.url).toBe('http://flink:8081');
45
+ });
46
+ it('deployStream returns job config', async () => {
47
+ service.configure({ url: 'http://localhost:8081' });
48
+ const pipeline = new TestPipeline();
49
+ const result = await service.deployStream(pipeline);
50
+ expect(result.status).toBe('config_generated');
51
+ expect(result.jobConfig).toBeDefined();
52
+ expect(result.jobConfig.jobName).toBe('TestPipeline');
53
+ expect(result.jobGraph).toBeDefined();
54
+ });
55
+ it('deployStream with config override', async () => {
56
+ service.configure({ url: 'http://localhost:8081' });
57
+ const result = await service.deployStream(new TestPipeline(), { parallelism: 16 });
58
+ expect(result.jobConfig.parallelism).toBe(16);
59
+ });
60
+ });
@@ -81,6 +81,6 @@ let ETLService = class ETLService {
81
81
  };
82
82
  exports.ETLService = ETLService;
83
83
  exports.ETLService = ETLService = __decorate([
84
- (0, core_1.Injectable)(),
84
+ (0, core_1.Service)(),
85
85
  __metadata("design:paramtypes", [schema_validator_1.SchemaValidator])
86
86
  ], ETLService);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=etl.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"etl.service.test.d.ts","sourceRoot":"","sources":["../../src/pipelines/etl.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const etl_service_1 = require("./etl.service");
13
+ const schema_validator_1 = require("../validators/schema.validator");
14
+ const decorators_1 = require("../decorators");
15
+ const schema_1 = require("../schema/schema");
16
+ let TestPipeline = class TestPipeline {
17
+ double(data) {
18
+ const n = data.x;
19
+ return { x: n * 2 };
20
+ }
21
+ validate(data) {
22
+ return data;
23
+ }
24
+ add(data) {
25
+ return { ...data, y: 10 };
26
+ }
27
+ };
28
+ __decorate([
29
+ (0, decorators_1.Transform)({ step: 1, name: 'double' }),
30
+ __metadata("design:type", Function),
31
+ __metadata("design:paramtypes", [Object]),
32
+ __metadata("design:returntype", void 0)
33
+ ], TestPipeline.prototype, "double", null);
34
+ __decorate([
35
+ (0, decorators_1.Validate)({
36
+ step: 2,
37
+ name: 'validate',
38
+ schema: schema_1.Schema.object({ x: schema_1.Schema.number().min(0) }),
39
+ }),
40
+ __metadata("design:type", Function),
41
+ __metadata("design:paramtypes", [Object]),
42
+ __metadata("design:returntype", void 0)
43
+ ], TestPipeline.prototype, "validate", null);
44
+ __decorate([
45
+ (0, decorators_1.Transform)({ step: 3, name: 'add' }),
46
+ __metadata("design:type", Function),
47
+ __metadata("design:paramtypes", [Object]),
48
+ __metadata("design:returntype", void 0)
49
+ ], TestPipeline.prototype, "add", null);
50
+ TestPipeline = __decorate([
51
+ (0, decorators_1.Pipeline)('test-pipeline')
52
+ ], TestPipeline);
53
+ let TransformOnlyPipeline = class TransformOnlyPipeline {
54
+ a(data) {
55
+ return { ...data, a: 1 };
56
+ }
57
+ };
58
+ __decorate([
59
+ (0, decorators_1.Transform)({ step: 1, name: 'a' }),
60
+ __metadata("design:type", Function),
61
+ __metadata("design:paramtypes", [Object]),
62
+ __metadata("design:returntype", void 0)
63
+ ], TransformOnlyPipeline.prototype, "a", null);
64
+ TransformOnlyPipeline = __decorate([
65
+ (0, decorators_1.Pipeline)('transform-only')
66
+ ], TransformOnlyPipeline);
67
+ let NoStepsPipeline = class NoStepsPipeline {
68
+ };
69
+ NoStepsPipeline = __decorate([
70
+ (0, decorators_1.Pipeline)('no-steps')
71
+ ], NoStepsPipeline);
72
+ describe('ETLService', () => {
73
+ let etlService;
74
+ beforeEach(() => {
75
+ etlService = new etl_service_1.ETLService(new schema_validator_1.SchemaValidator());
76
+ });
77
+ it('executes pipeline steps sequentially', async () => {
78
+ const pipeline = new TestPipeline();
79
+ const result = await etlService.execute(pipeline, { x: 5 });
80
+ expect(result).toEqual({ x: 10, y: 10 });
81
+ });
82
+ it('extractSteps returns sorted steps', () => {
83
+ const pipeline = new TestPipeline();
84
+ const steps = etlService.extractSteps(pipeline);
85
+ expect(steps).toHaveLength(3);
86
+ expect(steps[0].step).toBe(1);
87
+ expect(steps[1].step).toBe(2);
88
+ expect(steps[2].step).toBe(3);
89
+ });
90
+ it('throws when pipeline has no steps', async () => {
91
+ const pipeline = new NoStepsPipeline();
92
+ await expect(etlService.execute(pipeline, {})).rejects.toThrow('has no steps');
93
+ });
94
+ it('validates data at validate step', async () => {
95
+ const pipeline = new TestPipeline();
96
+ await expect(etlService.execute(pipeline, { x: -1 })).rejects.toThrow();
97
+ });
98
+ it('extractSteps returns only transform/validate steps', () => {
99
+ const pipeline = new TransformOnlyPipeline();
100
+ const steps = etlService.extractSteps(pipeline);
101
+ expect(steps).toHaveLength(1);
102
+ expect(steps[0].type).toBe('transform');
103
+ });
104
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline.base.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.base.test.d.ts","sourceRoot":"","sources":["../../src/pipelines/pipeline.base.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const pipeline_base_1 = require("./pipeline.base");
13
+ const etl_service_1 = require("./etl.service");
14
+ const schema_validator_1 = require("../validators/schema.validator");
15
+ const decorators_1 = require("../decorators");
16
+ let TestPipeline = class TestPipeline extends pipeline_base_1.PipelineBase {
17
+ double(data) {
18
+ const x = data.x;
19
+ return { x: x * 2 };
20
+ }
21
+ };
22
+ __decorate([
23
+ (0, decorators_1.Transform)({ step: 1, name: 'double' }),
24
+ __metadata("design:type", Function),
25
+ __metadata("design:paramtypes", [Object]),
26
+ __metadata("design:returntype", void 0)
27
+ ], TestPipeline.prototype, "double", null);
28
+ TestPipeline = __decorate([
29
+ (0, decorators_1.Pipeline)('base-test')
30
+ ], TestPipeline);
31
+ describe('PipelineBase', () => {
32
+ it('execute runs pipeline via ETLService', async () => {
33
+ const etlService = new etl_service_1.ETLService(new schema_validator_1.SchemaValidator());
34
+ const pipeline = new TestPipeline(etlService);
35
+ const result = await pipeline.execute({ x: 5 });
36
+ expect(result).toEqual({ x: 10 });
37
+ });
38
+ });
@@ -58,5 +58,5 @@ let PipelineBuilder = class PipelineBuilder {
58
58
  };
59
59
  exports.PipelineBuilder = PipelineBuilder;
60
60
  exports.PipelineBuilder = PipelineBuilder = __decorate([
61
- (0, core_1.Injectable)()
61
+ (0, core_1.Service)()
62
62
  ], PipelineBuilder);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline.builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.builder.test.d.ts","sourceRoot":"","sources":["../../src/pipelines/pipeline.builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pipeline_builder_1 = require("./pipeline.builder");
4
+ describe('PipelineBuilder', () => {
5
+ let builder;
6
+ beforeEach(() => {
7
+ builder = new pipeline_builder_1.PipelineBuilder();
8
+ });
9
+ it('adds transform and executes', async () => {
10
+ builder.addTransform('step1', (d) => Object.assign({}, d, { a: 1 }));
11
+ builder.addTransform('step2', (d) => Object.assign({}, d, { b: 2 }));
12
+ const result = await builder.execute({ x: 0 });
13
+ expect(result).toEqual({ x: 0, a: 1, b: 2 });
14
+ });
15
+ it('handles async transforms', async () => {
16
+ builder.addTransform('async', async (d) => Object.assign({}, d, { done: true }));
17
+ const result = await builder.execute({});
18
+ expect(result.done).toBe(true);
19
+ });
20
+ it('setName sets pipeline name', () => {
21
+ builder.setName('my-pipeline');
22
+ const built = builder.build();
23
+ expect(built.name).toBe('my-pipeline');
24
+ });
25
+ it('build returns config', () => {
26
+ builder.addTransform('s1', (d) => d).addValidate('s2', (d) => d);
27
+ const config = builder.build();
28
+ expect(config.steps).toHaveLength(2);
29
+ expect(config.name).toBe('unnamed-pipeline');
30
+ });
31
+ it('reset clears steps', async () => {
32
+ builder.addTransform('s1', (d) => d);
33
+ builder.reset();
34
+ const config = builder.build();
35
+ expect(config.steps).toHaveLength(0);
36
+ });
37
+ });
@@ -53,6 +53,6 @@ let StreamService = class StreamService {
53
53
  };
54
54
  exports.StreamService = StreamService;
55
55
  exports.StreamService = StreamService = __decorate([
56
- (0, core_1.Injectable)(),
56
+ (0, core_1.Service)(),
57
57
  __metadata("design:paramtypes", [etl_service_1.ETLService])
58
58
  ], StreamService);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stream.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.service.test.d.ts","sourceRoot":"","sources":["../../src/pipelines/stream.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const etl_service_1 = require("./etl.service");
13
+ const stream_service_1 = require("./stream.service");
14
+ const schema_validator_1 = require("../validators/schema.validator");
15
+ const decorators_1 = require("../decorators");
16
+ let BatchTestPipeline = class BatchTestPipeline {
17
+ inc(data) {
18
+ return { v: (data.v || 0) + 1 };
19
+ }
20
+ };
21
+ __decorate([
22
+ (0, decorators_1.Transform)({ step: 1, name: 'inc' }),
23
+ __metadata("design:type", Function),
24
+ __metadata("design:paramtypes", [Object]),
25
+ __metadata("design:returntype", void 0)
26
+ ], BatchTestPipeline.prototype, "inc", null);
27
+ BatchTestPipeline = __decorate([
28
+ (0, decorators_1.Pipeline)('batch-test'),
29
+ (0, decorators_1.Stream)({ name: 'test', source: 'kafka://in', sink: 'kafka://out' })
30
+ ], BatchTestPipeline);
31
+ describe('StreamService', () => {
32
+ let streamService;
33
+ beforeEach(() => {
34
+ const etlService = new etl_service_1.ETLService(new schema_validator_1.SchemaValidator());
35
+ streamService = new stream_service_1.StreamService(etlService);
36
+ });
37
+ it('processes batch of items', async () => {
38
+ const pipeline = new BatchTestPipeline();
39
+ const results = await streamService.processBatch(pipeline, [{ v: 0 }, { v: 1 }]);
40
+ expect(results).toEqual([{ v: 1 }, { v: 2 }]);
41
+ });
42
+ it('processStream yields results', async () => {
43
+ const pipeline = new BatchTestPipeline();
44
+ async function* source() {
45
+ yield { v: 0 };
46
+ yield { v: 5 };
47
+ }
48
+ const results = [];
49
+ for await (const r of streamService.processStream(pipeline, source())) {
50
+ results.push(r);
51
+ }
52
+ expect(results).toEqual([{ v: 1 }, { v: 6 }]);
53
+ });
54
+ });
@@ -83,5 +83,5 @@ let QualityService = class QualityService {
83
83
  };
84
84
  exports.QualityService = QualityService;
85
85
  exports.QualityService = QualityService = __decorate([
86
- (0, core_1.Injectable)()
86
+ (0, core_1.Service)()
87
87
  ], QualityService);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=quality.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.service.test.d.ts","sourceRoot":"","sources":["../../src/quality/quality.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const quality_service_1 = require("./quality.service");
4
+ describe('QualityService', () => {
5
+ let service;
6
+ beforeEach(() => {
7
+ service = new quality_service_1.QualityService();
8
+ });
9
+ it('runs registered checks', async () => {
10
+ service.registerCheck('custom', (data) => ({
11
+ name: 'custom',
12
+ passed: data.ok === true,
13
+ }));
14
+ const report = await service.runChecks('test', { ok: true });
15
+ expect(report.checks).toHaveLength(1);
16
+ expect(report.checks[0].passed).toBe(true);
17
+ expect(report.passed).toBe(true);
18
+ });
19
+ it('completeness check', () => {
20
+ const check = service.completeness(['email', 'name']);
21
+ expect(check({ email: 'a@b.com', name: 'x' }).passed).toBe(true);
22
+ expect(check({ email: 'a@b.com' }).passed).toBe(false);
23
+ });
24
+ it('notNull check', () => {
25
+ const check = service.notNull(['id']);
26
+ expect(check({ id: 1 }).passed).toBe(true);
27
+ expect(check({ id: null }).passed).toBe(false);
28
+ });
29
+ it('report includes totalRows', async () => {
30
+ service.registerCheck('dummy', () => ({ name: 'dummy', passed: true }));
31
+ const report = await service.runChecks('ds', [{}, {}]);
32
+ expect(report.totalRows).toBe(2);
33
+ });
34
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../../src/schema/schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("./schema");
4
+ describe('Schema', () => {
5
+ describe('string', () => {
6
+ it('validates string', () => {
7
+ const result = schema_1.Schema.string().validate('hello');
8
+ expect(result.success).toBe(true);
9
+ if (result.success)
10
+ expect(result.data).toBe('hello');
11
+ });
12
+ it('rejects non-string', () => {
13
+ const result = schema_1.Schema.string().validate(123);
14
+ expect(result.success).toBe(false);
15
+ if (!result.success)
16
+ expect(result.errors[0].message).toBe('Expected string');
17
+ });
18
+ it('email validation', () => {
19
+ expect(schema_1.Schema.string().email().validate('a@b.com').success).toBe(true);
20
+ expect(schema_1.Schema.string().email().validate('invalid').success).toBe(false);
21
+ });
22
+ it('min length', () => {
23
+ expect(schema_1.Schema.string().min(3).validate('abc').success).toBe(true);
24
+ expect(schema_1.Schema.string().min(3).validate('ab').success).toBe(false);
25
+ });
26
+ it('max length', () => {
27
+ expect(schema_1.Schema.string().max(3).validate('abc').success).toBe(true);
28
+ expect(schema_1.Schema.string().max(2).validate('abc').success).toBe(false);
29
+ });
30
+ it('uuid validation', () => {
31
+ const valid = '550e8400-e29b-41d4-a716-446655440000';
32
+ expect(schema_1.Schema.string().uuid().validate(valid).success).toBe(true);
33
+ expect(schema_1.Schema.string().uuid().validate('not-uuid').success).toBe(false);
34
+ });
35
+ it('oneOf validation', () => {
36
+ expect(schema_1.Schema.string().oneOf(['a', 'b']).validate('a').success).toBe(true);
37
+ expect(schema_1.Schema.string().oneOf(['a', 'b']).validate('c').success).toBe(false);
38
+ });
39
+ });
40
+ describe('number', () => {
41
+ it('validates number', () => {
42
+ const result = schema_1.Schema.number().validate(42);
43
+ expect(result.success).toBe(true);
44
+ if (result.success)
45
+ expect(result.data).toBe(42);
46
+ });
47
+ it('rejects non-number', () => {
48
+ expect(schema_1.Schema.number().validate('42').success).toBe(false);
49
+ expect(schema_1.Schema.number().validate(NaN).success).toBe(false);
50
+ });
51
+ it('min/max', () => {
52
+ expect(schema_1.Schema.number().min(0).max(100).validate(50).success).toBe(true);
53
+ expect(schema_1.Schema.number().min(0).validate(-1).success).toBe(false);
54
+ expect(schema_1.Schema.number().max(10).validate(11).success).toBe(false);
55
+ });
56
+ });
57
+ describe('date', () => {
58
+ it('validates Date', () => {
59
+ const d = new Date();
60
+ const result = schema_1.Schema.date().validate(d);
61
+ expect(result.success).toBe(true);
62
+ if (result.success)
63
+ expect(result.data).toBe(d);
64
+ });
65
+ it('validates date string', () => {
66
+ const result = schema_1.Schema.date().validate('2024-01-01');
67
+ expect(result.success).toBe(true);
68
+ });
69
+ it('rejects invalid date', () => {
70
+ expect(schema_1.Schema.date().validate('invalid').success).toBe(false);
71
+ expect(schema_1.Schema.date().validate({}).success).toBe(false);
72
+ });
73
+ });
74
+ describe('object', () => {
75
+ it('validates object shape', () => {
76
+ const schema = schema_1.Schema.object({
77
+ name: schema_1.Schema.string(),
78
+ age: schema_1.Schema.number(),
79
+ });
80
+ const result = schema.validate({ name: 'John', age: 30 });
81
+ expect(result.success).toBe(true);
82
+ if (result.success) {
83
+ expect(result.data.name).toBe('John');
84
+ expect(result.data.age).toBe(30);
85
+ }
86
+ });
87
+ it('rejects invalid fields', () => {
88
+ const schema = schema_1.Schema.object({
89
+ age: schema_1.Schema.number(),
90
+ });
91
+ const result = schema.validate({ age: 'thirty' });
92
+ expect(result.success).toBe(false);
93
+ if (!result.success)
94
+ expect(result.errors.length).toBeGreaterThan(0);
95
+ });
96
+ it('rejects non-object', () => {
97
+ expect(schema_1.Schema.object({}).validate('str').success).toBe(false);
98
+ expect(schema_1.Schema.object({}).validate(null).success).toBe(false);
99
+ expect(schema_1.Schema.object({}).validate([]).success).toBe(false);
100
+ });
101
+ });
102
+ describe('array', () => {
103
+ it('validates array of items', () => {
104
+ const schema = schema_1.Schema.array(schema_1.Schema.number());
105
+ const result = schema.validate([1, 2, 3]);
106
+ expect(result.success).toBe(true);
107
+ if (result.success)
108
+ expect(result.data).toEqual([1, 2, 3]);
109
+ });
110
+ it('rejects invalid items', () => {
111
+ const schema = schema_1.Schema.array(schema_1.Schema.number());
112
+ const result = schema.validate([1, 'two', 3]);
113
+ expect(result.success).toBe(false);
114
+ });
115
+ it('rejects non-array', () => {
116
+ expect(schema_1.Schema.array(schema_1.Schema.string()).validate({}).success).toBe(false);
117
+ });
118
+ });
119
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flink.client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.client.test.d.ts","sourceRoot":"","sources":["../../../src/streaming/flink/flink.client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const flink_client_1 = require("./flink.client");
4
+ // Mock fetch for Flink REST API
5
+ const mockFetch = jest.fn();
6
+ describe('FlinkClient', () => {
7
+ let client;
8
+ beforeAll(() => {
9
+ global.fetch = mockFetch;
10
+ });
11
+ beforeEach(() => {
12
+ mockFetch.mockReset();
13
+ client = new flink_client_1.FlinkClient({ url: 'http://localhost:8081' });
14
+ });
15
+ it('listJobs fetches job overview', async () => {
16
+ mockFetch.mockResolvedValue({
17
+ ok: true,
18
+ text: () => Promise.resolve(JSON.stringify({
19
+ jobs: [
20
+ { id: 'j1', status: 'RUNNING', 'start-time': 123, 'end-time': 456, duration: 100 },
21
+ ],
22
+ })),
23
+ });
24
+ const jobs = await client.listJobs();
25
+ expect(jobs).toHaveLength(1);
26
+ expect(jobs[0].id).toBe('j1');
27
+ expect(jobs[0].status).toBe('RUNNING');
28
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:8081/jobs/overview', expect.any(Object));
29
+ });
30
+ it('getJobStatus fetches job details', async () => {
31
+ mockFetch.mockResolvedValue({
32
+ ok: true,
33
+ text: () => Promise.resolve(JSON.stringify({ state: 'RUNNING', 'start-time': 123, duration: 500 })),
34
+ });
35
+ const status = await client.getJobStatus('j1');
36
+ expect(status.state).toBe('RUNNING');
37
+ expect(status.duration).toBe(500);
38
+ });
39
+ it('throws on API error', async () => {
40
+ mockFetch.mockResolvedValue({ ok: false, text: () => Promise.resolve('Not found') });
41
+ await expect(client.getJobStatus('bad')).rejects.toThrow('Flink API error');
42
+ });
43
+ it('submitJob throws with helpful message', async () => {
44
+ await expect(client.submitJob({})).rejects.toThrow('submitJob: Full Flink deployment requires');
45
+ });
46
+ it('getClusterInfo', async () => {
47
+ mockFetch.mockResolvedValue({
48
+ ok: true,
49
+ text: () => Promise.resolve(JSON.stringify({ taskmanagers: 2, 'slots-total': 8 })),
50
+ });
51
+ const info = await client.getClusterInfo();
52
+ expect(info.taskmanagers).toBe(2);
53
+ });
54
+ it('cancelJob', async () => {
55
+ mockFetch.mockResolvedValue({ ok: true, text: () => Promise.resolve('') });
56
+ await client.cancelJob('j1');
57
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('mode=cancel'), expect.any(Object));
58
+ });
59
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flink.job.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.job.test.d.ts","sourceRoot":"","sources":["../../../src/streaming/flink/flink.job.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const flink_client_1 = require("./flink.client");
4
+ const flink_job_1 = require("./flink.job");
5
+ const mockFetch = jest.fn();
6
+ describe('FlinkJob', () => {
7
+ let job;
8
+ beforeAll(() => {
9
+ global.fetch = mockFetch;
10
+ });
11
+ beforeEach(() => {
12
+ mockFetch.mockReset();
13
+ const client = new flink_client_1.FlinkClient({ url: 'http://localhost:8081' });
14
+ job = new flink_job_1.FlinkJob(client);
15
+ });
16
+ it('getStatus fetches job status', async () => {
17
+ mockFetch.mockResolvedValue({
18
+ ok: true,
19
+ text: () => Promise.resolve(JSON.stringify({ state: 'RUNNING', duration: 100 })),
20
+ });
21
+ const status = await job.getStatus('j1');
22
+ expect(status.state).toBe('RUNNING');
23
+ });
24
+ it('cancel calls cancel endpoint', async () => {
25
+ mockFetch.mockResolvedValue({ ok: true, text: () => Promise.resolve('') });
26
+ await job.cancel('j1');
27
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('/jobs/j1'), expect.any(Object));
28
+ });
29
+ it('createSavepoint', async () => {
30
+ mockFetch.mockResolvedValue({
31
+ ok: true,
32
+ text: () => Promise.resolve(JSON.stringify({ 'request-id': 'req-1' })),
33
+ });
34
+ const result = await job.createSavepoint('j1', '/path');
35
+ expect(result['request-id']).toBe('req-1');
36
+ });
37
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flink.operators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.operators.test.d.ts","sourceRoot":"","sources":["../../../src/streaming/flink/flink.operators.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const flink_operators_1 = require("./flink.operators");
4
+ describe('flink operators', () => {
5
+ describe('mapToFlinkOperator', () => {
6
+ it('maps transform step to map operator', () => {
7
+ const step = {
8
+ step: 1,
9
+ name: 'parse',
10
+ type: 'transform',
11
+ method: 'parse',
12
+ };
13
+ const op = (0, flink_operators_1.mapToFlinkOperator)(step);
14
+ expect(op.type).toBe('map');
15
+ expect(op.step).toBe(1);
16
+ expect(op.name).toBe('parse');
17
+ });
18
+ it('maps validate step to filter operator', () => {
19
+ const step = {
20
+ step: 2,
21
+ name: 'validate',
22
+ type: 'validate',
23
+ method: 'validate',
24
+ };
25
+ const op = (0, flink_operators_1.mapToFlinkOperator)(step);
26
+ expect(op.type).toBe('filter');
27
+ });
28
+ });
29
+ describe('createFlinkJobGraph', () => {
30
+ it('creates job graph with source, sink, transformations', () => {
31
+ const steps = [{ step: 1, name: 't1', type: 'transform', method: 't1' }];
32
+ const graph = (0, flink_operators_1.createFlinkJobGraph)(steps, { type: 'kafka', topic: 'in', properties: {} }, { type: 'kafka', topic: 'out', properties: {} });
33
+ expect(graph.source.topic).toBe('in');
34
+ expect(graph.sink.topic).toBe('out');
35
+ expect(graph.transformations).toHaveLength(1);
36
+ });
37
+ });
38
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stream.builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.builder.test.d.ts","sourceRoot":"","sources":["../../src/streaming/stream.builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const etl_service_1 = require("../pipelines/etl.service");
13
+ const stream_builder_1 = require("./stream.builder");
14
+ const schema_validator_1 = require("../validators/schema.validator");
15
+ const decorators_1 = require("../decorators");
16
+ let TestStreamPipeline = class TestStreamPipeline {
17
+ parse(data) {
18
+ return data;
19
+ }
20
+ };
21
+ __decorate([
22
+ (0, decorators_1.Transform)({ step: 1, name: 'parse' }),
23
+ __metadata("design:type", Function),
24
+ __metadata("design:paramtypes", [Object]),
25
+ __metadata("design:returntype", void 0)
26
+ ], TestStreamPipeline.prototype, "parse", null);
27
+ TestStreamPipeline = __decorate([
28
+ (0, decorators_1.Stream)({
29
+ name: 'test-stream',
30
+ source: 'kafka://events',
31
+ sink: 'kafka://processed',
32
+ parallelism: 4,
33
+ })
34
+ ], TestStreamPipeline);
35
+ describe('StreamBuilder', () => {
36
+ let builder;
37
+ beforeEach(() => {
38
+ builder = new stream_builder_1.StreamBuilder(new etl_service_1.ETLService(new schema_validator_1.SchemaValidator()));
39
+ });
40
+ it('builds config from @Stream pipeline', () => {
41
+ const pipeline = new TestStreamPipeline();
42
+ const { jobConfig, jobGraph } = builder.buildConfig(pipeline);
43
+ expect(jobConfig.jobName).toBe('TestStreamPipeline');
44
+ expect(jobConfig.parallelism).toBe(4);
45
+ expect(jobGraph.source.topic).toBe('events');
46
+ expect(jobGraph.sink.topic).toBe('processed');
47
+ expect(jobGraph.transformations).toHaveLength(1);
48
+ });
49
+ it('allows config override', () => {
50
+ const pipeline = new TestStreamPipeline();
51
+ const { jobConfig } = builder.buildConfig(pipeline, { parallelism: 8 });
52
+ expect(jobConfig.parallelism).toBe(8);
53
+ });
54
+ it('throws when pipeline not @Stream decorated', () => {
55
+ class PlainPipeline {
56
+ }
57
+ expect(() => builder.buildConfig(new PlainPipeline())).toThrow('Pipeline must be decorated with @Stream');
58
+ });
59
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stream.processor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.processor.test.d.ts","sourceRoot":"","sources":["../../src/streaming/stream.processor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const stream_processor_1 = require("./stream.processor");
13
+ const etl_service_1 = require("../pipelines/etl.service");
14
+ const schema_validator_1 = require("../validators/schema.validator");
15
+ const decorators_1 = require("../decorators");
16
+ let ProcTestPipeline = class ProcTestPipeline {
17
+ inc(data) {
18
+ return { v: (data.v || 0) + 1 };
19
+ }
20
+ };
21
+ __decorate([
22
+ (0, decorators_1.Transform)({ step: 1, name: 'inc' }),
23
+ __metadata("design:type", Function),
24
+ __metadata("design:paramtypes", [Object]),
25
+ __metadata("design:returntype", void 0)
26
+ ], ProcTestPipeline.prototype, "inc", null);
27
+ ProcTestPipeline = __decorate([
28
+ (0, decorators_1.Pipeline)('proc-test')
29
+ ], ProcTestPipeline);
30
+ describe('StreamProcessor', () => {
31
+ let processor;
32
+ beforeEach(() => {
33
+ processor = new stream_processor_1.StreamProcessor(new etl_service_1.ETLService(new schema_validator_1.SchemaValidator()));
34
+ });
35
+ it('processItem runs pipeline on single item', async () => {
36
+ const pipeline = new ProcTestPipeline();
37
+ const result = await processor.processItem(pipeline, { v: 0 });
38
+ expect(result).toEqual({ v: 1 });
39
+ });
40
+ it('processStream yields processed items', async () => {
41
+ const pipeline = new ProcTestPipeline();
42
+ async function* gen() {
43
+ yield { v: 1 };
44
+ yield { v: 2 };
45
+ }
46
+ const results = [];
47
+ for await (const r of processor.processStream(pipeline, gen())) {
48
+ results.push(r);
49
+ }
50
+ expect(results).toEqual([{ v: 2 }, { v: 3 }]);
51
+ });
52
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=built-in.transformers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in.transformers.test.d.ts","sourceRoot":"","sources":["../../src/transformers/built-in.transformers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const built_in_transformers_1 = require("./built-in.transformers");
4
+ describe('built-in transformers', () => {
5
+ describe('trimString', () => {
6
+ it('trims whitespace', () => {
7
+ expect((0, built_in_transformers_1.trimString)(' hi ')).toBe('hi');
8
+ });
9
+ it('converts non-string', () => {
10
+ expect((0, built_in_transformers_1.trimString)(123)).toBe('123');
11
+ });
12
+ });
13
+ describe('toLowerCase', () => {
14
+ it('lowercases string', () => {
15
+ expect((0, built_in_transformers_1.toLowerCase)('HELLO')).toBe('hello');
16
+ });
17
+ });
18
+ describe('toUpperCase', () => {
19
+ it('uppercases string', () => {
20
+ expect((0, built_in_transformers_1.toUpperCase)('hello')).toBe('HELLO');
21
+ });
22
+ });
23
+ describe('parseJson', () => {
24
+ it('parses JSON string', () => {
25
+ expect((0, built_in_transformers_1.parseJson)('{"a":1}')).toEqual({ a: 1 });
26
+ });
27
+ it('returns value for non-string', () => {
28
+ expect((0, built_in_transformers_1.parseJson)({ a: 1 })).toEqual({ a: 1 });
29
+ });
30
+ });
31
+ describe('stringifyJson', () => {
32
+ it('stringifies object', () => {
33
+ expect((0, built_in_transformers_1.stringifyJson)({ a: 1 })).toBe('{"a":1}');
34
+ });
35
+ });
36
+ describe('pick', () => {
37
+ it('picks specified keys', () => {
38
+ const fn = (0, built_in_transformers_1.pick)(['a', 'c']);
39
+ expect(fn({ a: 1, b: 2, c: 3 })).toEqual({ a: 1, c: 3 });
40
+ });
41
+ it('handles missing keys', () => {
42
+ expect((0, built_in_transformers_1.pick)(['x'])({})).toEqual({});
43
+ });
44
+ });
45
+ describe('omit', () => {
46
+ it('omits specified keys', () => {
47
+ const fn = (0, built_in_transformers_1.omit)(['b']);
48
+ expect(fn({ a: 1, b: 2, c: 3 })).toEqual({ a: 1, c: 3 });
49
+ });
50
+ });
51
+ describe('renameKeys', () => {
52
+ it('renames keys', () => {
53
+ const fn = (0, built_in_transformers_1.renameKeys)({ oldName: 'newName' });
54
+ expect(fn({ oldName: 'value', keep: 1 })).toEqual({ newName: 'value', keep: 1 });
55
+ });
56
+ });
57
+ });
@@ -61,5 +61,5 @@ let TransformerService = class TransformerService {
61
61
  };
62
62
  exports.TransformerService = TransformerService;
63
63
  exports.TransformerService = TransformerService = __decorate([
64
- (0, core_1.Injectable)()
64
+ (0, core_1.Service)()
65
65
  ], TransformerService);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transformer.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer.service.test.d.ts","sourceRoot":"","sources":["../../src/transformers/transformer.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const transformer_service_1 = require("./transformer.service");
4
+ describe('TransformerService', () => {
5
+ let service;
6
+ beforeEach(() => {
7
+ service = new transformer_service_1.TransformerService();
8
+ });
9
+ it('registers and applies transform', async () => {
10
+ service.register('double', (x) => x * 2);
11
+ const result = await service.apply('double', 5);
12
+ expect(result).toBe(10);
13
+ });
14
+ it('throws for unregistered transform', async () => {
15
+ await expect(service.apply('missing', 1)).rejects.toThrow('Transform not found: missing');
16
+ });
17
+ it('pipe composes functions', async () => {
18
+ const fn = service.pipe((x) => x + 1, (x) => x * 2);
19
+ const result = await fn(5);
20
+ expect(result).toBe(12);
21
+ });
22
+ it('map transforms array', async () => {
23
+ const mapper = service.map((x) => x * 2);
24
+ const result = await mapper([1, 2, 3]);
25
+ expect(result).toEqual([2, 4, 6]);
26
+ });
27
+ it('filter filters array', async () => {
28
+ const filter = service.filter((x) => x > 2);
29
+ const result = await filter([1, 2, 3, 4]);
30
+ expect(result).toEqual([3, 4]);
31
+ });
32
+ });
@@ -36,5 +36,5 @@ let SchemaValidator = class SchemaValidator {
36
36
  };
37
37
  exports.SchemaValidator = SchemaValidator;
38
38
  exports.SchemaValidator = SchemaValidator = __decorate([
39
- (0, core_1.Injectable)()
39
+ (0, core_1.Service)()
40
40
  ], SchemaValidator);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.validator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.validator.test.d.ts","sourceRoot":"","sources":["../../src/validators/schema.validator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_validator_1 = require("./schema.validator");
4
+ const schema_1 = require("../schema/schema");
5
+ describe('SchemaValidator', () => {
6
+ let validator;
7
+ beforeEach(() => {
8
+ validator = new schema_validator_1.SchemaValidator();
9
+ });
10
+ it('validates and returns data', () => {
11
+ const schema = schema_1.Schema.object({ x: schema_1.Schema.number() });
12
+ const result = validator.validate(schema, { x: 42 });
13
+ expect(result).toEqual({ x: 42 });
14
+ });
15
+ it('throws SchemaValidationException on invalid data', () => {
16
+ const schema = schema_1.Schema.object({ x: schema_1.Schema.number() });
17
+ expect(() => validator.validate(schema, { x: 'not a number' })).toThrow(schema_validator_1.SchemaValidationException);
18
+ try {
19
+ validator.validate(schema, { x: 'bad' });
20
+ }
21
+ catch (e) {
22
+ expect(e).toBeInstanceOf(schema_validator_1.SchemaValidationException);
23
+ expect(e.errors).toBeDefined();
24
+ }
25
+ });
26
+ it('validateOrThrow is alias for validate', () => {
27
+ const schema = schema_1.Schema.object({ x: schema_1.Schema.number() });
28
+ const result = validator.validateOrThrow(schema, { x: 1 });
29
+ expect(result).toEqual({ x: 1 });
30
+ });
31
+ it('safeValidate returns result without throwing', () => {
32
+ const schema = schema_1.Schema.string();
33
+ const valid = validator.safeValidate(schema, 'ok');
34
+ expect(valid.success).toBe(true);
35
+ if (valid.success)
36
+ expect(valid.data).toBe('ok');
37
+ const invalid = validator.safeValidate(schema, 123);
38
+ expect(invalid.success).toBe(false);
39
+ if (!invalid.success)
40
+ expect(invalid.errors.length).toBeGreaterThan(0);
41
+ });
42
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hazeljs/data",
3
- "version": "0.2.0-beta.53",
3
+ "version": "0.2.0-beta.55",
4
4
  "description": "Data Processing & ETL for HazelJS framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,5 +49,5 @@
49
49
  "url": "https://github.com/hazeljs/hazel-js/issues"
50
50
  },
51
51
  "homepage": "https://hazeljs.com",
52
- "gitHead": "84311f65083627fa53bf2a22f96cd212c196873c"
52
+ "gitHead": "f2e54f346eea552595a44607999454a9e388cb9e"
53
53
  }