Skip to content
This repository was archived by the owner on Feb 28, 2020. It is now read-only.

Commit

Permalink
Merge pull request #271 from IBM-Swift/updateTo2.7.0
Browse files Browse the repository at this point in the history
Release 2.7.0

### Features

* decouple swaggerize ([ead4636](ead4636))
* enable iOS sdk generation after invoking model generator ([#260](#260)) ([f27a770](f27a770))
  • Loading branch information
tunniclm authored Jul 27, 2017
2 parents 740b584 + d8cc918 commit c2738e7
Show file tree
Hide file tree
Showing 13 changed files with 514 additions and 99 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ branches:
- master
- develop
- "/^issue.*$/"
- /^greenkeeper/.*$/
node_js:
- '4'
- '6'
Expand Down
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="2.7.0"></a>
# [2.7.0](https://github.com/IBM-Swift/generator-swiftserver/compare/2.6.0...2.7.0) (2017-07-24)


### Features

* decouple swaggerize ([ead4636](https://github.com/IBM-Swift/generator-swiftserver/commit/ead4636))
* enable iOS sdk generation after invoking model generator ([#260](https://github.com/IBM-Swift/generator-swiftserver/issues/260)) ([f27a770](https://github.com/IBM-Swift/generator-swiftserver/commit/f27a770))



<a name="2.6.0"></a>
# [2.6.0](https://github.com/IBM-Swift/generator-swiftserver/compare/2.5.0...2.6.0) (2017-07-18)

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

# generator-swiftserver

[![Greenkeeper badge](https://badges.greenkeeper.io/IBM-Swift/generator-swiftserver.svg)](https://greenkeeper.io/)

This module is a [Yeoman](http://yeoman.io) generator for creating REST webservices based on the [Kitura web framework](http://kitura.io) with the [Swift](https://swift.org/) language.

This generator and the Yeoman library runs on Node.js and generates a Swift 3 application.
Expand Down
4 changes: 1 addition & 3 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ module.exports = Generator.extend({

promptSwiftServerSwaggerFiles: function () {
if (this.skipPrompting) return
this.log(chalk.magenta('Service prompts'))

var depth = 0
var prompts = [{
Expand Down Expand Up @@ -397,7 +398,6 @@ module.exports = Generator.extend({
if (this.skipPrompting) return
if (this.appType !== 'scaffold') return
if (this.bluemix) return
this.log(chalk.magenta('Service prompts'))

var choices = ['CouchDB', 'Redis']

Expand All @@ -422,7 +422,6 @@ module.exports = Generator.extend({
if (this.skipPrompting) return
if (this.appType !== 'scaffold') return
if (!this.bluemix) return
this.log(chalk.magenta('Service prompts'))

var choices = ['Cloudant', 'Redis', 'Object Storage', 'AppID', 'Auto-scaling', 'Watson Conversation', 'Alert Notification', 'Push Notifications']

Expand Down Expand Up @@ -495,7 +494,6 @@ module.exports = Generator.extend({
if (this.skipPrompting) return
if (this.appType !== 'crud') return
if (!this.bluemix) return
this.log(chalk.magenta('Service prompts'))

var choices = ['Auto-scaling']

Expand Down
39 changes: 39 additions & 0 deletions lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ var debug = require('debug')('generator-swiftserver:lib:helpers')
var format = require('util').format
var fs = require('fs')
var path = require('path')
var Promise = require('bluebird')
var request = require('request')
var requestAsync = Promise.promisify(request)
var YAML = require('js-yaml')
var chalk = require('chalk')

// Keywords which are reserved in Swift (taken from the Language Reference)
var RESERVED_DECLARATION_KEYWORDS = [
Expand Down Expand Up @@ -560,3 +565,37 @@ exports.getBluemixDefaultPlan = function (serviceType) {
default: return 'Lite'
}
}

function loadHttpAsync (uri) {
debug('in loadHttpAsync')

return requestAsync({ method: 'GET', uri: uri })
.then(result => {
if (result.statusCode !== 200) {
debug('get request returned status:', result.statusCode)
throw new Error(chalk.red('failed to load swagger from:', uri, 'status:', result.statusCode))
}
return result.body
})
}

function loadFileAsync (filePath, memfs) {
debug('in loadFileAsync')

return Promise.try(() => memfs.read(filePath))
.then(data => {
if (data === undefined) {
// when file exists but cannot read content.
debug('cannot read file contents', filePath)
throw new Error(chalk.red('failed to load swagger from:', filePath))
}
return data
})
}

exports.loadAsync = function (path, memfs) {
var isHttp = /^https?:\/\/\S+/.test(path)
var isYaml = (path.endsWith('.yaml') || path.endsWith('.yml'))
return (isHttp ? loadHttpAsync(path) : loadFileAsync(path, memfs))
.then(data => isYaml ? JSON.stringify(YAML.load(data)) : data)
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "generator-swiftserver",
"version": "2.6.0",
"version": "2.7.0",
"description": "Generator for Kitura REST webservice servers",
"main": "app/index.js",
"scripts": {
Expand Down Expand Up @@ -38,6 +38,8 @@
"devDependencies": {
"codecov": "^2.1.0",
"istanbul": "^0.4.5",
"mem-fs": "^1.1.3",
"mem-fs-editor": "^3.0.2",
"mocha": "^3.2.0",
"nock": "^9.0.13",
"nyc": "^10.1.2",
Expand Down
74 changes: 11 additions & 63 deletions refresh/fromswagger/swaggerize.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,61 +18,14 @@ var debug = require('debug')('generator-swiftserver:refresh:fromSwagger:swaggeri
var genUtils = require('./generatorUtils')
var SwaggerParser = require('swagger-parser')
var builderUtils = require('swaggerize-routes/lib/utils')
var YAML = require('js-yaml')
var chalk = require('chalk')
var Promise = require('bluebird')
var request = require('request')
var requestAsync = Promise.promisify(request)

function loadHttpAsync (uri) {
debug('in loadHttpAsync')

return requestAsync({ method: 'GET', uri: uri })
.catch(err => {
debug('get request returned err:', err)
throw new Error(chalk.red('failed to load swagger from:', uri, 'err:', err.message))
})
.then(result => {
if (result.statusCode !== 200) {
debug('get request returned status:', result.statusCode)
throw new Error(chalk.red('failed to load swagger from:', uri, 'status:', result.statusCode))
}
return result.body
})
}

function loadFileAsync (memfs, filePath) {
debug('in loadFileAsync')

return Promise.try(() => memfs.read(filePath))
.catch(err => {
// when file doesn't exist.
debug('file does not exist', filePath)
throw new Error(chalk.red('failed to load swagger from:', filePath, err.message))
})
.then(data => {
if (data === undefined) {
// when file exists but cannot read content.
debug('cannot read file contents', filePath)
throw new Error(chalk.red('failed to load swagger from:', filePath))
}
return data
})
}

function loadAsync (memfs, path) {
var isHttp = /^https?:\/\/\S+/.test(path)
var isYaml = (path.endsWith('.yaml') || path.endsWith('.yml'))
return (isHttp ? loadHttpAsync(path) : loadFileAsync(memfs, path))
.then(data => isYaml ? YAML.load(data) : JSON.parse(data))
}

function ensureValidAsync (api, apiPath) {
function ensureValidAsync (loadedSwagger) {
debug('in ensureValidAsync')
return SwaggerParser.validate(api)
return SwaggerParser.validate(loadedSwagger)
.catch(function (err) {
debug(err)
throw new Error(chalk.red(apiPath, 'does not conform to swagger specification'))
throw new Error(chalk.red('does not conform to swagger specification'))
})
}

Expand Down Expand Up @@ -182,19 +135,14 @@ function parseSwagger (api) {
return parsed
}

exports.parse = function (memfs, swaggerPath) {
exports.parse = function (swaggerStr) {
debug('in parse')
return loadAsync(memfs, swaggerPath)
.then(loaded => {
// take a copy of the swagger because the swagger-parser used by ensureValidAsync
// modifies the original loaded object.
var loadedAsJSONString = JSON.stringify(loaded)
return ensureValidAsync(loaded, swaggerPath)
.then(function () {
debug('successfully validated against schema')
// restore the original swagger.
var loaded = JSON.parse(loadedAsJSONString)
return { loaded: loaded, parsed: parseSwagger(loaded) }
})
var loaded = JSON.parse(swaggerStr)
return ensureValidAsync(loaded)
.then(function () {
debug('successfully validated against schema')
// restore the original swagger as the call to ensureValidAsync modifies the original loaded object.
loaded = JSON.parse(swaggerStr)
return { loaded: loaded, parsed: parseSwagger(loaded) }
})
}
81 changes: 54 additions & 27 deletions refresh/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,27 +666,34 @@ module.exports = Generator.extend({
parseFromSwagger: function () {
if (!this.fromSwagger) return

return swaggerize.parse(this.fs, this.fromSwagger)
return helpers.loadAsync(this.fromSwagger, this.fs)
.then(loaded => swaggerize.parse(loaded))
.then(response => {
this.loadedApi = response.loaded
this.parsedSwagger = response.parsed
})
.catch(err => {
err.message = chalk.red('failed to parse:' + this.fromSwagger + ' ' + err.message)
throw err
})
},

generateSDKs: function () {
var shouldGenerateClientWithModel = (!!this.swagger && JSON.stringify(this.swagger['paths']) !== '{}')
var shouldGenerateClient = (!!this.fromSwagger)
var shouldGenerateServer = (this.serverSwaggerFiles.length > 0)
if (!shouldGenerateClient && !shouldGenerateServer) return
if (!shouldGenerateClientWithModel && !shouldGenerateClient && !shouldGenerateServer) return

this.log(chalk.green('Generating SDK(s) from swagger file(s)...'))
var generationTasks = []
if (shouldGenerateClient) generationTasks.push(generateClientAsync.call(this))
if (shouldGenerateClientWithModel) generationTasks.push(generateClientAsync.call(this, this.swagger))
if (shouldGenerateClient) generationTasks.push(generateClientAsync.call(this, this.loadedApi))
if (shouldGenerateServer) generationTasks.push(generateServerAsync.call(this))
return Promise.all(generationTasks)

function generateClientAsync () {
function generateClientAsync (swaggerContent) {
var clientSDKName = `${this.projectName}_iOS_SDK`
return performSDKGenerationAsync(clientSDKName, 'ios_swift', JSON.stringify(this.loadedApi))
return performSDKGenerationAsync(clientSDKName, 'ios_swift', JSON.stringify(swaggerContent))
.then(generatedID => getClientSDKAsync(clientSDKName, generatedID))
.then(() => {
this.itemsToIgnore.push(`/${clientSDKName}*`)
Expand All @@ -695,32 +702,39 @@ module.exports = Generator.extend({

function generateServerAsync () {
return Promise.map(this.serverSwaggerFiles, file => {
return swaggerize.parse(this.fs, file)
.then(response => {
if (response.loaded.info.title === undefined) {
this.env.error(chalk.red('Could not extract title from Swagger API.'))
}

var serverSDKName = response.loaded.info.title.replace(/ /g, '_') + '_ServerSDK'
return performSDKGenerationAsync(serverSDKName, 'server_swift', JSON.stringify(response.loaded))
.then(generatedID => getServerSDKAsync(serverSDKName, generatedID))
.then(sdk => {
this.sdkTargets.push(serverSDKName)
if (sdk.packages.length > 0) {
// Since all of the projects generated by the SDK generation
// service will have the same pacakge dependencies, it is ok
// (for now) to overwrite with the latest set.
this.sdkPackages = sdk.packages
return helpers.loadAsync(file, this.fs)
.then(loaded => {
return swaggerize.parse(loaded)
.then(response => {
if (response.loaded.info.title === undefined) {
this.env.error(chalk.red('Could not extract title from Swagger API.'))
}
// Copy SDK's Sources directory into the project's
// Sources directory
this.fs.copy(path.join(sdk.tempDir, sdk.dirname, 'Sources'),
this.destinationPath('Sources', serverSDKName))

// Clean up the SDK's temp directory
rimraf.sync(sdk.tempDir)
var serverSDKName = response.loaded.info.title.replace(/ /g, '_') + '_ServerSDK'
return performSDKGenerationAsync(serverSDKName, 'server_swift', JSON.stringify(response.loaded))
.then(generatedID => getServerSDKAsync(serverSDKName, generatedID))
.then(sdk => {
this.sdkTargets.push(serverSDKName)
if (sdk.packages.length > 0) {
// Since all of the projects generated by the SDK generation
// service will have the same pacakge dependencies, it is ok
// (for now) to overwrite with the latest set.
this.sdkPackages = sdk.packages
}
// Copy SDK's Sources directory into the project's
// Sources directory
this.fs.copy(path.join(sdk.tempDir, sdk.dirname, 'Sources'),
this.destinationPath('Sources', serverSDKName))

// Clean up the SDK's temp directory
rimraf.sync(sdk.tempDir)
})
})
})
.catch(err => {
err.message = chalk.red(this.fromSwagger + ' ' + err.message)
throw err
})
})
}
},
Expand Down Expand Up @@ -891,6 +905,7 @@ module.exports = Generator.extend({
)
})

// make the swagger available for the swaggerUI
var swaggerFilename = this.destinationPath('definitions', `${this.projectName}.yaml`)
this.fs.write(swaggerFilename, YAML.safeDump(this.loadedApi))
}
Expand Down Expand Up @@ -1041,6 +1056,18 @@ module.exports = Generator.extend({
var swaggerFilename = this.destinationPath('definitions', `${this.projectName}.yaml`)
this.conflicter.force = true
this.fs.write(swaggerFilename, YAML.safeDump(this.swagger))

// Append items to .gitignore that may have been added through model gen process
var gitignoreFile = this.fs.read(this.destinationPath('.gitignore'))
for (var item in this.itemsToIgnore) {
// Ensure we only add unique values
if (gitignoreFile.indexOf(this.itemsToIgnore[item]) === -1) {
this.fs.append(
this.destinationPath('.gitignore'),
this.itemsToIgnore[item]
)
}
}
}
},

Expand Down
2 changes: 1 addition & 1 deletion release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if [[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_PULL_REQUEST == "false" ]]; th
echo "Creating release ${VERSION}"
git tag $VERSION && git push origin $VERSION || true
# Merge back into develop and push those changes
git fetch origin && git checkout develop && git merge --ff-only origin/master && git push origin develop
git fetch origin && git checkout develop && git merge origin/master && git push origin develop
# npm publish

# Deleting the old release branch
Expand Down
12 changes: 12 additions & 0 deletions test/integration/model/prompted_nobuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ describe('Prompt and no build integration tests for model generator', function (
})

describe('Create a new model, creating a new model json file and update the spec.json', function () {
this.timeout(300000)
var runContext

before(function () {
Expand Down Expand Up @@ -143,5 +144,16 @@ describe('Prompt and no build integration tests for model generator', function (
}
assert.jsonFileContent('spec.json', expected)
})

it('created a iOS SDK zip file', function () {
assert.file('test_iOS_SDK.zip')
})

it('added reference to generated iOS SDK to .gitignore', function () {
// ensure reference is present and that there is only one reference to iOS SDK
var fileContent = fs.readFileSync('.gitignore').toString('utf-8')
var occurrences = (fileContent.match(/\/test_iOS_SDK\*/g) || []).length
assert.equal(occurrences, 1)
})
})
})
Loading

0 comments on commit c2738e7

Please sign in to comment.