confluent-schema-registry 3.3.6 → 3.6.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +42 -1
- package/bin/avdlToAVSC.sh +1 -1
- package/dockest-error.json +3 -7
- package/jest.setup.ts +23 -13
- package/package.json +11 -17
- package/src/@types.ts +6 -13
- package/src/AvroHelper.ts +2 -3
- package/src/JsonSchema.ts +27 -15
- package/src/SchemaRegistry.json.spec.ts +18 -1
- package/src/SchemaRegistry.newApi.spec.ts +1 -1
- package/src/SchemaRegistry.spec.ts +15 -0
- package/src/SchemaRegistry.ts +16 -17
- package/src/api/index.spec.ts +24 -2
- package/src/api/index.ts +11 -2
- package/src/api/middleware/errorMiddleware.ts +1 -1
- package/src/constants.ts +1 -1
- package/src/index.ts +2 -1
- package/src/schemaTypeResolver.ts +2 -1
- package/src/utils/avdlToAVSC.spec.ts +28 -5
- package/src/utils/avdlToAVSC.ts +3 -3
- package/tmp/Array.avsc +22 -0
- package/tmp/Array1.avsc +28 -0
- package/tmp/Array2.avsc +17 -0
- package/tmp/Array3.avsc +17 -0
- package/tmp/ArrayUnion.avsc +23 -0
- package/tmp/Bam.avsc +9 -0
- package/tmp/Bar.avsc +46 -0
- package/tmp/Baz.avsc +39 -0
- package/tmp/Complex.avsc +81 -0
- package/tmp/Enum.avsc +13 -0
- package/tmp/EnumUnion.avsc +14 -0
- package/tmp/Foos.avsc +6 -0
- package/tmp/ImportMultipleNamespaces.avsc +35 -0
- package/tmp/KeyValue.avsc +12 -0
- package/tmp/Metadata.avsc +27 -0
- package/tmp/Multiple.avsc +26 -0
- package/tmp/MultipleNamespaces.avsc +44 -0
- package/tmp/MultipleUnion.avsc +28 -0
- package/tmp/Simple.avsc +9 -0
- package/tmp/Two.avsc +19 -0
- package/tmp/Union.avsc +20 -0
- package/dockest.ts +0 -30
package/CHANGELOG.md
CHANGED
@@ -9,7 +9,48 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
9
9
|
|
10
10
|
### Added
|
11
11
|
|
12
|
-
-
|
12
|
+
- Support [schema references](https://docs.confluent.io/platform/current/schema-registry/serdes-develop/index.html#schema-references) for Avro, Protocol Buffer, and JSON schema [#197](https://github.com/kafkajs/confluent-schema-registry/pull/197)
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
- Fix Apicurio compatibility with register function [#201](https://github.com/kafkajs/confluent-schema-registry/pull/201)
|
17
|
+
|
18
|
+
## [3.2.1] - 2022-01-28
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
|
22
|
+
- Don't swallow error message from client-side errors from registry requests [#176](https://github.com/kafkajs/confluent-schema-registry/pull/176)
|
23
|
+
|
24
|
+
## [3.2.0] - 2021-11-22
|
25
|
+
|
26
|
+
### Added
|
27
|
+
|
28
|
+
- Add reader schema option when decoding Avro messages [#166](https://github.com/kafkajs/confluent-schema-registry/pull/166)
|
29
|
+
|
30
|
+
## [3.1.1] - 2021-11-03
|
31
|
+
|
32
|
+
### Fixed
|
33
|
+
|
34
|
+
- Support backwards incompatible changes in Ajv 8 when passing in Ajv instance in JSON Schema options [#163](https://github.com/kafkajs/confluent-schema-registry/pull/163)
|
35
|
+
|
36
|
+
## [3.1.0] - 2021-11-03
|
37
|
+
|
38
|
+
### Added
|
39
|
+
|
40
|
+
- Allow passing in Ajv instance in JSON Schema options [#133](https://github.com/kafkajs/confluent-schema-registry/pull/133)
|
41
|
+
|
42
|
+
### Fixed
|
43
|
+
|
44
|
+
- Fix backwards compatibility with older Schema Registry versions [#158](https://github.com/kafkajs/confluent-schema-registry/pull/158)
|
45
|
+
|
46
|
+
### Fixed
|
47
|
+
|
48
|
+
- Fix gateway config for when setting HTTP agent [#127](https://github.com/kafkajs/confluent-schema-registry/pull/127)
|
49
|
+
|
50
|
+
## [3.0.1] - 2021-06-11
|
51
|
+
### Fixed
|
52
|
+
|
53
|
+
- Fix gateway config for when setting HTTP agent [#127](https://github.com/kafkajs/confluent-schema-registry/pull/127)
|
13
54
|
|
14
55
|
## [3.0.0] - 2021-05-20
|
15
56
|
|
package/bin/avdlToAVSC.sh
CHANGED
@@ -6,4 +6,4 @@ if [ -z "${avdl_path}" ]; then
|
|
6
6
|
exit;
|
7
7
|
fi
|
8
8
|
|
9
|
-
docker run --rm -v $
|
9
|
+
docker run --rm -v "$(pwd)":/avro kpnnl/avro-tools:1.12.0 idl2schemata ${avdl_path} tmp && cat tmp/${avsc_name}.avsc
|
package/dockest-error.json
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"errorPayload": {
|
3
|
-
"trap": "
|
4
|
-
"
|
5
|
-
"payload": {},
|
6
|
-
"name": "DockestError"
|
7
|
-
},
|
8
|
-
"promise": {}
|
3
|
+
"trap": "SIGINT",
|
4
|
+
"signal": "SIGINT"
|
9
5
|
},
|
10
|
-
"timestamp": "2024-
|
6
|
+
"timestamp": "2024-12-18T22:39:59.117Z"
|
11
7
|
}
|
package/jest.setup.ts
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
import { MAGIC_BYTE } from './src/wireEncoder'
|
2
2
|
import decode from './src/wireDecoder'
|
3
|
+
import { MatcherFunction } from 'expect'
|
3
4
|
|
4
|
-
const toMatchConfluentEncodedPayload
|
5
|
-
|
5
|
+
const toMatchConfluentEncodedPayload: MatcherFunction<[{ payload: Buffer }]> = function(
|
6
|
+
received,
|
7
|
+
{ payload: expectedPayload },
|
8
|
+
) {
|
9
|
+
const { printExpected, printReceived, printWithType } = this.utils
|
6
10
|
|
7
11
|
if (!Buffer.isBuffer(expectedPayload)) {
|
8
12
|
const error = [
|
@@ -13,16 +17,17 @@ const toMatchConfluentEncodedPayload = context => (received, { payload: expected
|
|
13
17
|
throw new Error(error)
|
14
18
|
}
|
15
19
|
|
16
|
-
const { magicByte, payload } = decode(received)
|
20
|
+
const { magicByte, payload } = decode(received as Buffer)
|
17
21
|
const expectedMessage = decode(expectedPayload)
|
18
22
|
|
19
23
|
if (!Buffer.isBuffer(received)) {
|
20
24
|
return {
|
21
25
|
pass: false,
|
22
|
-
message: () =>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
message: () =>
|
27
|
+
[
|
28
|
+
'Received value must be a Buffer',
|
29
|
+
printWithType('Received', received, printReceived),
|
30
|
+
].join('\n'),
|
26
31
|
}
|
27
32
|
}
|
28
33
|
|
@@ -40,7 +45,7 @@ const toMatchConfluentEncodedPayload = context => (received, { payload: expected
|
|
40
45
|
}
|
41
46
|
|
42
47
|
return {
|
43
|
-
pass:
|
48
|
+
pass: this.equals(payload, expectedMessage.payload),
|
44
49
|
message: () =>
|
45
50
|
[
|
46
51
|
'expected payload',
|
@@ -52,9 +57,14 @@ const toMatchConfluentEncodedPayload = context => (received, { payload: expected
|
|
52
57
|
}
|
53
58
|
|
54
59
|
expect.extend({
|
55
|
-
toMatchConfluentEncodedPayload
|
56
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
57
|
-
// @ts-ignore
|
58
|
-
return toMatchConfluentEncodedPayload(this)(...args)
|
59
|
-
},
|
60
|
+
toMatchConfluentEncodedPayload,
|
60
61
|
})
|
62
|
+
|
63
|
+
declare global {
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
65
|
+
namespace jest {
|
66
|
+
interface Matchers<R, T = {}> {
|
67
|
+
toMatchConfluentEncodedPayload(args: { registryId: number; payload: Buffer }): R
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "confluent-schema-registry",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.6.2",
|
4
4
|
"main": "dist/index.js",
|
5
5
|
"description": "ConfluentSchemaRegistry is a library that makes it easier to interact with the Confluent schema registry, it provides convenient methods to encode, decode and register new schemas using the Apache Avro serialization format.",
|
6
6
|
"keywords": [
|
@@ -17,40 +17,34 @@
|
|
17
17
|
"build:watch": "rm -rf ./dist && tsc --watch",
|
18
18
|
"test:unit:watch": "yarn test:unit --watch",
|
19
19
|
"test:unit": "jest",
|
20
|
-
"test": "
|
21
|
-
"test:debug": "ts-node ./dockest.ts debug",
|
20
|
+
"test": "docker compose up -d --wait schemaRegistry && jest",
|
22
21
|
"lint": "eslint './src/**/*.ts'",
|
22
|
+
"check:types": "tsc --noEmit",
|
23
23
|
"format": "yarn lint --fix"
|
24
24
|
},
|
25
25
|
"dependencies": {
|
26
26
|
"ajv": "^7.1.0",
|
27
27
|
"avsc": ">= 5.4.13 < 6",
|
28
|
-
"mappersmith": ">= 2.
|
29
|
-
"protobufjs": "
|
28
|
+
"mappersmith": ">= 2.44.0 < 3",
|
29
|
+
"protobufjs": ">= 6.11.4 < 8"
|
30
30
|
},
|
31
31
|
"devDependencies": {
|
32
|
-
"@types/
|
33
|
-
"@types/
|
34
|
-
"@types/jest": "^25.2.1",
|
35
|
-
"@types/node": "^12.7.3",
|
32
|
+
"@types/jest": "^29.5.14",
|
33
|
+
"@types/node": "^18.19.70",
|
36
34
|
"@types/prettier": "^1.18.2",
|
37
|
-
"@types/uuid": "^3.4.5",
|
38
35
|
"@typescript-eslint/eslint-plugin": "^2.1.0",
|
39
36
|
"@typescript-eslint/parser": "^2.1.0",
|
40
37
|
"@typescript-eslint/typescript-estree": "^2.1.0",
|
41
38
|
"ajv8": "npm:ajv@^8.6.3",
|
42
|
-
"dockest": "^2.1.0",
|
43
39
|
"eslint": "^6.3.0",
|
44
40
|
"eslint-config-prettier": "^6.1.0",
|
45
41
|
"eslint-plugin-no-only-tests": "^2.3.1",
|
46
42
|
"eslint-plugin-prettier": "^3.1.0",
|
47
|
-
"
|
48
|
-
"fs-extra": "^8.1.0",
|
49
|
-
"jest": "^25.2.7",
|
43
|
+
"jest": "^29.7.0",
|
50
44
|
"prettier": "^1.18.2",
|
51
|
-
"ts-jest": "^
|
45
|
+
"ts-jest": "^29.2.5",
|
52
46
|
"ts-node": "^8.3.0",
|
53
|
-
"typescript": "^
|
54
|
-
"uuid": "^
|
47
|
+
"typescript": "^5.7.3",
|
48
|
+
"uuid": "^11.0.5"
|
55
49
|
}
|
56
50
|
}
|
package/src/@types.ts
CHANGED
@@ -23,10 +23,12 @@ export type AvroOptions = Partial<ForSchemaOptions> & {
|
|
23
23
|
}
|
24
24
|
|
25
25
|
export type JsonOptions = ConstructorParameters<typeof Ajv>[0] & {
|
26
|
-
ajvInstance?:
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
ajvInstance?:
|
27
|
+
| {
|
28
|
+
addSchema: Ajv['addSchema']
|
29
|
+
compile: (schema: any) => ValidateFunction
|
30
|
+
}
|
31
|
+
| Ajv
|
30
32
|
referencedSchemas?: JsonConfluentSchema[]
|
31
33
|
}
|
32
34
|
export type ProtoOptions = { messageName?: string; referencedSchemas?: ProtoConfluentSchema[] }
|
@@ -94,12 +96,3 @@ export interface SchemaResponse {
|
|
94
96
|
}
|
95
97
|
|
96
98
|
export type ConfluentSchema = AvroConfluentSchema | ProtoConfluentSchema | JsonConfluentSchema
|
97
|
-
|
98
|
-
declare global {
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
100
|
-
namespace jest {
|
101
|
-
interface Matchers<R, T = {}> {
|
102
|
-
toMatchConfluentEncodedPayload(args: { registryId: number; payload: Buffer }): R
|
103
|
-
}
|
104
|
-
}
|
105
|
-
}
|
package/src/AvroHelper.ts
CHANGED
@@ -12,7 +12,7 @@ import { ConfluentSchemaRegistryArgumentError } from './errors'
|
|
12
12
|
import avro, { ForSchemaOptions, Schema, Type } from 'avsc'
|
13
13
|
import { SchemaResponse, SchemaType } from './@types'
|
14
14
|
|
15
|
-
type TypeHook = (schema: Schema, opts: ForSchemaOptions) => Type
|
15
|
+
type TypeHook = (schema: Schema, opts: ForSchemaOptions) => Type | undefined
|
16
16
|
export default class AvroHelper implements SchemaHelper {
|
17
17
|
private getRawAvroSchema(schema: ConfluentSchema): RawAvroSchema {
|
18
18
|
return (typeof schema.schema === 'string'
|
@@ -57,8 +57,7 @@ export default class AvroHelper implements SchemaHelper {
|
|
57
57
|
|
58
58
|
public getSubject(
|
59
59
|
schema: AvroConfluentSchema,
|
60
|
-
|
61
|
-
avroSchema: AvroSchema,
|
60
|
+
_avroSchema: AvroSchema,
|
62
61
|
separator: string,
|
63
62
|
): ConfluentSubject {
|
64
63
|
const rawSchema: RawAvroSchema = this.getRawAvroSchema(schema)
|
package/src/JsonSchema.ts
CHANGED
@@ -5,6 +5,7 @@ import { ConfluentSchemaRegistryValidationError } from './errors'
|
|
5
5
|
interface BaseAjvValidationError {
|
6
6
|
data?: unknown
|
7
7
|
schema?: unknown
|
8
|
+
message?: string
|
8
9
|
}
|
9
10
|
interface OldAjvValidationError extends BaseAjvValidationError {
|
10
11
|
dataPath: string
|
@@ -41,8 +42,15 @@ export default class JsonSchema implements Schema {
|
|
41
42
|
}
|
42
43
|
|
43
44
|
private validatePayload(payload: any) {
|
44
|
-
const paths:
|
45
|
-
|
45
|
+
const paths: any[] = []
|
46
|
+
|
47
|
+
if (
|
48
|
+
!this.isValid(payload, {
|
49
|
+
errorHook: (path, message) => {
|
50
|
+
paths.push({ path, message })
|
51
|
+
},
|
52
|
+
})
|
53
|
+
) {
|
46
54
|
throw new ConfluentSchemaRegistryValidationError('invalid payload', paths)
|
47
55
|
}
|
48
56
|
}
|
@@ -57,19 +65,23 @@ export default class JsonSchema implements Schema {
|
|
57
65
|
this.validatePayload(payload)
|
58
66
|
return payload
|
59
67
|
}
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
|
69
|
+
public isValid(
|
70
|
+
payload: object,
|
71
|
+
opts?: { errorHook: (path: Array<string>, value: any, type?: any) => void },
|
72
|
+
): boolean {
|
73
|
+
if (!this.validate(payload)) {
|
74
|
+
if (opts?.errorHook) {
|
75
|
+
for (const err of this.validate.errors as AjvValidationError[]) {
|
76
|
+
const path = this.isOldAjvValidationError(err) ? err.dataPath : err.instancePath
|
77
|
+
opts.errorHook([path], err.message ?? err.data, err.schema)
|
78
|
+
}
|
79
|
+
return false
|
80
|
+
}
|
81
|
+
}
|
82
|
+
return true
|
83
|
+
}
|
84
|
+
|
73
85
|
private isOldAjvValidationError(error: AjvValidationError): error is OldAjvValidationError {
|
74
86
|
return (error as OldAjvValidationError).dataPath != null
|
75
87
|
}
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import SchemaRegistry, { RegisteredSchema } from './SchemaRegistry'
|
2
2
|
import API from './api'
|
3
3
|
import { JsonConfluentSchema, SchemaType } from './@types'
|
4
|
+
import Ajv from 'ajv'
|
5
|
+
import { ConfluentSchemaRegistryValidationError } from './errors'
|
4
6
|
|
5
7
|
const REGISTRY_HOST = 'http://localhost:8982'
|
6
8
|
const schemaRegistryAPIClientArgs = { host: REGISTRY_HOST }
|
@@ -100,8 +102,13 @@ describe('SchemaRegistry', () => {
|
|
100
102
|
let api
|
101
103
|
|
102
104
|
beforeEach(async () => {
|
105
|
+
const options = {
|
106
|
+
[SchemaType.JSON]: {
|
107
|
+
allErrors: true,
|
108
|
+
},
|
109
|
+
}
|
103
110
|
api = API(schemaRegistryAPIClientArgs)
|
104
|
-
schemaRegistry = new SchemaRegistry(schemaRegistryArgs)
|
111
|
+
schemaRegistry = new SchemaRegistry(schemaRegistryArgs, options)
|
105
112
|
})
|
106
113
|
|
107
114
|
describe('when register', () => {
|
@@ -161,6 +168,16 @@ describe('SchemaRegistry', () => {
|
|
161
168
|
|
162
169
|
expect(resultObj).toEqual(obj)
|
163
170
|
})
|
171
|
+
|
172
|
+
it('should return error message', async () => {
|
173
|
+
const obj = { id2a: 'sdfsdfsdf', level2a: 1 }
|
174
|
+
try {
|
175
|
+
await schemaRegistry.encode(registeredSchema.id, obj)
|
176
|
+
} catch (ex) {
|
177
|
+
expect(ex.paths[0].message).toBeDefined()
|
178
|
+
expect(ex.paths[0].message).toEqual('should be number')
|
179
|
+
}
|
180
|
+
})
|
164
181
|
})
|
165
182
|
|
166
183
|
describe('with multiple reference', () => {
|
@@ -587,7 +587,7 @@ describe('SchemaRegistry - new Api', () => {
|
|
587
587
|
} catch (error) {
|
588
588
|
expect(error).toBeInstanceOf(ConfluentSchemaRegistryValidationError)
|
589
589
|
expect(error.message).toEqual('invalid payload')
|
590
|
-
expect(error.paths).toEqual([
|
590
|
+
expect(error.paths[0].path).toEqual(['/fullName'])
|
591
591
|
}
|
592
592
|
},
|
593
593
|
)
|
@@ -250,3 +250,18 @@ describe('SchemaRegistry - old AVRO api', () => {
|
|
250
250
|
})
|
251
251
|
})
|
252
252
|
})
|
253
|
+
|
254
|
+
describe('SchemaRegistry - Custom Middleware', () => {
|
255
|
+
const customMiddleware = jest.fn()
|
256
|
+
|
257
|
+
const schemaRegistry = new SchemaRegistry({
|
258
|
+
...schemaRegistryArgs,
|
259
|
+
middlewares: [customMiddleware],
|
260
|
+
})
|
261
|
+
|
262
|
+
it('should have called the custom middleware', async () => {
|
263
|
+
await schemaRegistry.register(personSchema)
|
264
|
+
|
265
|
+
expect(customMiddleware).toHaveBeenCalled()
|
266
|
+
})
|
267
|
+
})
|
package/src/SchemaRegistry.ts
CHANGED
@@ -3,7 +3,7 @@ import { Response } from 'mappersmith'
|
|
3
3
|
|
4
4
|
import { encode, MAGIC_BYTE } from './wireEncoder'
|
5
5
|
import decode from './wireDecoder'
|
6
|
-
import { COMPATIBILITY,
|
6
|
+
import { COMPATIBILITY, DEFAULT_SEPARATOR } from './constants'
|
7
7
|
import API, { SchemaRegistryAPIClientArgs, SchemaRegistryAPIClient } from './api'
|
8
8
|
import Cache from './cache'
|
9
9
|
import {
|
@@ -46,13 +46,13 @@ interface Opts {
|
|
46
46
|
interface AvroDecodeOptions {
|
47
47
|
readerSchema?: RawAvroSchema | AvroSchema | Schema
|
48
48
|
}
|
49
|
-
interface DecodeOptions {
|
49
|
+
export interface DecodeOptions {
|
50
50
|
[SchemaType.AVRO]?: AvroDecodeOptions
|
51
51
|
}
|
52
52
|
|
53
53
|
const DEFAULT_OPTS = {
|
54
54
|
compatibility: COMPATIBILITY.BACKWARD,
|
55
|
-
separator:
|
55
|
+
separator: DEFAULT_SEPARATOR,
|
56
56
|
}
|
57
57
|
export default class SchemaRegistry {
|
58
58
|
private api: SchemaRegistryAPIClient
|
@@ -62,10 +62,10 @@ export default class SchemaRegistry {
|
|
62
62
|
public cache: Cache
|
63
63
|
|
64
64
|
constructor(
|
65
|
-
{ auth, clientId, host, retry, agent }: SchemaRegistryAPIClientArgs,
|
65
|
+
{ auth, clientId, host, retry, agent, middlewares }: SchemaRegistryAPIClientArgs,
|
66
66
|
options?: SchemaRegistryAPIClientOptions,
|
67
67
|
) {
|
68
|
-
this.api = API({ auth, clientId, host, retry, agent })
|
68
|
+
this.api = API({ auth, clientId, host, retry, agent, middlewares })
|
69
69
|
this.cache = new Cache()
|
70
70
|
this.options = options
|
71
71
|
}
|
@@ -138,7 +138,7 @@ export default class SchemaRegistry {
|
|
138
138
|
)
|
139
139
|
}
|
140
140
|
} catch (error) {
|
141
|
-
if (error.status !== 404) {
|
141
|
+
if (!error || typeof error !== 'object' || !('status' in error) || error.status !== 404) {
|
142
142
|
throw error
|
143
143
|
} else {
|
144
144
|
isFirstTimeRegistration = true
|
@@ -355,7 +355,7 @@ export default class SchemaRegistry {
|
|
355
355
|
|
356
356
|
return id
|
357
357
|
} catch (error) {
|
358
|
-
if (error
|
358
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
359
359
|
throw new ConfluentSchemaRegistryError(error)
|
360
360
|
}
|
361
361
|
|
@@ -370,18 +370,17 @@ export default class SchemaRegistry {
|
|
370
370
|
return id
|
371
371
|
}
|
372
372
|
|
373
|
-
private getSchemaOriginRequest(registryId: number) {
|
373
|
+
private async getSchemaOriginRequest(registryId: number): Promise<Response> {
|
374
374
|
// ensure that cache-misses result in a single origin request
|
375
|
-
|
376
|
-
|
377
|
-
} else {
|
378
|
-
const request = this.api.Schema.find({ id: registryId }).finally(() => {
|
379
|
-
delete this.cacheMissRequests[registryId]
|
380
|
-
})
|
375
|
+
const req = this.cacheMissRequests[registryId]
|
376
|
+
if (req) return req
|
381
377
|
|
382
|
-
|
378
|
+
const request = this.api.Schema.find({ id: registryId }).finally(() => {
|
379
|
+
delete this.cacheMissRequests[registryId]
|
380
|
+
})
|
383
381
|
|
384
|
-
|
385
|
-
|
382
|
+
this.cacheMissRequests[registryId] = request
|
383
|
+
|
384
|
+
return request
|
386
385
|
}
|
387
386
|
}
|
package/src/api/index.spec.ts
CHANGED
@@ -1,7 +1,27 @@
|
|
1
|
+
import { Middleware } from 'mappersmith'
|
1
2
|
import API from '.'
|
2
3
|
import { mockClient, install, uninstall } from 'mappersmith/test'
|
3
4
|
|
4
|
-
const
|
5
|
+
const customMiddleware: Middleware = jest.fn(() => {
|
6
|
+
return {
|
7
|
+
async request(request) {
|
8
|
+
return request.enhance({
|
9
|
+
headers: {
|
10
|
+
Authorization: 'Bearer Random',
|
11
|
+
},
|
12
|
+
})
|
13
|
+
},
|
14
|
+
async response(next) {
|
15
|
+
return next()
|
16
|
+
},
|
17
|
+
}
|
18
|
+
})
|
19
|
+
|
20
|
+
const client = API({
|
21
|
+
clientId: 'test-client',
|
22
|
+
host: 'http://example.com',
|
23
|
+
middlewares: [customMiddleware],
|
24
|
+
})
|
5
25
|
const mock = mockClient<typeof client>(client)
|
6
26
|
.resource('Schema')
|
7
27
|
.method('find')
|
@@ -14,10 +34,12 @@ describe('API Client', () => {
|
|
14
34
|
|
15
35
|
afterEach(() => uninstall())
|
16
36
|
|
17
|
-
it('should include a user agent header', async () => {
|
37
|
+
it('should include a user agent header and call custom middleware', async () => {
|
18
38
|
const response = await client.Schema.find({ id: 'abc' })
|
19
39
|
|
20
40
|
expect(mock.callsCount()).toBe(1)
|
21
41
|
expect(response.request().header('User-Agent')).not.toBeUndefined()
|
42
|
+
expect(response.request().header('Authorization')).toBe('Bearer Random')
|
43
|
+
expect(customMiddleware).toHaveBeenCalled()
|
22
44
|
})
|
23
45
|
})
|
package/src/api/index.ts
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
import { Agent } from 'http'
|
2
|
-
import forge, {
|
2
|
+
import forge, {
|
3
|
+
Authorization,
|
4
|
+
Client,
|
5
|
+
GatewayConfiguration,
|
6
|
+
Middleware,
|
7
|
+
ManifestOptions,
|
8
|
+
} from 'mappersmith'
|
3
9
|
import RetryMiddleware, { RetryMiddlewareOptions } from 'mappersmith/middleware/retry/v2'
|
4
10
|
import BasicAuthMiddleware from 'mappersmith/middleware/basic-auth'
|
5
11
|
|
@@ -23,6 +29,7 @@ export interface SchemaRegistryAPIClientArgs {
|
|
23
29
|
retry?: Partial<RetryMiddlewareOptions>
|
24
30
|
/** HTTP Agent that will be passed to underlying API calls */
|
25
31
|
agent?: Agent
|
32
|
+
middlewares?: Middleware[]
|
26
33
|
}
|
27
34
|
|
28
35
|
// TODO: Improve typings
|
@@ -48,10 +55,11 @@ export default ({
|
|
48
55
|
host,
|
49
56
|
retry = {},
|
50
57
|
agent,
|
58
|
+
middlewares = [],
|
51
59
|
}: SchemaRegistryAPIClientArgs): SchemaRegistryAPIClient => {
|
52
60
|
const clientId = userClientId || DEFAULT_API_CLIENT_ID
|
53
61
|
// FIXME: ResourcesType typings is not exposed by mappersmith
|
54
|
-
const manifest:
|
62
|
+
const manifest: ManifestOptions<any> = {
|
55
63
|
clientId,
|
56
64
|
ignoreGlobalMiddleware: true,
|
57
65
|
host,
|
@@ -61,6 +69,7 @@ export default ({
|
|
61
69
|
RetryMiddleware(Object.assign(DEFAULT_RETRY, retry)),
|
62
70
|
errorMiddleware,
|
63
71
|
...(auth ? [BasicAuthMiddleware(auth)] : []),
|
72
|
+
...middlewares,
|
64
73
|
],
|
65
74
|
resources: {
|
66
75
|
Schema: {
|
@@ -30,7 +30,7 @@ const errorMiddleware: Middleware = ({ clientId }) => ({
|
|
30
30
|
new Promise((resolve, reject) =>
|
31
31
|
next()
|
32
32
|
.then(resolve)
|
33
|
-
.catch((response: Response) => reject(new ResponseError(clientId, response))),
|
33
|
+
.catch((response: Response) => reject(new ResponseError(clientId ?? '', response))),
|
34
34
|
),
|
35
35
|
})
|
36
36
|
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
import { default as SchemaRegistry, DecodeOptions } from './SchemaRegistry'
|
2
|
+
export { SchemaRegistry, DecodeOptions }
|
2
3
|
export * from './utils'
|
3
4
|
export { SchemaType } from './@types'
|
4
5
|
export { COMPATIBILITY } from './constants'
|
@@ -96,6 +96,7 @@ export const schemaFromConfluentSchema = (
|
|
96
96
|
|
97
97
|
return schema
|
98
98
|
} catch (err) {
|
99
|
-
throw new ConfluentSchemaRegistryArgumentError(err.message)
|
99
|
+
if (err instanceof Error) throw new ConfluentSchemaRegistryArgumentError(err.message)
|
100
|
+
throw err
|
100
101
|
}
|
101
102
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import path from 'path'
|
2
|
-
import fs from 'fs-extra'
|
3
|
-
import execa from 'execa'
|
4
2
|
import avro from 'avsc'
|
3
|
+
import { exec } from 'child_process'
|
4
|
+
import fs from 'node:fs'
|
5
5
|
|
6
6
|
import SchemaRegistry from '../SchemaRegistry'
|
7
7
|
import { avdlToAVSCAsync } from './avdlToAVSC'
|
@@ -9,13 +9,26 @@ import { avdlToAVSCAsync } from './avdlToAVSC'
|
|
9
9
|
const registry = new SchemaRegistry({ host: 'http://localhost:8982' })
|
10
10
|
const absolutePath = (...paths: string[]) => path.join(__dirname, '../..', ...paths)
|
11
11
|
|
12
|
+
const promisifiedExec = async (command: string): Promise<string> => {
|
13
|
+
return new Promise((resolve, reject) => {
|
14
|
+
exec(command, (error, stdout) => {
|
15
|
+
if (error) {
|
16
|
+
return reject(error)
|
17
|
+
}
|
18
|
+
|
19
|
+
return resolve(stdout)
|
20
|
+
})
|
21
|
+
})
|
22
|
+
}
|
23
|
+
|
12
24
|
const compareWithJavaImplementation = (avdlPath: string, name: string) => async () => {
|
13
25
|
const absolutePathToAvdlToAVSC = absolutePath('./bin/avdlToAVSC.sh')
|
14
|
-
const execaArgs = [`./fixtures/avdl/${avdlPath}`, name]
|
15
26
|
|
16
27
|
let expectedAVSC
|
17
28
|
try {
|
18
|
-
const
|
29
|
+
const result = await promisifiedExec(
|
30
|
+
`${absolutePathToAvdlToAVSC} ./fixtures/avdl/${avdlPath} ${name}`,
|
31
|
+
)
|
19
32
|
expectedAVSC = JSON.parse(result)
|
20
33
|
} catch (error) {
|
21
34
|
console.error(`Error when running ${absolutePathToAvdlToAVSC}`, error) // eslint-disable-line no-console
|
@@ -31,7 +44,17 @@ const compareWithJavaImplementation = (avdlPath: string, name: string) => async
|
|
31
44
|
|
32
45
|
beforeAll(async () => {
|
33
46
|
jest.setTimeout(10000)
|
34
|
-
|
47
|
+
|
48
|
+
// deletes all the files from tmp dir
|
49
|
+
const tmpDirectory = absolutePath('./tmp')
|
50
|
+
try {
|
51
|
+
fs.statSync(tmpDirectory)
|
52
|
+
} catch (e) {
|
53
|
+
fs.mkdirSync(tmpDirectory)
|
54
|
+
}
|
55
|
+
for (const file of fs.readdirSync(tmpDirectory)) {
|
56
|
+
fs.unlinkSync(path.join(tmpDirectory, file))
|
57
|
+
}
|
35
58
|
})
|
36
59
|
|
37
60
|
test('simple protocol', compareWithJavaImplementation('simple.avdl', 'Simple'))
|
package/src/utils/avdlToAVSC.ts
CHANGED
@@ -21,7 +21,7 @@ interface Field {
|
|
21
21
|
|
22
22
|
let cache: any
|
23
23
|
const merge = Object.assign
|
24
|
-
const isObject = (obj: unknown): obj is Obj => obj && typeof obj === 'object'
|
24
|
+
const isObject = (obj: unknown): obj is Obj => !!obj && typeof obj === 'object'
|
25
25
|
const isIterable = (obj: unknown): obj is Iterable =>
|
26
26
|
isObject(obj) && typeof obj.map !== 'undefined'
|
27
27
|
const isFieldArray = (field: unknown): field is Field =>
|
@@ -92,12 +92,12 @@ export function avdlToAVSC(path: any) {
|
|
92
92
|
export async function avdlToAVSCAsync(path: string) {
|
93
93
|
cache = {}
|
94
94
|
|
95
|
-
const protocol:
|
95
|
+
const protocol: Record<string, any> = await new Promise((resolve, reject) => {
|
96
96
|
assembleProtocol(path, (err: AssembleProtocolError, schema) => {
|
97
97
|
if (err) {
|
98
98
|
reject(new ConfluentSchemaRegistryError(`${err.message}. Caused by: ${err.path}`))
|
99
99
|
} else {
|
100
|
-
resolve(schema)
|
100
|
+
resolve(schema as Record<string, any>)
|
101
101
|
}
|
102
102
|
})
|
103
103
|
})
|
package/tmp/Array.avsc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Array",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "properties",
|
7
|
+
"type" : {
|
8
|
+
"type" : "array",
|
9
|
+
"items" : {
|
10
|
+
"type" : "record",
|
11
|
+
"name" : "KeyValue",
|
12
|
+
"fields" : [ {
|
13
|
+
"name" : "key",
|
14
|
+
"type" : "string"
|
15
|
+
}, {
|
16
|
+
"name" : "value",
|
17
|
+
"type" : "string"
|
18
|
+
} ]
|
19
|
+
}
|
20
|
+
}
|
21
|
+
} ]
|
22
|
+
}
|
package/tmp/Array1.avsc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Array1",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "array2",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "array",
|
9
|
+
"items" : {
|
10
|
+
"type" : "record",
|
11
|
+
"name" : "Array2",
|
12
|
+
"fields" : [ {
|
13
|
+
"name" : "array2_name",
|
14
|
+
"type" : "string"
|
15
|
+
}, {
|
16
|
+
"name" : "foos",
|
17
|
+
"type" : [ "null", {
|
18
|
+
"type" : "enum",
|
19
|
+
"name" : "Foos",
|
20
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
21
|
+
} ],
|
22
|
+
"default" : null
|
23
|
+
} ]
|
24
|
+
}
|
25
|
+
} ],
|
26
|
+
"default" : null
|
27
|
+
} ]
|
28
|
+
}
|
package/tmp/Array2.avsc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Array2",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "array2_name",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "foos",
|
10
|
+
"type" : [ "null", {
|
11
|
+
"type" : "enum",
|
12
|
+
"name" : "Foos",
|
13
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
14
|
+
} ],
|
15
|
+
"default" : null
|
16
|
+
} ]
|
17
|
+
}
|
package/tmp/Array3.avsc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Array3",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "bam",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "record",
|
9
|
+
"name" : "Bam",
|
10
|
+
"fields" : [ {
|
11
|
+
"name" : "bam",
|
12
|
+
"type" : "string"
|
13
|
+
} ]
|
14
|
+
} ],
|
15
|
+
"default" : null
|
16
|
+
} ]
|
17
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "ArrayUnion",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "properties",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "array",
|
9
|
+
"items" : {
|
10
|
+
"type" : "record",
|
11
|
+
"name" : "KeyValue",
|
12
|
+
"fields" : [ {
|
13
|
+
"name" : "key",
|
14
|
+
"type" : "string"
|
15
|
+
}, {
|
16
|
+
"name" : "value",
|
17
|
+
"type" : "string"
|
18
|
+
} ]
|
19
|
+
}
|
20
|
+
} ],
|
21
|
+
"default" : null
|
22
|
+
} ]
|
23
|
+
}
|
package/tmp/Bam.avsc
ADDED
package/tmp/Bar.avsc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Bar",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "baz",
|
7
|
+
"type" : {
|
8
|
+
"type" : "record",
|
9
|
+
"name" : "Baz",
|
10
|
+
"fields" : [ {
|
11
|
+
"name" : "array1",
|
12
|
+
"type" : [ "null", {
|
13
|
+
"type" : "array",
|
14
|
+
"items" : {
|
15
|
+
"type" : "record",
|
16
|
+
"name" : "Array1",
|
17
|
+
"fields" : [ {
|
18
|
+
"name" : "array2",
|
19
|
+
"type" : [ "null", {
|
20
|
+
"type" : "array",
|
21
|
+
"items" : {
|
22
|
+
"type" : "record",
|
23
|
+
"name" : "Array2",
|
24
|
+
"fields" : [ {
|
25
|
+
"name" : "array2_name",
|
26
|
+
"type" : "string"
|
27
|
+
}, {
|
28
|
+
"name" : "foos",
|
29
|
+
"type" : [ "null", {
|
30
|
+
"type" : "enum",
|
31
|
+
"name" : "Foos",
|
32
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
33
|
+
} ],
|
34
|
+
"default" : null
|
35
|
+
} ]
|
36
|
+
}
|
37
|
+
} ],
|
38
|
+
"default" : null
|
39
|
+
} ]
|
40
|
+
}
|
41
|
+
} ],
|
42
|
+
"default" : null
|
43
|
+
} ]
|
44
|
+
}
|
45
|
+
} ]
|
46
|
+
}
|
package/tmp/Baz.avsc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Baz",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "array1",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "array",
|
9
|
+
"items" : {
|
10
|
+
"type" : "record",
|
11
|
+
"name" : "Array1",
|
12
|
+
"fields" : [ {
|
13
|
+
"name" : "array2",
|
14
|
+
"type" : [ "null", {
|
15
|
+
"type" : "array",
|
16
|
+
"items" : {
|
17
|
+
"type" : "record",
|
18
|
+
"name" : "Array2",
|
19
|
+
"fields" : [ {
|
20
|
+
"name" : "array2_name",
|
21
|
+
"type" : "string"
|
22
|
+
}, {
|
23
|
+
"name" : "foos",
|
24
|
+
"type" : [ "null", {
|
25
|
+
"type" : "enum",
|
26
|
+
"name" : "Foos",
|
27
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
28
|
+
} ],
|
29
|
+
"default" : null
|
30
|
+
} ]
|
31
|
+
}
|
32
|
+
} ],
|
33
|
+
"default" : null
|
34
|
+
} ]
|
35
|
+
}
|
36
|
+
} ],
|
37
|
+
"default" : null
|
38
|
+
} ]
|
39
|
+
}
|
package/tmp/Complex.avsc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Complex",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "array1",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "array",
|
9
|
+
"items" : {
|
10
|
+
"type" : "record",
|
11
|
+
"name" : "Array1",
|
12
|
+
"fields" : [ {
|
13
|
+
"name" : "array2",
|
14
|
+
"type" : [ "null", {
|
15
|
+
"type" : "array",
|
16
|
+
"items" : {
|
17
|
+
"type" : "record",
|
18
|
+
"name" : "Array2",
|
19
|
+
"fields" : [ {
|
20
|
+
"name" : "array2_name",
|
21
|
+
"type" : "string"
|
22
|
+
}, {
|
23
|
+
"name" : "foos",
|
24
|
+
"type" : [ "null", {
|
25
|
+
"type" : "enum",
|
26
|
+
"name" : "Foos",
|
27
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
28
|
+
} ],
|
29
|
+
"default" : null
|
30
|
+
} ]
|
31
|
+
}
|
32
|
+
} ],
|
33
|
+
"default" : null
|
34
|
+
} ]
|
35
|
+
}
|
36
|
+
} ],
|
37
|
+
"default" : null
|
38
|
+
}, {
|
39
|
+
"name" : "array3",
|
40
|
+
"type" : {
|
41
|
+
"type" : "array",
|
42
|
+
"items" : {
|
43
|
+
"type" : "record",
|
44
|
+
"name" : "Array3",
|
45
|
+
"fields" : [ {
|
46
|
+
"name" : "bam",
|
47
|
+
"type" : [ "null", {
|
48
|
+
"type" : "record",
|
49
|
+
"name" : "Bam",
|
50
|
+
"fields" : [ {
|
51
|
+
"name" : "bam",
|
52
|
+
"type" : "string"
|
53
|
+
} ]
|
54
|
+
} ],
|
55
|
+
"default" : null
|
56
|
+
} ]
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}, {
|
60
|
+
"name" : "bar",
|
61
|
+
"type" : {
|
62
|
+
"type" : "record",
|
63
|
+
"name" : "Bar",
|
64
|
+
"fields" : [ {
|
65
|
+
"name" : "baz",
|
66
|
+
"type" : {
|
67
|
+
"type" : "record",
|
68
|
+
"name" : "Baz",
|
69
|
+
"fields" : [ {
|
70
|
+
"name" : "array1",
|
71
|
+
"type" : [ "null", {
|
72
|
+
"type" : "array",
|
73
|
+
"items" : "Array1"
|
74
|
+
} ],
|
75
|
+
"default" : null
|
76
|
+
} ]
|
77
|
+
}
|
78
|
+
} ]
|
79
|
+
}
|
80
|
+
} ]
|
81
|
+
}
|
package/tmp/Enum.avsc
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "EnumUnion",
|
4
|
+
"namespace" : "com.org.app.track",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "foos",
|
7
|
+
"type" : [ "null", {
|
8
|
+
"type" : "enum",
|
9
|
+
"name" : "Foos",
|
10
|
+
"symbols" : [ "foo", "bar", "baz" ]
|
11
|
+
} ],
|
12
|
+
"default" : null
|
13
|
+
} ]
|
14
|
+
}
|
package/tmp/Foos.avsc
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "ImportMultipleNamespaces",
|
4
|
+
"namespace" : "com.org.domain.fixtures",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "metadata",
|
7
|
+
"type" : {
|
8
|
+
"type" : "record",
|
9
|
+
"name" : "Metadata",
|
10
|
+
"namespace" : "com.org.messaging",
|
11
|
+
"fields" : [ {
|
12
|
+
"name" : "event_id",
|
13
|
+
"type" : "string"
|
14
|
+
}, {
|
15
|
+
"name" : "publisher_system_id",
|
16
|
+
"type" : "string"
|
17
|
+
}, {
|
18
|
+
"name" : "occurred_at",
|
19
|
+
"type" : {
|
20
|
+
"type" : "long",
|
21
|
+
"logicalType" : "timestamp-millis"
|
22
|
+
}
|
23
|
+
}, {
|
24
|
+
"name" : "published_at",
|
25
|
+
"type" : {
|
26
|
+
"type" : "long",
|
27
|
+
"logicalType" : "timestamp-millis"
|
28
|
+
}
|
29
|
+
}, {
|
30
|
+
"name" : "correlation_id",
|
31
|
+
"type" : "string"
|
32
|
+
} ]
|
33
|
+
}
|
34
|
+
} ]
|
35
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Metadata",
|
4
|
+
"namespace" : "com.org.messaging",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "event_id",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "publisher_system_id",
|
10
|
+
"type" : "string"
|
11
|
+
}, {
|
12
|
+
"name" : "occurred_at",
|
13
|
+
"type" : {
|
14
|
+
"type" : "long",
|
15
|
+
"logicalType" : "timestamp-millis"
|
16
|
+
}
|
17
|
+
}, {
|
18
|
+
"name" : "published_at",
|
19
|
+
"type" : {
|
20
|
+
"type" : "long",
|
21
|
+
"logicalType" : "timestamp-millis"
|
22
|
+
}
|
23
|
+
}, {
|
24
|
+
"name" : "correlation_id",
|
25
|
+
"type" : "string"
|
26
|
+
} ]
|
27
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Multiple",
|
4
|
+
"namespace" : "com.org.domain.fixtures",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "foo",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "bar",
|
10
|
+
"type" : {
|
11
|
+
"type" : "record",
|
12
|
+
"name" : "Bar",
|
13
|
+
"fields" : [ {
|
14
|
+
"name" : "baz",
|
15
|
+
"type" : {
|
16
|
+
"type" : "record",
|
17
|
+
"name" : "Baz",
|
18
|
+
"fields" : [ {
|
19
|
+
"name" : "bam",
|
20
|
+
"type" : "string"
|
21
|
+
} ]
|
22
|
+
}
|
23
|
+
} ]
|
24
|
+
}
|
25
|
+
} ]
|
26
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "MultipleNamespaces",
|
4
|
+
"namespace" : "com.org.confluentschemaregistry",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "metadata",
|
7
|
+
"type" : {
|
8
|
+
"type" : "record",
|
9
|
+
"name" : "Metadata",
|
10
|
+
"namespace" : "com.org.messaging",
|
11
|
+
"fields" : [ {
|
12
|
+
"name" : "event_id",
|
13
|
+
"type" : "string"
|
14
|
+
}, {
|
15
|
+
"name" : "publisher_system_id",
|
16
|
+
"type" : "string"
|
17
|
+
}, {
|
18
|
+
"name" : "occurred_at",
|
19
|
+
"type" : {
|
20
|
+
"type" : "long",
|
21
|
+
"logicalType" : "timestamp-millis"
|
22
|
+
}
|
23
|
+
}, {
|
24
|
+
"name" : "published_at",
|
25
|
+
"type" : {
|
26
|
+
"type" : "long",
|
27
|
+
"logicalType" : "timestamp-millis"
|
28
|
+
}
|
29
|
+
}, {
|
30
|
+
"name" : "correlation_id",
|
31
|
+
"type" : "string"
|
32
|
+
} ]
|
33
|
+
}
|
34
|
+
}, {
|
35
|
+
"name" : "id",
|
36
|
+
"type" : "string"
|
37
|
+
}, {
|
38
|
+
"name" : "amount",
|
39
|
+
"type" : "int"
|
40
|
+
}, {
|
41
|
+
"name" : "description",
|
42
|
+
"type" : "string"
|
43
|
+
} ]
|
44
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "MultipleUnion",
|
4
|
+
"namespace" : "com.org.domain.fixtures",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "foo",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "bar",
|
10
|
+
"type" : [ "null", {
|
11
|
+
"type" : "record",
|
12
|
+
"name" : "Bar",
|
13
|
+
"fields" : [ {
|
14
|
+
"name" : "baz",
|
15
|
+
"type" : [ "null", {
|
16
|
+
"type" : "record",
|
17
|
+
"name" : "Baz",
|
18
|
+
"fields" : [ {
|
19
|
+
"name" : "bam",
|
20
|
+
"type" : "string"
|
21
|
+
} ]
|
22
|
+
} ],
|
23
|
+
"default" : null
|
24
|
+
} ]
|
25
|
+
} ],
|
26
|
+
"default" : null
|
27
|
+
} ]
|
28
|
+
}
|
package/tmp/Simple.avsc
ADDED
package/tmp/Two.avsc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Two",
|
4
|
+
"namespace" : "com.org.domain.fixtures",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "foo",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "bar",
|
10
|
+
"type" : {
|
11
|
+
"type" : "record",
|
12
|
+
"name" : "Bar",
|
13
|
+
"fields" : [ {
|
14
|
+
"name" : "baz",
|
15
|
+
"type" : "string"
|
16
|
+
} ]
|
17
|
+
}
|
18
|
+
} ]
|
19
|
+
}
|
package/tmp/Union.avsc
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"type" : "record",
|
3
|
+
"name" : "Union",
|
4
|
+
"namespace" : "com.org.domain.fixtures",
|
5
|
+
"fields" : [ {
|
6
|
+
"name" : "foo",
|
7
|
+
"type" : "string"
|
8
|
+
}, {
|
9
|
+
"name" : "bar",
|
10
|
+
"type" : [ "null", {
|
11
|
+
"type" : "record",
|
12
|
+
"name" : "Bar",
|
13
|
+
"fields" : [ {
|
14
|
+
"name" : "baz",
|
15
|
+
"type" : "string"
|
16
|
+
} ]
|
17
|
+
} ],
|
18
|
+
"default" : null
|
19
|
+
} ]
|
20
|
+
}
|
package/dockest.ts
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
import { Dockest, sleepWithLog, logLevel } from 'dockest'
|
2
|
-
import { DockestService } from 'dockest/dist/@types'
|
3
|
-
|
4
|
-
const dockest = new Dockest({
|
5
|
-
composeFile: 'docker-compose.yml',
|
6
|
-
dumpErrors: true,
|
7
|
-
jestLib: require('jest'),
|
8
|
-
jestOpts: {
|
9
|
-
updateSnapshot: true,
|
10
|
-
},
|
11
|
-
logLevel: logLevel.DEBUG,
|
12
|
-
})
|
13
|
-
|
14
|
-
const dockestServices: DockestService[] = [
|
15
|
-
{
|
16
|
-
serviceName: 'zooKeeper',
|
17
|
-
dependents: [
|
18
|
-
{
|
19
|
-
serviceName: 'kafka',
|
20
|
-
readinessCheck: () => sleepWithLog(10, `Sleeping for Kafka`),
|
21
|
-
},
|
22
|
-
],
|
23
|
-
},
|
24
|
-
{
|
25
|
-
serviceName: 'schemaRegistry',
|
26
|
-
readinessCheck: () => sleepWithLog(35, `Sleeping for Schema Registry`),
|
27
|
-
},
|
28
|
-
]
|
29
|
-
|
30
|
-
dockest.run(dockestServices)
|