Skip to content

Commit

Permalink
chore: rewrite precession of assets-discovery and small RegistryUI ch…
Browse files Browse the repository at this point in the history
…anges
  • Loading branch information
nightnei committed Sep 6, 2021
1 parent 6678781 commit 1271727
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 60 deletions.
4 changes: 2 additions & 2 deletions ilc/client/ilcConfig.js
Expand Up @@ -12,12 +12,12 @@ export default function () {

registryConf = JSON.parse(confScript.innerHTML);

document.head.appendChild(getSystemjsImportmap(registryConf));
document.head.appendChild(getSystemjsImportmap(registryConf.apps, registryConf.sharedLibs));

return registryConf;
};

function getSystemjsImportmap({ apps, sharedLibs }) {
function getSystemjsImportmap(apps, sharedLibs) {
const deps = {};

/**
Expand Down
22 changes: 19 additions & 3 deletions registry/client/src/sharedLibs/Edit.js
Expand Up @@ -6,8 +6,9 @@ import {
TabbedForm,
TextInput,
FormDataConsumer,
TextField,
FunctionField,
} from 'react-admin'; // eslint-disable-line import/no-unresolved
import { Typography } from '@material-ui/core';

import * as validators from '../validators';
import Title from './Title';
Expand Down Expand Up @@ -42,13 +43,28 @@ const validateSharedLib = (values) => {
return errors;
};

const styles = {
row: {
display: 'flex',
width: '100%',
alignItems: 'center',
},
};

const InputForm = ({mode = 'edit', ...props}) => {
return (
<TabbedForm {...props}>
<FormTab label="Summary">
{mode === 'edit'
? <TextField source="name" />
: <TextInput source="name" fullWidth />}
? <FunctionField
label="Name"
render={record => `@sharedLibrary/${record.name}`}
/>
: <div style={styles.row}>
<Typography variant="body1">@sharedLibrary/</Typography>
<TextInput source="name" fullWidth />
</div>
}
<TextInput
fullWidth
multiline
Expand Down
8 changes: 6 additions & 2 deletions registry/client/src/sharedLibs/List.js
Expand Up @@ -6,6 +6,7 @@ import {
SimpleList,
TextField,
EditButton,
FunctionField,
} from 'react-admin'; // eslint-disable-line import/no-unresolved
import {
Empty,
Expand All @@ -29,12 +30,15 @@ const PostList = props => {
>
{isSmall ? (
<SimpleList
primaryText={record => record.name}
primaryText={record => `@sharedLibrary/${record.name}`}
secondaryText={record => record.spaBundle}
/>
) : (
<Datagrid rowClick="show" optimized>
<TextField source="name" />
<FunctionField
label="Name"
render={record => `@sharedLibrary/${record.name}`}
/>
<TextField source="spaBundle" />
<ListActionsToolbar>
<EditButton />
Expand Down
6 changes: 5 additions & 1 deletion registry/client/src/sharedLibs/Show.js
Expand Up @@ -5,6 +5,7 @@ import {
TabbedShowLayout,
TextField,
UrlField,
FunctionField,
} from 'react-admin'; // eslint-disable-line import/no-unresolved

import Title from './Title';
Expand All @@ -16,7 +17,10 @@ export default ({ permissions, hasList, hasEdit, hasShow, hasCreate, ...props })
<Show {...props} title={<Title />} actions={<ShowTopToolbar />}>
<TabbedShowLayout {...props} toolbar={null}>
<Tab label="Summary">
<TextField source="name" />
<FunctionField
label="Name"
render={record => `@sharedLibrary/${record.name}`}
/>
<TextField source="adminNotes" component="pre" emptyText={EMPTY_TEXT} />
</Tab>
<Tab label="Assets">
Expand Down
9 changes: 8 additions & 1 deletion registry/server/apps/routes/createApp.ts
Expand Up @@ -22,6 +22,13 @@ const validateRequestBeforeCreateApp = validateRequestFactory([{
const createApp = async (req: Request, res: Response): Promise<void> => {
const app = req.body;

try {
await setDataFromManifest(app, 'apps');
} catch (error) {
res.status(422).send(error.message);
return;
}

await db.versioning(req.user, {type: 'apps', id: app.name}, async (trx) => {
await db('apps')
.insert(stringifyJSON(['dependencies', 'props', 'ssrProps', 'ssr', 'configSelector', 'discoveryMetadata'], app))
Expand All @@ -33,4 +40,4 @@ const createApp = async (req: Request, res: Response): Promise<void> => {
res.status(200).send(preProcessResponse(savedApp));
};

export default [validateRequestBeforeCreateApp, setDataFromManifest, createApp];
export default [validateRequestBeforeCreateApp, createApp];
9 changes: 8 additions & 1 deletion registry/server/apps/routes/updateApp.ts
Expand Up @@ -37,6 +37,13 @@ const updateApp = async (req: Request<UpdateAppRequestParams>, res: Response): P
const app = req.body;
const appName = req.params.name;

try {
await setDataFromManifest(app, 'apps');
} catch (error) {
res.status(422).send(error.message);
return;
}

const countToUpdate = await db('apps').where({ name: appName })
if (!countToUpdate.length) {
res.status(404).send('Not found');
Expand All @@ -55,4 +62,4 @@ const updateApp = async (req: Request<UpdateAppRequestParams>, res: Response): P
res.status(200).send(preProcessResponse(updatedApp));
};

export default [validateRequestBeforeUpdateApp, setDataFromManifest, updateApp];
export default [validateRequestBeforeUpdateApp, updateApp];
15 changes: 5 additions & 10 deletions registry/server/common/middlewares/setDataFromManifest.ts
Expand Up @@ -9,10 +9,9 @@ import {
parseJSON,
} from '../services/json';
import processManifest from '../services/assetsManifestProcessor';
import AssetsDiscoveryWhiteLists from '../services/AssetsDiscoveryWhiteLists';

const setDataFromManifest = async (req: Request, res: Response, next: NextFunction) => {
const entity = req.body;

const setDataFromManifest = async (entity: Record<string, any>, entityName: string) => {
if (entity.assetsDiscoveryUrl) {
let response;

Expand All @@ -22,21 +21,19 @@ const setDataFromManifest = async (req: Request, res: Response, next: NextFuncti
});
} catch (error) {
console.error(`Caught an error while trying to fetch a manifest file from '${entity.assetsDiscoveryUrl}':`, error);
res.status(422).send('"assetsDiscoveryUrl" is not available. Check the url via browser manually.');
return;
throw new Error('"assetsDiscoveryUrl" is not available. Check the url via browser manually.');
}

const {
spaBundle,
cssBundle,
dependencies,
} = processManifest(entity.assetsDiscoveryUrl, response.data);
} = processManifest(entity.assetsDiscoveryUrl, response.data, AssetsDiscoveryWhiteLists[entityName]);

if (spaBundle) {
entity.spaBundle = spaBundle;
} else {
res.status(422).send('"spaBundle" must be specified in the manifest file from provided "assetsDiscoveryUrl" if it was not specified manually');
return;
throw new Error('"spaBundle" must be specified in the manifest file from provided "assetsDiscoveryUrl" if it was not specified manually');
}

if (cssBundle) {
Expand All @@ -47,8 +44,6 @@ const setDataFromManifest = async (req: Request, res: Response, next: NextFuncti
entity.dependencies = parseJSON(dependencies);
}
}

next();
};

export default setDataFromManifest;
7 changes: 2 additions & 5 deletions registry/server/common/services/AssetsDiscovery.ts
Expand Up @@ -4,6 +4,7 @@ import urljoin from 'url-join';

import knex from '../../db';
import manifestProcessor from './assetsManifestProcessor';
import AssetsDiscoveryWhiteLists from './AssetsDiscoveryWhiteLists';

export default class AssetsDiscovery {
private tableName: string;
Expand Down Expand Up @@ -58,11 +59,7 @@ export default class AssetsDiscovery {
continue;
}

let data = manifestProcessor(reqUrl, res.data);
if (this.tableName === 'shared_libs') {
// "dependencies" comes from assets-discovery.json, but we don't have column dependencies at the current moment
delete data.dependencies;
}
let data = manifestProcessor(reqUrl, res.data, AssetsDiscoveryWhiteLists[this.tableName]);

await knex(this.tableName).where(this.tableId, entity[this.tableId]).update(Object.assign({}, data, {
assetsDiscoveryUpdatedAt: now,
Expand Down
6 changes: 6 additions & 0 deletions registry/server/common/services/AssetsDiscoveryWhiteLists.ts
@@ -0,0 +1,6 @@
const AssetsDiscoveryWhiteLists: Record<string, string[]> = {
shared_libs: ['spaBundle'],
apps: ['spaBundle', 'cssBundle', 'dependencies'],
};

export default AssetsDiscoveryWhiteLists;
5 changes: 2 additions & 3 deletions registry/server/common/services/assetsManifestProcessor.ts
@@ -1,9 +1,8 @@
import _ from 'lodash';
import url from 'url';


export default function processManifest(baseUrl: string, manifest: any) {
let data = _.pick(manifest, ['spaBundle', 'cssBundle', 'dependencies']);
export default function processManifest(baseUrl: string, manifest: any, whiteList: string[]) {
const data = _.pick(manifest, whiteList);

if (data.spaBundle) {
data.spaBundle = url.resolve(baseUrl, data.spaBundle);
Expand Down
10 changes: 7 additions & 3 deletions registry/server/sharedLibs/routes/createSharedLib.ts
Expand Up @@ -19,8 +19,12 @@ const validateRequestBeforeCreateSharedLib = validateRequestFactory([{
const createSharedLib = async (req: Request, res: Response): Promise<void> => {
const sharedLib = req.body;

// "dependencies" comes from assets-discovery.json, but we don't have column dependencies at the current moment
delete sharedLib.dependencies;
try {
await setDataFromManifest(sharedLib, 'shared_libs');
} catch (error) {
res.status(422).send(error.message);
return;
}

await db.versioning(req.user, { type: 'shared_libs', id: sharedLib.name }, async (trx) => {
await db('shared_libs').insert(sharedLib).transacting(trx);
Expand All @@ -31,4 +35,4 @@ const createSharedLib = async (req: Request, res: Response): Promise<void> => {
res.status(200).send(preProcessResponse(savedSharedLib));
};

export default [validateRequestBeforeCreateSharedLib, setDataFromManifest, createSharedLib];
export default [validateRequestBeforeCreateSharedLib, createSharedLib];
10 changes: 7 additions & 3 deletions registry/server/sharedLibs/routes/updateSharedLib.ts
Expand Up @@ -34,8 +34,12 @@ const updateSharedLib = async (req: Request<UpdateSharedLibRequestParams>, res:
const sharedLib = req.body;
const sharedLibName = req.params.name;

// "dependencies" comes from assets-discovery.json, but we don't have column dependencies at the current moment
delete sharedLib.dependencies;
try {
await setDataFromManifest(sharedLib, 'shared_libs');
} catch (error) {
res.status(422).send(error.message);
return;
}

const countToUpdate = await db('shared_libs').where({ name: sharedLibName })
if (!countToUpdate.length) {
Expand All @@ -52,4 +56,4 @@ const updateSharedLib = async (req: Request<UpdateSharedLibRequestParams>, res:
res.status(200).send(preProcessResponse(updatedSharedLib));
};

export default [validateRequestBeforeUpdateSharedLib, setDataFromManifest, updateSharedLib];
export default [validateRequestBeforeUpdateSharedLib, updateSharedLib];
61 changes: 35 additions & 26 deletions registry/tests/assetsManifestProcessor.spec.ts
Expand Up @@ -3,7 +3,7 @@ import { expect } from './common';
import processor from '../server/common/services/assetsManifestProcessor'

describe('assetsManifestProcessor', () => {
it('perform basic link resolution & cleanup of extra props', () => {
it('perform basic link resolution & cleanup non white listed properties', () => {
expect(processor('https://example.com/folder/assets-discovery.js', {
a: 'tst',
spaBundle: 'https://example.com/aa.js',
Expand All @@ -12,48 +12,57 @@ describe('assetsManifestProcessor', () => {
a1: 'https://example.com/aa.js',
a2: './tst/aa.js',
}
})).to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
dependencies: JSON.stringify({
a1: 'https://example.com/aa.js',
a2: 'https://example.com/folder/tst/aa.js',
})
});
},
['spaBundle', 'cssBundle', 'dependencies']))
.to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
dependencies: JSON.stringify({
a1: 'https://example.com/aa.js',
a2: 'https://example.com/folder/tst/aa.js',
})
});
});

it('handles absence of dependencies object or invalid type correctly', () => {
it('handles absence of dependencies object or invalid type correctly', () => {
expect(processor('https://example.com/folder/assets-discovery.js', {
spaBundle: 'https://example.com/aa.js',
cssBundle: './tst/aa.js',
})).to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
});
},
['spaBundle', 'cssBundle', 'dependencies']))
.to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
});

expect(processor('https://example.com/folder/assets-discovery.js', {
spaBundle: 'https://example.com/aa.js',
cssBundle: './tst/aa.js',
dependencies: ['aaa']
})).to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
});
},
['spaBundle', 'cssBundle', 'dependencies']))
.to.eql({
spaBundle: 'https://example.com/aa.js',
cssBundle: 'https://example.com/folder/tst/aa.js',
});
});

it('handles absence of cssBundle correctly', () => {
it('handles absence of cssBundle correctly', () => {
expect(processor('https://example.com/folder/assets-discovery.js', {
spaBundle: 'https://example.com/aa.js',
})).to.eql({
spaBundle: 'https://example.com/aa.js',
});
},
['spaBundle', 'cssBundle', 'dependencies']))
.to.eql({
spaBundle: 'https://example.com/aa.js',
});
});

it('handles absence of spaBundle correctly', () => {
it('handles absence of spaBundle correctly', () => {
expect(processor('https://example.com/folder/assets-discovery.js', {
cssBundle: 'https://example.com/aa.css',
})).to.eql({
cssBundle: 'https://example.com/aa.css',
});
}, ['spaBundle', 'cssBundle', 'dependencies']))
.to.eql({
cssBundle: 'https://example.com/aa.css',
});
});
});

0 comments on commit 1271727

Please sign in to comment.