Skip to content

Commit 4aef6c3

Browse files
committed
update to dcat US 3.0
1 parent 69ea737 commit 4aef6c3

7 files changed

+83
-53
lines changed

src/dcat-us/compile-dcat-feed.test.ts

+6-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { compileDcatFeedEntry } from './compile-dcat-feed';
22
import * as datasetFromApi from '../test-helpers/mock-dataset.json';
33
import { DcatUsError } from './dcat-us-error';
44

5-
describe('generating DCAT-US 1.1 feed', () => {
5+
describe('generating DCAT-US 3.0 feed', () => {
66
it('should throw 400 DcatUs error if template contains transformer that is not defined', async function () {
77
const dcatTemplate = {
88
title: '{{name}}',
@@ -24,41 +24,27 @@ describe('generating DCAT-US 1.1 feed', () => {
2424
title: '{{name}}',
2525
description: '{{description}}',
2626
keyword: '{{tags}}',
27-
distribution: [
27+
'dcat:distribution': [
2828
'distro1',
2929
'distro2',
3030
['distro3', 'distro4']
3131
]
3232
}
3333

3434
const dcatDataset = JSON.parse(compileDcatFeedEntry(datasetFromApi, dcatTemplate, {}));
35-
expect(dcatDataset.distribution).toBeDefined();
36-
expect(dcatDataset.distribution).toStrictEqual(['distro1', 'distro2', 'distro3', 'distro4']);
35+
expect(dcatDataset['dcat:distribution']).toBeDefined();
36+
expect(dcatDataset['dcat:distribution']).toStrictEqual(['distro1', 'distro2', 'distro3', 'distro4']);
3737
});
3838

3939
it('show not return uninterpolated distribution in dataset', async function () {
4040
const dcatTemplate = {
4141
title: '{{name}}',
4242
description: '{{description}}',
4343
keyword: '{{tags}}',
44-
distribution: ['distro1', '{{distroname}}']
44+
'dcat:distribution': ['distro1', '{{distroname}}']
4545
}
4646
const dcatDataset = JSON.parse(compileDcatFeedEntry(datasetFromApi, dcatTemplate, {}));
47-
expect(dcatDataset.distribution).toStrictEqual(['distro1']);
48-
});
49-
50-
it('should contain default theme if spatial key exists in dataset', async function () {
51-
const distribution = ['distro1', '{{distroname}}'];
52-
const dcatTemplate = {
53-
title: '{{name}}',
54-
description: '{{description}}',
55-
keyword: '{{tags}}',
56-
distribution,
57-
spatial: '{{extent}}'
58-
}
59-
const dcatDataset = JSON.parse(compileDcatFeedEntry(datasetFromApi, dcatTemplate, {}));
60-
expect(dcatDataset.theme).toBeDefined();
61-
expect(dcatDataset.theme).toStrictEqual(['geospatial']);
47+
expect(dcatDataset['dcat:distribution']).toStrictEqual(['distro1']);
6248
});
6349

6450
it('should throw error if geojson from provider is missing', async function () {

src/dcat-us/compile-dcat-feed.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ export function compileDcatFeedEntry(geojsonFeature: Feature | undefined, feedTe
1414
const dcatFeedItem = generateDcatItem(feedTemplate, feedTemplateTransforms, geojsonFeature);
1515
return indent(JSON.stringify({
1616
...dcatFeedItem,
17-
distribution: Array.isArray(dcatFeedItem.distribution) && removeUninterpolatedDistributions(_.flatten(dcatFeedItem.distribution)),
18-
theme: dcatFeedItem.spatial && ['geospatial']
17+
'dcat:distribution':
18+
Array.isArray(dcatFeedItem['dcat:distribution']) &&
19+
removeUninterpolatedDistributions(_.flatten(dcatFeedItem['dcat:distribution'])),
1920
}, null, '\t'), 2);
2021
} catch (err) {
2122
throw new DcatUsError(err.message, 400);

src/dcat-us/constants/contexts.ts

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
export const HEADER_V3 = {
2+
'@context': {
3+
'@version': 1.1,
4+
'@protected': true,
5+
'adms': 'http://www.w3.org/ns/adms#',
6+
'cnt': 'http://www.w3.org/2011/content#',
7+
'dash': 'http://datashapes.org/dash#',
8+
'dcat': 'http://www.w3.org/ns/dcat#',
9+
'dcatap': 'http://data.europa.eu/r5r/',
10+
'dcat-us': 'http://data.resources.gov/ontology/dcat-us#',
11+
'dcat-us-shp': 'http://data.resources.gov/shapes/dcat-us#',
12+
'dcterms': 'http://purl.org/dc/terms/',
13+
'dqv': 'http://www.w3.org/ns/dqv#',
14+
'foaf': 'http://xmlns.com/foaf/0.1/',
15+
'gsp': 'http://www.opengis.net/ont/geosparql#',
16+
'locn': 'http://www.w3.org/ns/locn#',
17+
'odrs': 'http://schema.theodi.org/odrs#',
18+
'org': 'http://www.w3c.org/ns/org#',
19+
'owl': 'http://www.w3.org/2002/07/owl#',
20+
'prov': 'http://www.w3.org/ns/prov#',
21+
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
22+
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
23+
'schema': 'http://schema.org/',
24+
'sh': 'http://www.w3.org/ns/shacl#',
25+
'skos': 'http://www.w3.org/2004/02/skos/core#',
26+
'sdmx-attribute': 'http://purl.org/linked-data/sdmx/2009/attribute#',
27+
'spdx': 'http://spdx.org/rdf/terms#',
28+
'vcard': 'http://www.w3.org/2006/vcard/ns#',
29+
"xsd": "http://www.w3.org/2001/XMLSchema#",
30+
'adms:Identifier': {
31+
'@id': 'adms:Identifier',
32+
'@context': {
33+
'schemaAgency': 'http://www.w3.org/ns/adms#schemaAgency',
34+
'creator': {
35+
'@id': 'dcterms:creator',
36+
'@type': '@id'
37+
},
38+
'issued': {
39+
'@id': 'dcterms:issued'
40+
},
41+
'version': 'http://purl.org/dc/terms/version',
42+
'notation': 'http://www.w3.org/2004/02/skos/core#notation'
43+
}
44+
},
45+
},
46+
'@type': 'dcat:Catalog',
47+
conformsTo: 'https://resource.data.gov/profile/dcat-us#',
48+
};

src/dcat-us/index.test.ts

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { readableFromArray, streamToString } from '../test-helpers/stream-utils';
22
import { getDataStreamDcatUs11 } from './';
33
import * as datasetFromApi from '../test-helpers/mock-dataset.json';
4+
import { HEADER_V3 } from './constants/contexts';
45

56
async function generateDcatFeed(dataset, template, templateTransforms) {
67
const { stream: dcatStream } = getDataStreamDcatUs11(template, templateTransforms);
@@ -10,15 +11,14 @@ async function generateDcatFeed(dataset, template, templateTransforms) {
1011
return { feed: JSON.parse(feedString) };
1112
}
1213

13-
describe('generating DCAT-US 1.1 feed', () => {
14+
describe('generating DCAT-US 3.0 feed', () => {
1415
it('formats catalog correctly', async function () {
1516
const { feed } = await generateDcatFeed([], {}, {});
1617

17-
expect(feed['@context']).toBe('https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld');
18+
expect(feed['@context']).toStrictEqual(HEADER_V3['@context']);
19+
expect(feed['conformsTo']).toBe('https://resource.data.gov/profile/dcat-us#');
1820
expect(feed['@type']).toBe('dcat:Catalog');
19-
expect(feed['conformsTo']).toBe('https://project-open-data.cio.gov/v1.1/schema');
20-
expect(feed['describedBy']).toBe('https://project-open-data.cio.gov/v1.1/schema/catalog.json');
21-
expect(Array.isArray(feed['dataset'])).toBeTruthy();
21+
expect(Array.isArray(feed['dcat:dataset'])).toBeTruthy();
2222
});
2323

2424
it('should interprolate dataset stream to feed based upon template', async function () {
@@ -35,20 +35,23 @@ describe('generating DCAT-US 1.1 feed', () => {
3535
'@type': 'vcard:Contact',
3636
fn: '{{owner}}',
3737
hasEmail: '{{orgContactEmail:optional}}'
38+
},
39+
header: {
40+
'@id': 'hub.arcgis.com'
3841
}
3942
}, {
4043
toISO: (_key, val) => {
4144
return new Date(val).toISOString();
4245
}
4346
});
4447

45-
expect(feed['@context']).toBe('https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld');
48+
expect(feed['@context']).toStrictEqual(HEADER_V3['@context']);
4649
expect(feed['@type']).toBe('dcat:Catalog');
47-
expect(feed['conformsTo']).toBe('https://project-open-data.cio.gov/v1.1/schema');
48-
expect(feed['describedBy']).toBe('https://project-open-data.cio.gov/v1.1/schema/catalog.json');
49-
expect(Array.isArray(feed['dataset'])).toBeTruthy();
50-
expect(feed['dataset'].length).toBe(1);
51-
const feedResponse = feed['dataset'][0];
50+
expect(feed['@id']).toBe('hub.arcgis.com');
51+
expect(feed['conformsTo']).toBe('https://resource.data.gov/profile/dcat-us#');
52+
expect(Array.isArray(feed['dcat:dataset'])).toBeTruthy();
53+
expect(feed['dcat:dataset'].length).toBe(1);
54+
const feedResponse = feed['dcat:dataset'][0];
5255
expect(feedResponse.title).toBe('Tahoe places of interest');
5356
expect(feedResponse.description).toBe('Description. Here be Tahoe things. You can do a lot here. Here are some more words. And a few more.<div><br /></div><div>with more words</div><div><br /></div><div>adding a few more to test how long it takes for our jobs to execute.</div><div><br /></div><div>Tom was here!</div>');
5457
expect(feedResponse.issued).toBe('2021-01-29T15:34:38.000Z');

src/dcat-us/index.ts

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
11
import { compileDcatFeedEntry } from './compile-dcat-feed';
22
import { FeedFormatterStream } from './feed-formatter-stream';
33
import { TransformsList } from 'adlib';
4+
import { HEADER_V3 } from './constants/contexts';
45

56
export function getDataStreamDcatUs11(feedTemplate: any, feedTemplateTransforms: TransformsList) {
6-
const catalogStr = JSON.stringify({
7-
'@context':
8-
'https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld',
9-
'@type': 'dcat:Catalog',
10-
conformsTo: 'https://project-open-data.cio.gov/v1.1/schema',
11-
describedBy: 'https://project-open-data.cio.gov/v1.1/schema/catalog.json',
12-
}, null, '\t');
13-
14-
const header = `${catalogStr.substr(
15-
0,
16-
catalogStr.length - 2,
17-
)},\n\t"dataset": [\n`;
18-
197
const footer = '\n\t]\n}';
8+
const { header: templateHeader, ...restFeedTemplate } = feedTemplate;
9+
10+
const catalogStr = JSON.stringify({ ...HEADER_V3, ...templateHeader }, null, '\t');
11+
const header = `${catalogStr.substring(0, catalogStr.length - 2)},\n\t"dcat:dataset": [\n`;
2012

2113
const formatFn = (chunk) => {
22-
return compileDcatFeedEntry(chunk, feedTemplate, feedTemplateTransforms);
14+
return compileDcatFeedEntry(chunk, restFeedTemplate, feedTemplateTransforms);
2315
};
2416

2517
return {
2618
stream: new FeedFormatterStream(header, footer, ',\n', formatFn)
2719
};
28-
}
20+
}

src/index.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('Output Plugin', () => {
6060
title: '{{name}}',
6161
description: '{{description}}',
6262
keyword: '{{tags}}',
63-
issued: '{{created}}'
63+
issued: '{{created}}',
6464
}
6565

6666
mockConfigModule = mocked(require('config'), true);
@@ -82,7 +82,7 @@ describe('Output Plugin', () => {
8282
expect(plugin.constructor.version).toBeDefined();
8383
expect(plugin.constructor.routes).toEqual([
8484
{
85-
path: '/dcat-us/1.1',
85+
path: '/dcat-us/3.0',
8686
methods: ['get'],
8787
handler: 'serve',
8888
},
@@ -124,8 +124,8 @@ describe('Output Plugin', () => {
124124
const dcatStream = res.body;
125125
expect(dcatStream['@context']).toBeDefined();
126126
expect(dcatStream['@type']).toBe('dcat:Catalog');
127-
expect(dcatStream['dataset']).toBeInstanceOf(Array);
128-
expect(dcatStream['dataset'].length).toBe(1);
127+
expect(dcatStream['dcat:dataset']).toBeInstanceOf(Array);
128+
expect(dcatStream['dcat:dataset'].length).toBe(1);
129129
});
130130
});
131131

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export = class OutputDcatUs11 {
1010
static version = version;
1111
static routes = [
1212
{
13-
path: '/dcat-us/1.1',
13+
path: '/dcat-us/3.0',
1414
methods: ['get'],
1515
handler: 'serve',
1616
},

0 commit comments

Comments
 (0)