Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
sosna committed Oct 29, 2017
2 parents ff63557 + a35cc9e commit 13ab971
Show file tree
Hide file tree
Showing 3 changed files with 310 additions and 13 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"node": ">=6"
},
"description": "The SDMX RESTful API for JavaScript",
"version": "1.0.0",
"version": "2.7.0",
"main": "./lib/index.js",
"scripts": {
"prebuild": "rm -rf lib && mkdir lib",
Expand Down Expand Up @@ -40,14 +40,14 @@
"coffee-coverage": "2.0.1",
"coffee-script": "1.12.7",
"coffeeify": "3.0.0",
"coffeelint": "2.0.6",
"coffeelint": "2.0.7",
"commitizen": "2.9.6",
"cz-conventional-changelog": "2.0.0",
"cz-conventional-changelog": "2.1.0",
"husky": "0.14.3",
"istanbul": "0.4.5",
"mocha": "4.0.1",
"nock": "9.0.22",
"semantic-release": "8.0.3"
"nock": "9.0.27",
"semantic-release": "8.2.0"
},
"config": {
"commitizen": {
Expand Down
80 changes: 72 additions & 8 deletions src/utils/url-generator.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
{DataQuery} = require '../data/data-query'
{MetadataQuery} = require '../metadata/metadata-query'
{isItemScheme} = require '../metadata/metadata-type'
{MetadataDetail} = require '../metadata/metadata-detail'
{MetadataReferences} = require '../metadata/metadata-references'

itemAllowed = (resource, api) ->
api isnt ApiVersion.v1_0_0 and
api isnt ApiVersion.v1_0_1 and
api isnt ApiVersion.v1_0_2 and
((resource isnt 'hierarchicalcodelist' and isItemScheme(resource)) or
(api isnt ApiVersion.v1_1_0 and resource is 'hierarchicalcodelist'))

itemNeeded = (item, resource, api) ->
item isnt 'all' and itemAllowed(resource, api)

createEntryPoint = (service) ->
throw ReferenceError "#{service.url} is not a valid service"\
Expand All @@ -27,27 +39,79 @@ createDataQuery = (query, service) ->
url = url + "&lastNObservations=#{query.lastNObs}" if query.lastNObs
url

createMetadataQuery = (query, service) ->
createShortDataQuery = (query, service) ->
url = createEntryPoint service
url = url + "#{query.resource}/#{query.agency}/#{query.id}/#{query.version}"
url = url + "data/#{query.flow}"
if query.key isnt 'all' or query.provider isnt 'all'
url = url + '/' + query.key
if query.provider isnt 'all'
url = url + '/' + query.provider
params = []
if query.obsDimension isnt 'TIME_PERIOD'
params.push "dimensionAtObservation=#{query.obsDimension}"
params.push "detail=#{query.detail}" if query.detail isnt 'full'
if (service.api isnt ApiVersion.v1_0_0 and
service.api isnt ApiVersion.v1_0_1 and
service.api isnt ApiVersion.v1_0_2 and
((query.resource isnt 'hierarchicalcodelist' and
isItemScheme(query.resource)) or (service.api isnt ApiVersion.v1_1_0 and
query.resource is 'hierarchicalcodelist')))
query.history)
params.push "includeHistory=#{query.history}"
params.push "startPeriod=#{query.start}" if query.start
params.push "endPeriod=#{query.end}" if query.end
params.push "updatedAfter=#{query.updatedAfter}" if query.updatedAfter
params.push "firstNObservations=#{query.firstNObs}" if query.firstNObs
params.push "lastNObservations=#{query.lastNObs}" if query.lastNObs
if params.length > 0
url = url + "?"
url = url + params.reduceRight (x, y) -> x + "&" + y
url

createMetadataQuery = (query, service) ->
url = createEntryPoint service
url = url + "#{query.resource}/#{query.agency}/#{query.id}/#{query.version}"
if itemAllowed(query.resource, service.api)
url = url + "/#{query.item}"
url = url + "?detail=#{query.detail}&references=#{query.references}"
url

createShortMetadataQuery = (q, s) ->
u = createEntryPoint s
u = u + "#{q.resource}"
if (q.agency isnt "all" or q.id isnt "all" or q.version isnt "latest" or
itemNeeded(q.item, q.resource, s.api))
u = u + "/#{q.agency}"
if q.id isnt "all" or q.version isnt "latest" or
itemNeeded(q.item, q.resource, s.api)
u = u + "/#{q.id}"
if q.version isnt "latest" or itemNeeded(q.item, q.resource, s.api)
u = u + "/#{q.version}"
if itemAllowed(q.resource, s.api) and q.item isnt "all"
u = u + "/#{q.item}"
if (q.detail isnt MetadataDetail.FULL or
q.references isnt MetadataReferences.NONE)
u = u + "?"
if q.detail isnt MetadataDetail.FULL
u = u + "detail=#{q.detail}"
if (q.detail isnt MetadataDetail.FULL and
q.references isnt MetadataReferences.NONE)
u = u + "&"
if q.references isnt MetadataReferences.NONE
u = u + "references=#{q.references}"
u

generator = class Generator

getUrl: (@query, service) ->
getUrl: (@query, service, skipDefaults) ->
@service = service ? ApiVersion.LATEST
if @query?.flow?
url = createDataQuery(@query, @service)
if skipDefaults
url = createShortDataQuery(@query, @service)
else
url = createDataQuery(@query, @service)
else if @query?.resource?
url = createMetadataQuery(@query, @service)
if skipDefaults
url = createShortMetadataQuery(@query, @service)
else
url = createMetadataQuery(@query, @service)
else
throw TypeError "#{@query} is not a valid SDMX data or metadata query"
url
Expand Down
233 changes: 233 additions & 0 deletions test/utils/url-generator.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,103 @@ describe 'URL Generator', ->
url = new UrlGenerator().getUrl(query, service)
url.should.equal expected

it 'offers to skip default values for metadata', ->
expected = "http://test.com/codelist"
query = MetadataQuery.from({
resource: 'codelist'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds them when needed (id)', ->
expected = "http://test.com/codelist/all/CL_FREQ"
query = MetadataQuery.from({
resource: 'codelist'
id: 'CL_FREQ'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds them when needed (version)', ->
expected = "http://test.com/codelist/all/all/42"
query = MetadataQuery.from({
resource: 'codelist'
version: '42'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds them when needed (item)', ->
expected = "http://test.com/codelist/all/all/latest/1"
query = MetadataQuery.from({
resource: 'codelist'
item: '1'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds them when needed (item, old API)', ->
expected = "http://test.com/codelist"
query = MetadataQuery.from({
resource: 'codelist'
item: '1'
})
service = Service.from({
url: 'http://test.com'
api: ApiVersion.v1_0_2
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (detail)', ->
expected = "http://test.com/codelist?detail=allstubs"
query = MetadataQuery.from({
resource: 'codelist'
detail: 'allstubs'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (references)', ->
expected = "http://test.com/codelist?references=datastructure"
query = MetadataQuery.from({
resource: 'codelist'
references: 'datastructure'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (detail & refs)', ->
expected = "http://test.com/codelist?detail=allstubs&references=datastructure"
query = MetadataQuery.from({
resource: 'codelist'
detail: 'allstubs'
references: 'datastructure'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

describe 'for data queries', ->

it 'generates a URL for a full data query', ->
Expand Down Expand Up @@ -201,6 +298,142 @@ describe 'URL Generator', ->
url = new UrlGenerator().getUrl(query, service)
url.should.equal expected

it 'offers to skip default values for data', ->
expected = "http://test.com/data/EXR"
query = DataQuery.from({
flow: 'EXR'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds them when needed (provider)', ->
expected = "http://test.com/data/EXR/all/ECB"
query = DataQuery.from({
flow: 'EXR'
provider: 'ECB'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (start)', ->
expected = "http://test.com/data/EXR?startPeriod=2010"
query = DataQuery.from({
flow: 'EXR'
start: '2010'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (end)', ->
expected = "http://test.com/data/EXR?endPeriod=2010"
query = DataQuery.from({
flow: 'EXR'
end: '2010'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (updatedAfter)', ->
expected = "http://test.com/data/EXR?updatedAfter=2016-03-01T00:00:00Z"
query = DataQuery.from({
flow: 'EXR'
updatedAfter: '2016-03-01T00:00:00Z'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (firstNObs)', ->
expected = "http://test.com/data/EXR?firstNObservations=1"
query = DataQuery.from({
flow: 'EXR'
firstNObs: 1
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (lastNObs)', ->
expected = "http://test.com/data/EXR?lastNObservations=2"
query = DataQuery.from({
flow: 'EXR'
lastNObs: 2
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (detail)', ->
expected = "http://test.com/data/EXR?detail=dataonly"
query = DataQuery.from({
flow: 'EXR'
detail: 'dataonly'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (history)', ->
expected = "http://test.com/data/EXR?includeHistory=true"
query = DataQuery.from({
flow: 'EXR'
history: true
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (obsDim)', ->
expected = "http://test.com/data/EXR?dimensionAtObservation=CURR"
query = DataQuery.from({
flow: 'EXR'
obsDimension: 'CURR'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'offers to skip defaults but adds params when needed (various)', ->
expected = "http://test.com/data/EXR/A..EUR.SP00.A?\
updatedAfter=2016-03-01T00:00:00Z\
&startPeriod=2010&dimensionAtObservation=CURRENCY"
query = DataQuery.from({
flow: 'EXR'
key: 'A..EUR.SP00.A'
obsDimension: 'CURRENCY'
start: '2010'
updatedAfter: '2016-03-01T00:00:00Z'
})
service = Service.from({
url: 'http://test.com'
})
url = new UrlGenerator().getUrl(query, service, true)
url.should.equal expected

it 'throws an exception if no query is supplied', ->
test = -> new UrlGenerator().getUrl()
should.Throw(test, Error, 'not a valid SDMX data or metadata query')
Expand Down

0 comments on commit 13ab971

Please sign in to comment.