-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8a6d819
commit 4ac866c
Showing
5 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
163 changes: 163 additions & 0 deletions
163
backend/components/schema-registry-manager/backend/src/app.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
|
||
import dotenv from "dotenv"; | ||
import express, { Express, Request, Response } from "express"; | ||
import { SchemaProvider } from "./types"; | ||
import { createSchema, getSchemaInfo, getSchemaVersions, getSchemas, updateSchema } from "./providers/karapace"; | ||
|
||
dotenv.config(); | ||
|
||
const app: Express = express(); | ||
const port = process.env.PORT || 3000; | ||
const bodyParser = require('body-parser'); | ||
const currentProvider: SchemaProvider = SchemaProvider.karapace; | ||
|
||
// Middleware | ||
app.use(bodyParser.json()); | ||
|
||
app.get('/schemas.provider', (req: Request, res: Response) => { | ||
res.status(200).send(currentProvider); | ||
}); | ||
|
||
app.get('/schemas.list', (req: Request, res: Response) => { | ||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
getSchemas().then((response: string[]) => { | ||
res.send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
app.get('/schemas.versions', (req: Request, res: Response) => { | ||
if (!req.query.topicName) { | ||
res.status(400).send('Missing topicName'); | ||
return; | ||
} | ||
|
||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
getSchemaVersions(req.query.topicName as string).then((response: any) => { | ||
res.status(200).send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
app.get('/schemas.info', (req: Request, res: Response) => { | ||
if (!req.query.topicName) { | ||
res.status(400).send('Missing topicName'); | ||
return; | ||
} | ||
|
||
let version = 'latest'; | ||
if (req.query.version) { | ||
version = req.query.version as string; | ||
} | ||
|
||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
getSchemaInfo(req.query.topicName as string, version).then((response: any) => { | ||
res.status(200).send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
app.post('/schemas.update', (req: Request, res: Response) => { | ||
if (!req.query.topicName) { | ||
res.status(400).send('Missing topicName'); | ||
return; | ||
} | ||
if (!req.body.schema) { | ||
res.status(400).send('Missing schema'); | ||
return; | ||
} | ||
|
||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
updateSchema(req.query.topicName as string, req.body.schema as string).then((response: any) => { | ||
res.status(200).send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
app.post('/schemas.create', (req: Request, res: Response) => { | ||
if (!req.query.topicName) { | ||
res.status(400).send('Missing topicName'); | ||
return; | ||
} | ||
if (!req.body.schema) { | ||
res.status(400).send('Missing schema'); | ||
return; | ||
} | ||
|
||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
createSchema(req.query.topicName as string, req.body.schema as string).then((response: any) => { | ||
res.status(200).send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
app.post('/schemas.compatibility', (req: Request, res: Response) => { | ||
if (!req.query.topicName) { | ||
res.status(400).send('Missing topicName'); | ||
return; | ||
} | ||
if (!req.query.version) { | ||
res.status(400).send('Missing version'); | ||
return; | ||
} | ||
if (!req.body.schema) { | ||
res.status(400).send('Missing schema'); | ||
return; | ||
} | ||
|
||
switch (currentProvider) { | ||
case SchemaProvider.karapace: | ||
createSchema(req.query.topicName as string, req.body.schema as string).then((response: any) => { | ||
res.status(200).send(response); | ||
}).catch((e: any) => { | ||
res.status(500).send(e); | ||
}); | ||
break; | ||
default: | ||
res.status(404).send('Provider Not Found'); | ||
break; | ||
} | ||
}); | ||
|
||
async function main() { | ||
app.listen(port, () => { | ||
console.log(`Server is running on http://localhost:${port}`); | ||
}); | ||
} | ||
|
||
main().catch(console.error); |
12 changes: 12 additions & 0 deletions
12
backend/components/schema-registry-manager/backend/src/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"dependencies": { | ||
"@types/express": "^4.17.21", | ||
"@types/node": "^20.10.3", | ||
"node-fetch": "^2.6.1" | ||
}, | ||
"devDependencies": { | ||
"@types/express": "^4.17.21", | ||
"@types/node": "^20.10.3", | ||
"typescript": "^5.3.2" | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
backend/components/schema-registry-manager/backend/src/providers/karapace.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
export async function getSchemas() { | ||
return getData('subjects').then(response => { | ||
return response; | ||
}); | ||
}; | ||
|
||
export async function getSchemaVersions(topicName: string) { | ||
return getData(`subjects/${topicName}/versions`).then(response => { | ||
if (response.error_code && response.error_code.toString().includes('404') && !topicName.includes('-value')) { | ||
return Promise.reject('404 Not Found'); | ||
} | ||
return response; | ||
}); | ||
}; | ||
|
||
export async function getSchemaInfo(topicName: string, version: string) { | ||
return getData(`subjects/${topicName}/versions/${version}`).then(response => { | ||
if (response.error_code && response.error_code.toString().includes('404') && !topicName.includes('-value')) { | ||
return Promise.reject('404 Not Found'); | ||
} | ||
return response; | ||
}); | ||
}; | ||
|
||
export async function updateSchema(topicName: string, schema: string) { | ||
const body = { | ||
schema: JSON.stringify({...JSON.parse(schema)}), | ||
}; | ||
return postData(`subjects/${topicName}/versions`, body).then(response => { | ||
if (response.error_code && response.error_code.toString().includes('404') && !topicName.includes('-value')) { | ||
return Promise.reject('404 Not Found'); | ||
} | ||
if (response.id) return response; | ||
if (response.message) return Promise.reject(response.message); | ||
return Promise.reject('Unknown Error'); | ||
}); | ||
}; | ||
|
||
export async function createSchema(topicName: string, schema: string) { | ||
const body = { | ||
schema: JSON.stringify({...JSON.parse(schema)}), | ||
}; | ||
return postData(`subjects/${topicName}/versions`, body) | ||
.then(response => { | ||
if (response.id) return response; | ||
if (response.message) return Promise.reject(response.message); | ||
return Promise.reject('Unknown Error'); | ||
}) | ||
.catch(e => { | ||
return Promise.reject(e); | ||
}); | ||
}; | ||
|
||
export async function checkCompatibilityOfNewSchema(topicName: string, schema: string, version: number) { | ||
const body = { | ||
schema: JSON.stringify({...JSON.parse(schema)}), | ||
}; | ||
return postData(`compatibility/subjects/${topicName}/versions/${version}`, body) | ||
.then(response => { | ||
if (response.error_code && response.error_code.toString().includes('404') && !topicName.includes('-value')) { | ||
return Promise.reject('404 Not Found'); | ||
} | ||
if (response.is_compatible !== undefined) { | ||
if (response.is_compatible === true) { | ||
return Promise.resolve(true); | ||
} | ||
return Promise.reject('Schema Not Compatible'); | ||
} | ||
if (response.message) return Promise.reject(response.message); | ||
return Promise.reject('Unknown Error'); | ||
}) | ||
.catch(e => { | ||
return Promise.reject(e); | ||
}); | ||
}; | ||
|
||
// export const deleteSchema = (topicName: string) => async () => { | ||
// return deleteData(`subjects/${topicName}`).then(response => { | ||
// if (response.error_code && response.error_code.toString().includes('404') && !topicName.includes('-value')) { | ||
// return Promise.reject('404 Not Found'); | ||
// } | ||
// return Promise.resolve(true); | ||
// }); | ||
// }; | ||
|
||
// export const getLastMessage = (topicName: string) => async (dispatch: Dispatch<any>) => { | ||
// const body = { | ||
// ksql: `PRINT '${topicName}' FROM BEGINNING LIMIT 1;`, | ||
// streamsProperties: {}, | ||
// }; | ||
// return postData('query', body).then(response => { | ||
// dispatch(setLastMessage(response)); | ||
// return Promise.resolve(true); | ||
// }); | ||
// }; | ||
|
||
async function getData(url: string) { | ||
const response = await fetch(process.env.URL + '/' + url, { | ||
method: 'GET', | ||
}); | ||
return response.json(); | ||
} | ||
|
||
async function deleteData(url: string) { | ||
const response = await fetch(process.env.URL + '/' + url, { | ||
method: 'DELETE', | ||
}); | ||
return response.json(); | ||
} | ||
|
||
async function postData(url: string, body: any) { | ||
const response = await fetch(process.env.URL + '/' + url, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/vnd.schemaregistry.v1+json', | ||
}, | ||
body: JSON.stringify(body), | ||
}); | ||
|
||
return response.json(); | ||
} |
10 changes: 10 additions & 0 deletions
10
backend/components/schema-registry-manager/backend/src/tsconfig.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "ES2016", | ||
"module": "commonjs", | ||
"strict": true, | ||
"esModuleInterop": true, | ||
"skipLibCheck": true, | ||
"forceConsistentCasingInFileNames": true | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
backend/components/schema-registry-manager/backend/src/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export enum SchemaProvider { | ||
karapace = 'karapace', | ||
confluentCloud = 'confluent-cloud', | ||
} | ||
|
||
module.exports = { | ||
SchemaProvider: SchemaProvider | ||
}; |