@hazeljs/data 0.2.0-alpha.1
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/LICENSE +192 -0
- package/README.md +308 -0
- package/dist/connectors/connector.interface.d.ts +29 -0
- package/dist/connectors/connector.interface.d.ts.map +1 -0
- package/dist/connectors/connector.interface.js +6 -0
- package/dist/connectors/csv.connector.d.ts +63 -0
- package/dist/connectors/csv.connector.d.ts.map +1 -0
- package/dist/connectors/csv.connector.js +147 -0
- package/dist/connectors/http.connector.d.ts +68 -0
- package/dist/connectors/http.connector.d.ts.map +1 -0
- package/dist/connectors/http.connector.js +131 -0
- package/dist/connectors/index.d.ts +7 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +12 -0
- package/dist/connectors/memory.connector.d.ts +38 -0
- package/dist/connectors/memory.connector.d.ts.map +1 -0
- package/dist/connectors/memory.connector.js +56 -0
- package/dist/connectors/memory.connector.test.d.ts +2 -0
- package/dist/connectors/memory.connector.test.d.ts.map +1 -0
- package/dist/connectors/memory.connector.test.js +43 -0
- package/dist/data.module.d.ts +30 -0
- package/dist/data.module.d.ts.map +1 -0
- package/dist/data.module.js +120 -0
- package/dist/data.module.test.d.ts +2 -0
- package/dist/data.module.test.d.ts.map +1 -0
- package/dist/data.module.test.js +28 -0
- package/dist/data.types.d.ts +67 -0
- package/dist/data.types.d.ts.map +1 -0
- package/dist/data.types.js +5 -0
- package/dist/decorators/index.d.ts +6 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +24 -0
- package/dist/decorators/pii.decorator.d.ts +59 -0
- package/dist/decorators/pii.decorator.d.ts.map +1 -0
- package/dist/decorators/pii.decorator.js +197 -0
- package/dist/decorators/pii.decorator.test.d.ts +2 -0
- package/dist/decorators/pii.decorator.test.d.ts.map +1 -0
- package/dist/decorators/pii.decorator.test.js +150 -0
- package/dist/decorators/pipeline.decorator.d.ts +22 -0
- package/dist/decorators/pipeline.decorator.d.ts.map +1 -0
- package/dist/decorators/pipeline.decorator.js +42 -0
- package/dist/decorators/pipeline.decorator.test.d.ts +2 -0
- package/dist/decorators/pipeline.decorator.test.d.ts.map +1 -0
- package/dist/decorators/pipeline.decorator.test.js +104 -0
- package/dist/decorators/stream.decorator.d.ts +31 -0
- package/dist/decorators/stream.decorator.d.ts.map +1 -0
- package/dist/decorators/stream.decorator.js +48 -0
- package/dist/decorators/transform.decorator.d.ts +29 -0
- package/dist/decorators/transform.decorator.d.ts.map +1 -0
- package/dist/decorators/transform.decorator.js +41 -0
- package/dist/decorators/validate.decorator.d.ts +34 -0
- package/dist/decorators/validate.decorator.d.ts.map +1 -0
- package/dist/decorators/validate.decorator.js +49 -0
- package/dist/flink.service.d.ts +80 -0
- package/dist/flink.service.d.ts.map +1 -0
- package/dist/flink.service.js +134 -0
- package/dist/flink.service.test.d.ts +2 -0
- package/dist/flink.service.test.d.ts.map +1 -0
- package/dist/flink.service.test.js +60 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/pipelines/etl.service.d.ts +59 -0
- package/dist/pipelines/etl.service.d.ts.map +1 -0
- package/dist/pipelines/etl.service.js +223 -0
- package/dist/pipelines/etl.service.test.d.ts +2 -0
- package/dist/pipelines/etl.service.test.d.ts.map +1 -0
- package/dist/pipelines/etl.service.test.js +319 -0
- package/dist/pipelines/pipeline.base.d.ts +24 -0
- package/dist/pipelines/pipeline.base.d.ts.map +1 -0
- package/dist/pipelines/pipeline.base.js +29 -0
- package/dist/pipelines/pipeline.base.test.d.ts +2 -0
- package/dist/pipelines/pipeline.base.test.d.ts.map +1 -0
- package/dist/pipelines/pipeline.base.test.js +38 -0
- package/dist/pipelines/pipeline.builder.d.ts +95 -0
- package/dist/pipelines/pipeline.builder.d.ts.map +1 -0
- package/dist/pipelines/pipeline.builder.js +212 -0
- package/dist/pipelines/pipeline.builder.test.d.ts +2 -0
- package/dist/pipelines/pipeline.builder.test.d.ts.map +1 -0
- package/dist/pipelines/pipeline.builder.test.js +185 -0
- package/dist/pipelines/stream.service.d.ts +12 -0
- package/dist/pipelines/stream.service.d.ts.map +1 -0
- package/dist/pipelines/stream.service.js +58 -0
- package/dist/pipelines/stream.service.test.d.ts +2 -0
- package/dist/pipelines/stream.service.test.d.ts.map +1 -0
- package/dist/pipelines/stream.service.test.js +103 -0
- package/dist/quality/quality.service.d.ts +87 -0
- package/dist/quality/quality.service.d.ts.map +1 -0
- package/dist/quality/quality.service.js +326 -0
- package/dist/quality/quality.service.test.d.ts +2 -0
- package/dist/quality/quality.service.test.d.ts.map +1 -0
- package/dist/quality/quality.service.test.js +128 -0
- package/dist/schema/schema.d.ts +127 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +487 -0
- package/dist/schema/schema.test.d.ts +2 -0
- package/dist/schema/schema.test.d.ts.map +1 -0
- package/dist/schema/schema.test.js +411 -0
- package/dist/streaming/flink/flink.client.d.ts +96 -0
- package/dist/streaming/flink/flink.client.d.ts.map +1 -0
- package/dist/streaming/flink/flink.client.js +267 -0
- package/dist/streaming/flink/flink.client.test.d.ts +2 -0
- package/dist/streaming/flink/flink.client.test.d.ts.map +1 -0
- package/dist/streaming/flink/flink.client.test.js +59 -0
- package/dist/streaming/flink/flink.job.d.ts +29 -0
- package/dist/streaming/flink/flink.job.d.ts.map +1 -0
- package/dist/streaming/flink/flink.job.js +27 -0
- package/dist/streaming/flink/flink.job.test.d.ts +2 -0
- package/dist/streaming/flink/flink.job.test.d.ts.map +1 -0
- package/dist/streaming/flink/flink.job.test.js +37 -0
- package/dist/streaming/flink/flink.operators.d.ts +35 -0
- package/dist/streaming/flink/flink.operators.d.ts.map +1 -0
- package/dist/streaming/flink/flink.operators.js +43 -0
- package/dist/streaming/flink/flink.operators.test.d.ts +2 -0
- package/dist/streaming/flink/flink.operators.test.d.ts.map +1 -0
- package/dist/streaming/flink/flink.operators.test.js +38 -0
- package/dist/streaming/stream.builder.d.ts +22 -0
- package/dist/streaming/stream.builder.d.ts.map +1 -0
- package/dist/streaming/stream.builder.js +50 -0
- package/dist/streaming/stream.builder.test.d.ts +2 -0
- package/dist/streaming/stream.builder.test.d.ts.map +1 -0
- package/dist/streaming/stream.builder.test.js +59 -0
- package/dist/streaming/stream.processor.d.ts +66 -0
- package/dist/streaming/stream.processor.d.ts.map +1 -0
- package/dist/streaming/stream.processor.js +178 -0
- package/dist/streaming/stream.processor.test.d.ts +2 -0
- package/dist/streaming/stream.processor.test.d.ts.map +1 -0
- package/dist/streaming/stream.processor.test.js +151 -0
- package/dist/streaming/stream.processor.windowing.test.d.ts +2 -0
- package/dist/streaming/stream.processor.windowing.test.d.ts.map +1 -0
- package/dist/streaming/stream.processor.windowing.test.js +69 -0
- package/dist/telemetry/telemetry.d.ts +124 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -0
- package/dist/telemetry/telemetry.js +259 -0
- package/dist/telemetry/telemetry.test.d.ts +2 -0
- package/dist/telemetry/telemetry.test.d.ts.map +1 -0
- package/dist/telemetry/telemetry.test.js +51 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +18 -0
- package/dist/testing/pipeline-test-harness.d.ts +40 -0
- package/dist/testing/pipeline-test-harness.d.ts.map +1 -0
- package/dist/testing/pipeline-test-harness.js +55 -0
- package/dist/testing/pipeline-test-harness.test.d.ts +2 -0
- package/dist/testing/pipeline-test-harness.test.d.ts.map +1 -0
- package/dist/testing/pipeline-test-harness.test.js +102 -0
- package/dist/testing/schema-faker.d.ts +32 -0
- package/dist/testing/schema-faker.d.ts.map +1 -0
- package/dist/testing/schema-faker.js +91 -0
- package/dist/testing/schema-faker.test.d.ts +2 -0
- package/dist/testing/schema-faker.test.d.ts.map +1 -0
- package/dist/testing/schema-faker.test.js +66 -0
- package/dist/transformers/built-in.transformers.d.ts +12 -0
- package/dist/transformers/built-in.transformers.d.ts.map +1 -0
- package/dist/transformers/built-in.transformers.js +75 -0
- package/dist/transformers/built-in.transformers.test.d.ts +2 -0
- package/dist/transformers/built-in.transformers.test.d.ts.map +1 -0
- package/dist/transformers/built-in.transformers.test.js +85 -0
- package/dist/transformers/transformer.service.d.ts +14 -0
- package/dist/transformers/transformer.service.d.ts.map +1 -0
- package/dist/transformers/transformer.service.js +65 -0
- package/dist/transformers/transformer.service.test.d.ts +2 -0
- package/dist/transformers/transformer.service.test.d.ts.map +1 -0
- package/dist/transformers/transformer.service.test.js +42 -0
- package/dist/validators/schema.validator.d.ts +21 -0
- package/dist/validators/schema.validator.d.ts.map +1 -0
- package/dist/validators/schema.validator.js +40 -0
- package/dist/validators/schema.validator.test.d.ts +2 -0
- package/dist/validators/schema.validator.test.d.ts.map +1 -0
- package/dist/validators/schema.validator.test.js +42 -0
- package/package.json +53 -0
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
describe('boolean', () => {
|
|
120
|
+
it('validates boolean', () => {
|
|
121
|
+
expect(schema_1.Schema.boolean().validate(true).success).toBe(true);
|
|
122
|
+
expect(schema_1.Schema.boolean().validate(false).success).toBe(true);
|
|
123
|
+
expect(schema_1.Schema.boolean().validate(1).success).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('literal', () => {
|
|
127
|
+
it('validates literal value', () => {
|
|
128
|
+
expect(schema_1.Schema.literal('active').validate('active').success).toBe(true);
|
|
129
|
+
expect(schema_1.Schema.literal('active').validate('inactive').success).toBe(false);
|
|
130
|
+
expect(schema_1.Schema.literal(42).validate(42).success).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('union', () => {
|
|
134
|
+
it('validates union of schemas', () => {
|
|
135
|
+
const schema = schema_1.Schema.union([schema_1.Schema.literal('a'), schema_1.Schema.literal('b')]);
|
|
136
|
+
expect(schema.validate('a').success).toBe(true);
|
|
137
|
+
expect(schema.validate('b').success).toBe(true);
|
|
138
|
+
expect(schema.validate('c').success).toBe(false);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('optional and default', () => {
|
|
142
|
+
it('optional accepts undefined', () => {
|
|
143
|
+
const schema = schema_1.Schema.string().optional();
|
|
144
|
+
expect(schema.validate(undefined).success).toBe(true);
|
|
145
|
+
expect(schema.validate('x').success).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it('default returns default for undefined', () => {
|
|
148
|
+
const schema = schema_1.Schema.string().default('fallback');
|
|
149
|
+
const result = schema.validate(undefined);
|
|
150
|
+
expect(result.success).toBe(true);
|
|
151
|
+
if (result.success)
|
|
152
|
+
expect(result.data).toBe('fallback');
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe('transform and refine', () => {
|
|
156
|
+
it('transform coerces after validation', () => {
|
|
157
|
+
const schema = schema_1.Schema.number().transform((n) => n * 2);
|
|
158
|
+
const result = schema.validate(21);
|
|
159
|
+
expect(result.success).toBe(true);
|
|
160
|
+
if (result.success)
|
|
161
|
+
expect(result.data).toBe(42);
|
|
162
|
+
});
|
|
163
|
+
it('refine adds custom constraint', () => {
|
|
164
|
+
const schema = schema_1.Schema.number().refine((n) => n % 2 === 0, 'Must be even');
|
|
165
|
+
expect(schema.validate(4).success).toBe(true);
|
|
166
|
+
expect(schema.validate(3).success).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
describe('toJsonSchema', () => {
|
|
170
|
+
it('exports string schema', () => {
|
|
171
|
+
const js = schema_1.Schema.string().toJsonSchema();
|
|
172
|
+
expect(js).toMatchObject({ type: 'string' });
|
|
173
|
+
});
|
|
174
|
+
it('exports object schema', () => {
|
|
175
|
+
const schema = schema_1.Schema.object({ name: schema_1.Schema.string() });
|
|
176
|
+
const js = schema.toJsonSchema();
|
|
177
|
+
expect(js).toMatchObject({ type: 'object' });
|
|
178
|
+
expect(js).toHaveProperty('properties');
|
|
179
|
+
});
|
|
180
|
+
it('exports array schema', () => {
|
|
181
|
+
const schema = schema_1.Schema.array(schema_1.Schema.number());
|
|
182
|
+
const js = schema.toJsonSchema();
|
|
183
|
+
expect(js).toMatchObject({ type: 'array' });
|
|
184
|
+
expect(js).toHaveProperty('items');
|
|
185
|
+
});
|
|
186
|
+
it('exports literal schema', () => {
|
|
187
|
+
const js = schema_1.Schema.literal('x').toJsonSchema();
|
|
188
|
+
expect(js).toMatchObject({ const: 'x' });
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('nullable', () => {
|
|
192
|
+
it('accepts null', () => {
|
|
193
|
+
const schema = schema_1.Schema.string().nullable();
|
|
194
|
+
expect(schema.validate(null).success).toBe(true);
|
|
195
|
+
expect(schema.validate('x').success).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe('validateAsync', () => {
|
|
199
|
+
it('validates with async refinements', async () => {
|
|
200
|
+
const schema = schema_1.Schema.number().refineAsync(async (n) => n > 0, 'Must be positive');
|
|
201
|
+
const result = await schema.validateAsync(5);
|
|
202
|
+
expect(result.success).toBe(true);
|
|
203
|
+
const fail = await schema.validateAsync(-1);
|
|
204
|
+
expect(fail.success).toBe(false);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe('number integer and url', () => {
|
|
208
|
+
it('integer rejects decimals', () => {
|
|
209
|
+
expect(schema_1.Schema.number().integer().validate(5).success).toBe(true);
|
|
210
|
+
expect(schema_1.Schema.number().integer().validate(5.5).success).toBe(false);
|
|
211
|
+
});
|
|
212
|
+
it('string url validates', () => {
|
|
213
|
+
expect(schema_1.Schema.string().url().validate('https://example.com').success).toBe(true);
|
|
214
|
+
expect(schema_1.Schema.string().url().validate('not-a-url').success).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
describe('object pick omit extend strict', () => {
|
|
218
|
+
const base = schema_1.Schema.object({ a: schema_1.Schema.number(), b: schema_1.Schema.string(), c: schema_1.Schema.boolean() });
|
|
219
|
+
it('pick selects keys', () => {
|
|
220
|
+
const picked = base.pick(['a', 'c']);
|
|
221
|
+
const result = picked.validate({ a: 1, b: 'x', c: true });
|
|
222
|
+
expect(result.success).toBe(true);
|
|
223
|
+
if (result.success) {
|
|
224
|
+
expect(result.data).toEqual({ a: 1, c: true });
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
it('omit removes keys', () => {
|
|
228
|
+
const omitted = base.omit(['b']);
|
|
229
|
+
const result = omitted.validate({ a: 1, b: 'x', c: true });
|
|
230
|
+
expect(result.success).toBe(true);
|
|
231
|
+
if (result.success) {
|
|
232
|
+
expect(result.data).toEqual({ a: 1, c: true });
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
it('extend adds fields', () => {
|
|
236
|
+
const extended = base.extend({ d: schema_1.Schema.number() });
|
|
237
|
+
const result = extended.validate({ a: 1, b: 'x', c: true, d: 4 });
|
|
238
|
+
expect(result.success).toBe(true);
|
|
239
|
+
if (result.success)
|
|
240
|
+
expect(result.data.d).toBe(4);
|
|
241
|
+
});
|
|
242
|
+
it('strict rejects unknown keys', () => {
|
|
243
|
+
const strict = base.strict();
|
|
244
|
+
const result = strict.validate({ a: 1, b: 'x', c: true, extra: 'bad' });
|
|
245
|
+
expect(result.success).toBe(false);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
describe('array min max nonempty', () => {
|
|
249
|
+
it('min rejects short arrays', () => {
|
|
250
|
+
const schema = schema_1.Schema.array(schema_1.Schema.number()).min(2);
|
|
251
|
+
expect(schema.validate([1, 2]).success).toBe(true);
|
|
252
|
+
expect(schema.validate([1]).success).toBe(false);
|
|
253
|
+
});
|
|
254
|
+
it('nonempty rejects empty', () => {
|
|
255
|
+
const schema = schema_1.Schema.array(schema_1.Schema.string()).nonempty();
|
|
256
|
+
expect(schema.validate(['x']).success).toBe(true);
|
|
257
|
+
expect(schema.validate([]).success).toBe(false);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
describe('transform throws', () => {
|
|
261
|
+
it('transform error is caught', () => {
|
|
262
|
+
const schema = schema_1.Schema.number().transform((n) => {
|
|
263
|
+
if (n < 0)
|
|
264
|
+
throw new Error('Negative');
|
|
265
|
+
return n;
|
|
266
|
+
});
|
|
267
|
+
const result = schema.validate(-1);
|
|
268
|
+
expect(result.success).toBe(false);
|
|
269
|
+
if (!result.success)
|
|
270
|
+
expect(result.errors[0].message).toBe('Negative');
|
|
271
|
+
});
|
|
272
|
+
it('transform non-Error throw uses generic message', () => {
|
|
273
|
+
const schema = schema_1.Schema.number().transform(() => {
|
|
274
|
+
throw 'string error';
|
|
275
|
+
});
|
|
276
|
+
const result = schema.validate(1);
|
|
277
|
+
expect(result.success).toBe(false);
|
|
278
|
+
if (!result.success)
|
|
279
|
+
expect(result.errors[0].message).toBe('Transform failed');
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
describe('string pattern required trim', () => {
|
|
283
|
+
it('pattern validates regex', () => {
|
|
284
|
+
expect(schema_1.Schema.string().pattern(/^\d+$/).validate('123').success).toBe(true);
|
|
285
|
+
expect(schema_1.Schema.string().pattern(/^\d+$/, 'Digits only').validate('abc').success).toBe(false);
|
|
286
|
+
});
|
|
287
|
+
it('required rejects empty string', () => {
|
|
288
|
+
expect(schema_1.Schema.string().required().validate('x').success).toBe(true);
|
|
289
|
+
expect(schema_1.Schema.string().required().validate('').success).toBe(false);
|
|
290
|
+
});
|
|
291
|
+
it('trim preprocesses', () => {
|
|
292
|
+
const result = schema_1.Schema.string().trim().validate(' hi ');
|
|
293
|
+
expect(result.success).toBe(true);
|
|
294
|
+
if (result.success)
|
|
295
|
+
expect(result.data).toBe('hi');
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
describe('number positive negative multipleOf', () => {
|
|
299
|
+
it('positive rejects zero and negative', () => {
|
|
300
|
+
expect(schema_1.Schema.number().positive().validate(1).success).toBe(true);
|
|
301
|
+
expect(schema_1.Schema.number().positive().validate(0).success).toBe(false);
|
|
302
|
+
expect(schema_1.Schema.number().positive().validate(-1).success).toBe(false);
|
|
303
|
+
});
|
|
304
|
+
it('negative rejects zero and positive', () => {
|
|
305
|
+
expect(schema_1.Schema.number().negative().validate(-1).success).toBe(true);
|
|
306
|
+
expect(schema_1.Schema.number().negative().validate(0).success).toBe(false);
|
|
307
|
+
});
|
|
308
|
+
it('multipleOf validates', () => {
|
|
309
|
+
expect(schema_1.Schema.number().multipleOf(5).validate(10).success).toBe(true);
|
|
310
|
+
expect(schema_1.Schema.number().multipleOf(5).validate(7).success).toBe(false);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
describe('number and boolean default', () => {
|
|
314
|
+
it('number default for undefined', () => {
|
|
315
|
+
const schema = schema_1.Schema.number().default(42);
|
|
316
|
+
const result = schema.validate(undefined);
|
|
317
|
+
expect(result.success).toBe(true);
|
|
318
|
+
if (result.success)
|
|
319
|
+
expect(result.data).toBe(42);
|
|
320
|
+
});
|
|
321
|
+
it('boolean default for undefined', () => {
|
|
322
|
+
const schema = schema_1.Schema.boolean().default(true);
|
|
323
|
+
const result = schema.validate(undefined);
|
|
324
|
+
expect(result.success).toBe(true);
|
|
325
|
+
if (result.success)
|
|
326
|
+
expect(result.data).toBe(true);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
describe('date min max default', () => {
|
|
330
|
+
it('date min max', () => {
|
|
331
|
+
const min = new Date('2024-01-01');
|
|
332
|
+
const max = new Date('2024-12-31');
|
|
333
|
+
const schema = schema_1.Schema.date().min(min).max(max);
|
|
334
|
+
expect(schema.validate(new Date('2024-06-15')).success).toBe(true);
|
|
335
|
+
expect(schema.validate(new Date('2023-06-15')).success).toBe(false);
|
|
336
|
+
expect(schema.validate(new Date('2025-06-15')).success).toBe(false);
|
|
337
|
+
});
|
|
338
|
+
it('date default for undefined', () => {
|
|
339
|
+
const d = new Date('2024-01-01');
|
|
340
|
+
const schema = schema_1.Schema.date().default(d);
|
|
341
|
+
const result = schema.validate(undefined);
|
|
342
|
+
expect(result.success).toBe(true);
|
|
343
|
+
if (result.success)
|
|
344
|
+
expect(result.data).toEqual(d);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
describe('nullable toJsonSchema', () => {
|
|
348
|
+
it('nullable string has type array', () => {
|
|
349
|
+
const js = schema_1.Schema.string().nullable().toJsonSchema();
|
|
350
|
+
expect(js.type).toEqual(['string', 'null']);
|
|
351
|
+
});
|
|
352
|
+
it('nullable without base type', () => {
|
|
353
|
+
const schema = schema_1.Schema.literal('x').nullable();
|
|
354
|
+
const js = schema.toJsonSchema();
|
|
355
|
+
expect(js.type).toEqual(['null']);
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
describe('optional toJsonSchema', () => {
|
|
359
|
+
it('optional has _optional flag', () => {
|
|
360
|
+
const js = schema_1.Schema.string().optional().toJsonSchema();
|
|
361
|
+
expect(js._optional).toBe(true);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
describe('object pick filters keys not in shape', () => {
|
|
365
|
+
it('pick ignores keys not in shape', () => {
|
|
366
|
+
const base = schema_1.Schema.object({ a: schema_1.Schema.number() });
|
|
367
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
368
|
+
const picked = base.pick(['a', 'nonexistent']);
|
|
369
|
+
const result = picked.validate({ a: 1 });
|
|
370
|
+
expect(result.success).toBe(true);
|
|
371
|
+
if (result.success)
|
|
372
|
+
expect(result.data).toEqual({ a: 1 });
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
describe('array max', () => {
|
|
376
|
+
it('max rejects long arrays', () => {
|
|
377
|
+
const schema = schema_1.Schema.array(schema_1.Schema.number()).max(2);
|
|
378
|
+
expect(schema.validate([1, 2]).success).toBe(true);
|
|
379
|
+
expect(schema.validate([1, 2, 3]).success).toBe(false);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
describe('refineAsync', () => {
|
|
383
|
+
it('refineAsync failure path', async () => {
|
|
384
|
+
const schema = schema_1.Schema.number().refineAsync(async (n) => n > 10, 'Must be > 10');
|
|
385
|
+
const result = await schema.validateAsync(5);
|
|
386
|
+
expect(result.success).toBe(false);
|
|
387
|
+
if (!result.success)
|
|
388
|
+
expect(result.errors[0].message).toBe('Must be > 10');
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
describe('buildSchema refine failure', () => {
|
|
392
|
+
it('sync refine failure returns error', () => {
|
|
393
|
+
const schema = schema_1.Schema.number().refine((n) => n > 0, 'Must be positive');
|
|
394
|
+
const result = schema.validate(-1);
|
|
395
|
+
expect(result.success).toBe(false);
|
|
396
|
+
if (!result.success)
|
|
397
|
+
expect(result.errors[0].message).toBe('Must be positive');
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
describe('validateAsync with sync failure', () => {
|
|
401
|
+
it('returns sync failure without running async refinements', async () => {
|
|
402
|
+
const schema = schema_1.Schema.number()
|
|
403
|
+
.refine((n) => n > 0, 'sync fail')
|
|
404
|
+
.refineAsync(async () => true, 'async');
|
|
405
|
+
const result = await schema.validateAsync(-1);
|
|
406
|
+
expect(result.success).toBe(false);
|
|
407
|
+
if (!result.success)
|
|
408
|
+
expect(result.errors[0].message).toBe('sync fail');
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { FlinkAuthConfig, FlinkJobConfig } from '../../data.types';
|
|
2
|
+
export interface FlinkClientConfig {
|
|
3
|
+
url: string;
|
|
4
|
+
auth?: FlinkAuthConfig;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
retries?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface FlinkJobInfo {
|
|
9
|
+
id: string;
|
|
10
|
+
status: string;
|
|
11
|
+
startTime?: number;
|
|
12
|
+
endTime?: number;
|
|
13
|
+
duration?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface FlinkJobSubmitRequest {
|
|
16
|
+
jobName?: string;
|
|
17
|
+
parallelism?: number;
|
|
18
|
+
savepointPath?: string;
|
|
19
|
+
allowNonRestoredState?: boolean;
|
|
20
|
+
programArgs?: string;
|
|
21
|
+
entryClass?: string;
|
|
22
|
+
jarFile?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Flink Client - REST API client for Apache Flink clusters
|
|
26
|
+
* Interacts with Flink JobManager REST API
|
|
27
|
+
*/
|
|
28
|
+
export declare class FlinkClient {
|
|
29
|
+
readonly url: string;
|
|
30
|
+
private readonly config;
|
|
31
|
+
constructor(config: FlinkClientConfig);
|
|
32
|
+
private request;
|
|
33
|
+
listJobs(): Promise<FlinkJobInfo[]>;
|
|
34
|
+
getJobStatus(jobId: string): Promise<{
|
|
35
|
+
state: string;
|
|
36
|
+
startTime?: number;
|
|
37
|
+
duration?: number;
|
|
38
|
+
}>;
|
|
39
|
+
cancelJob(jobId: string): Promise<void>;
|
|
40
|
+
stopJob(jobId: string, savepointPath?: string): Promise<{
|
|
41
|
+
'request-id': string;
|
|
42
|
+
}>;
|
|
43
|
+
createSavepoint(jobId: string, savepointPath?: string): Promise<{
|
|
44
|
+
'request-id': string;
|
|
45
|
+
}>;
|
|
46
|
+
getClusterInfo(): Promise<{
|
|
47
|
+
taskmanagers?: number;
|
|
48
|
+
'slots-total'?: number;
|
|
49
|
+
}>;
|
|
50
|
+
getTaskManagers(): Promise<unknown[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Upload a JAR file to the Flink cluster.
|
|
53
|
+
* @param jarPath Local filesystem path to the JAR file
|
|
54
|
+
* @returns The Flink JAR ID for subsequent run calls
|
|
55
|
+
*/
|
|
56
|
+
uploadJar(jarPath: string): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Run a previously uploaded JAR as a Flink job.
|
|
59
|
+
* @param jarId The JAR ID returned by uploadJar()
|
|
60
|
+
* @param request Optional run parameters (entry class, parallelism, args, etc.)
|
|
61
|
+
* @returns The Flink job ID
|
|
62
|
+
*/
|
|
63
|
+
runJar(jarId: string, request?: FlinkJobSubmitRequest): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Submit a SQL statement to the Flink SQL Gateway.
|
|
66
|
+
* Requires Flink SQL Gateway to be running.
|
|
67
|
+
* @param sql The SQL statement to execute (CREATE TABLE, INSERT INTO, etc.)
|
|
68
|
+
* @param sessionId An existing Flink SQL Gateway session ID
|
|
69
|
+
*/
|
|
70
|
+
submitSql(sql: string, sessionId: string): Promise<string>;
|
|
71
|
+
/**
|
|
72
|
+
* Create a new SQL Gateway session.
|
|
73
|
+
* @returns The session ID
|
|
74
|
+
*/
|
|
75
|
+
createSqlSession(properties?: Record<string, string>): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Submit a job to Flink cluster.
|
|
78
|
+
* Requires `jarFile` path in the jobConfig or uses FlinkJobSubmitRequest.jarFile.
|
|
79
|
+
*
|
|
80
|
+
* Workflow: upload JAR → run JAR → return job ID.
|
|
81
|
+
*/
|
|
82
|
+
submitJob(jobConfig: FlinkJobConfig, request?: FlinkJobSubmitRequest): Promise<string>;
|
|
83
|
+
/**
|
|
84
|
+
* List uploaded JARs on the cluster.
|
|
85
|
+
*/
|
|
86
|
+
listJars(): Promise<Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
name: string;
|
|
89
|
+
uploaded: number;
|
|
90
|
+
}>>;
|
|
91
|
+
/**
|
|
92
|
+
* Delete an uploaded JAR from the cluster.
|
|
93
|
+
*/
|
|
94
|
+
deleteJar(jarId: string): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=flink.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flink.client.d.ts","sourceRoot":"","sources":["../../../src/streaming/flink/flink.client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;gBAE/B,MAAM,EAAE,iBAAiB;YASvB,OAAO;IA4Cf,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA+BnC,YAAY,CAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAY9D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAKjF,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAKzF,cAAc,IAAI,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAI5E,eAAe,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAK3C;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8DjD;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAejF;;;;;OAKG;IACG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWhE;;;OAGG;IACG,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAW5E;;;;;OAKG;IACG,SAAS,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBhG;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAOhF;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9C"}
|