Commit fb15c01c authored by vinay's avatar vinay
Browse files

ADD : Broken X-Form Serving Api

No related merge requests found
Showing with 210 additions and 7 deletions
+210 -7
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
"cache-manager": "^4.1.0", "cache-manager": "^4.1.0",
"cache-manager-redis-store": "^3.0.1", "cache-manager-redis-store": "^3.0.1",
"ioredis": "^5.3.1", "ioredis": "^5.3.1",
"libxmljs": "^1.0.9",
"localforage": "^1.10.0",
"minio": "^7.0.32", "minio": "^7.0.32",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"request": "^2.88.2", "request": "^2.88.2",
...@@ -38,8 +40,7 @@ ...@@ -38,8 +40,7 @@
"webpack": "^5.74.0", "webpack": "^5.74.0",
"xml2js": "^0.4.23", "xml2js": "^0.4.23",
"xml2json": "^0.12.0", "xml2json": "^0.12.0",
"xmldom": "^0.6.0", "xmldom": "^0.6.0"
"localforage": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@nestjs/cli": "^8.0.0", "@nestjs/cli": "^8.0.0",
......
...@@ -41,11 +41,14 @@ type PrefillDto = { ...@@ -41,11 +41,14 @@ type PrefillDto = {
@Controller() @Controller()
export class AppController { export class AppController {
getHello(): any {
throw new Error('Method not implemented.');
}
constructor( constructor(
@Inject(CACHE_MANAGER) private cacheManager: Cache, @Inject(CACHE_MANAGER) private cacheManager: Cache,
private readonly appService: AppService, private readonly appService: AppService,
private configService: ConfigService, private configService: ConfigService,
) { } ) {}
MINIO_ENDPOINT = this.configService.get('MINIO_ENDPOINT'); MINIO_ENDPOINT = this.configService.get('MINIO_ENDPOINT');
MINIO_URL = this.configService.get('MINIO_URL'); MINIO_URL = this.configService.get('MINIO_URL');
...@@ -241,6 +244,15 @@ export class AppController { ...@@ -241,6 +244,15 @@ export class AppController {
return parser.toJson(xml.xml); return parser.toJson(xml.xml);
} }
// form list vinay start
@Get('formlist')
async formList(@Query('form-id') formId: string) {
return await this.appService.getFormList(formId);
}
// form list vinay end
@Get('osceForm/:type/:year/:speciality?') @Get('osceForm/:type/:year/:speciality?')
getOsceForm( getOsceForm(
@Param('type') type, @Param('type') type,
...@@ -275,7 +287,7 @@ export class AppController { ...@@ -275,7 +287,7 @@ export class AppController {
port: parseInt(this.configService.get('MINIO_PORT')), port: parseInt(this.configService.get('MINIO_PORT')),
useSSL: this.configService.get('MINIO_USE_SSL') === true, useSSL: this.configService.get('MINIO_USE_SSL') === true,
accessKey: this.configService.get('MINIO_USERNAME'), accessKey: this.configService.get('MINIO_USERNAME'),
secretKey: this.configService.get('MINIO_PASSWORD') secretKey: this.configService.get('MINIO_PASSWORD'),
}); });
const metaData: ItemBucketMetadata = { const metaData: ItemBucketMetadata = {
...@@ -290,7 +302,7 @@ export class AppController { ...@@ -290,7 +302,7 @@ export class AppController {
metaData, metaData,
function (err, res) { function (err, res) {
if (err) { if (err) {
console.log(err) console.log(err);
throw new HttpException( throw new HttpException(
'Error uploading file', 'Error uploading file',
HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST,
...@@ -299,7 +311,9 @@ export class AppController { ...@@ -299,7 +311,9 @@ export class AppController {
}, },
); );
const fileURL = `${this.MINIO_URL}/${this.configService.get('MINIO_BUCKETNAME')}/${fileName}`; const fileURL = `${this.MINIO_URL}/${this.configService.get(
'MINIO_BUCKETNAME',
)}/${fileName}`;
console.log('Uploaded File:', fileURL); console.log('Uploaded File:', fileURL);
......
import { ConsoleLogger, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { DOMParser } from 'xmldom'; import { DOMParser } from 'xmldom';
import * as fs from 'fs'; import * as fs from 'fs';
import { join } from 'path'; import { join } from 'path';
import Xform from './xform';
import libxmljs from 'libxmljs';
@Injectable() @Injectable()
export class AppService { export class AppService {
...@@ -308,4 +310,23 @@ export class AppService { ...@@ -308,4 +310,23 @@ export class AppService {
console.log('Update Done'); console.log('Update Done');
} }
} }
async getFormList(formId: string) {
const form = libxmljs.Document();
const formFilePath = join(__dirname, `forms/${formId}.xml`);
const xform = form.node('xforms');
xform.namespace('http://openrosa.org/xforms/xformsList');
let file = fs.readFileSync(formFilePath);
const id = formFilePath.substring(0, file.length - 4);
const formObject = await new Xform(id, formFilePath).getProperties(
formFilePath,
);
if (formObject) {
for (const property in formObject) {
xform.node(property, formObject[property]);
}
}
return [xform].toString();
}
} }
'use strict';
const fs = require('fs');
const path = require('path');
const url = require('url');
// const utils = require('../lib/utils');
const libxmljs = require('libxmljs');
// const debug = require( 'debug' )( 'Xform model' );
// TODO move
const FORMSTORAGEPATH = path.resolve(__dirname, '../../storage/forms');
class Xform {
static node(arg0: string) {
throw new Error('Method not implemented.');
}
data: any;
doc: any;
namespaces: {
xmlns: string;
h: string;
jr: string;
orx: string;
xsd: string;
ev: string;
};
constructor(private readonly id: string, private readonly path: string) {}
initialize() {
const xform = this;
return new Promise(function (resolve, reject) {
// mimicking future async db query
fs.readFile(xform.path, 'utf-8', (error: any, data: any) => {
if (error) {
reject(error);
} else {
xform.data = data;
//that.data = '<data>dfdsa';
try {
xform.doc = libxmljs.parseXml(xform.data);
xform.namespaces = xform._getNamespaces();
//debug( 'defaultNamespace', JSON.stringify( that.defaultNamespace[ 0 ] ) );
resolve(true);
} catch (e) {
const err = new Error(
'XML Error in form "' + xform.id + '": ' + JSON.stringify(e),
);
reject(err);
}
}
});
});
}
getProperties(baseUrl: any) {
const xform = this;
return this.initialize().then(() => {
const props = {
formID: xform._getFormId(),
name: xform._getName(),
majorMinorVersion: xform._getMajorMinorVersion(),
version: xform._getVersion(),
// hash: xform._getHash(),
downloadUrl: xform._getDownloadUrl(baseUrl),
};
return xform._getManifestUrl(baseUrl).then(function (manifestUrl: any) {
if (manifestUrl) {
props['manifestUrl'] = manifestUrl;
}
return props;
});
});
}
_getNamespaces() {
// TODO: extract these from this.doc instead
return {
xmlns: 'http://www.w3.org/2002/xforms',
h: 'http://www.w3.org/1999/xhtml',
jr: 'http://openrosa.org/javarosa',
orx: 'http://openrosa.org/xforms',
xsd: 'http://www.w3.org/2001/XMLSchema',
ev: 'http://www.w3.org/2001/xml-events',
};
}
_getFormId() {
let id = this.doc.get(
'//xmlns:model/xmlns:instance/node()[@id]',
this.namespaces,
);
if (!id) {
throw new Error('id attribute not found for form "' + this.id + '"');
}
// there has to be a better way to get this id and version...
id = id.attr('id').toString();
return id.substring(5, id.length - 1);
}
_getName() {
const title = this.doc.get('//h:head/h:title', this.namespaces);
if (!title) {
throw new Error('title element not found for form "' + this.id + '"');
}
return title.text();
}
_getMajorMinorVersion() {
return '';
}
_getVersion() {
let version = this.doc.get(
'//xmlns:model/xmlns:instance/node()[@version]',
this.namespaces,
);
if (!version) {
return '';
}
// there has to be a better way to get this version...
version = version.attr('version').toString();
return version.substring(10, version.length - 1);
}
// _getHash() {
// return 'md5:' + utils.md5(this.data);
// }
_getDescriptionText() {
return this._getName();
}
_getDescriptionUrl() {
return '';
}
_getDownloadUrl(baseUrl: any) {
return url.resolve(baseUrl, path.join('form', this.id, 'form.xml'));
}
_getManifestUrl(baseUrl: any) {
const xform = this;
return new Promise((resolve, reject) => {
fs.readdir(
path.join(FORMSTORAGEPATH, xform.id + '-media'),
(error: any, files: string | any[]) => {
if (error || files.length === 0) {
resolve(null);
} else {
resolve(
url.resolve(
baseUrl,
path.join('/form/', xform.id, '/manifest.xml'),
),
);
}
},
);
});
}
}
export default Xform;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment