Skip to content

Commit

Permalink
feat: support string or numeric JSON format for numeric IDs in Swift (#…
Browse files Browse the repository at this point in the history
…937)

Updated the Swift SDK generator to use the new `AnyInt` wrapper for numeric id properties. This means

- number/string JSON type -> string works
- number/string JSON type -> number works

Added tests to verify expected behavior and the new generator support
  • Loading branch information
jkaster authored Jan 13, 2022
1 parent 1b13712 commit 1487d8a
Show file tree
Hide file tree
Showing 11 changed files with 1,741 additions and 476 deletions.
2 changes: 1 addition & 1 deletion packages/sdk-codegen/src/sdkModels.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ describe('sdkModels', () => {
const actual = apiTestModel.search('beta', statusCriteria)
expect(Object.entries(allMethods(actual.tags))).toHaveLength(238)
const types = Object.entries(actual.types)
expect(types).toHaveLength(128)
expect(types).toHaveLength(129)
})

it('stable items', () => {
Expand Down
40 changes: 40 additions & 0 deletions packages/sdk-codegen/src/swift.gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,46 @@ public enum PermissionType: String, Codable {
self.init(name: name, parent_id: parent_id)
}
}`
expect(actual).toEqual(expected)
})

it('numeric ID properties use map to AnyInt', () => {
const type = apiTestModel.types.AnyIntIds
const actual = gen.declareType(indent, type)
const expected = `public struct AnyIntIds: SDKModel {
private enum CodingKeys : String, CodingKey {
case _id = "id"
case _user_id = "user_id"
}
private var _id: AnyInt
/**
* The unique id of this item (read-only)
*/
public var id: Int {
get { _id.value }
set { _id = AnyInt.init(newValue) }
}
private var _user_id: AnyInt?
/**
* Test user id (read-only)
*/
public var user_id: Int? {
get { _user_id?.value }
set { _user_id = newValue.map(AnyInt.init) }
}
public init(id: Int, user_id: Int? = nil) {
self._id = AnyInt.init(id)
self._user_id = user_id.map(AnyInt.init)
}
public init(_ id: Int, user_id: Int? = nil) {
self.init(id: id, user_id: user_id)
}
}`
expect(actual).toEqual(expected)
})
Expand Down
43 changes: 35 additions & 8 deletions packages/sdk-codegen/src/swift.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,20 @@ import Foundation
)
}

/**
* true if this property should use AnyInt
* @param property to check
*/
useAnyInt(property: IProperty) {
const nameCheck = property.name.toLowerCase()
const typeCheck = property.type.name.toLowerCase()
return (
this.anyString &&
(typeCheck === 'integer' || typeCheck === 'int64') &&
(nameCheck === 'id' || nameCheck.endsWith('_id'))
)
}

/**
* Private version of the name (_ prefix)
* @param name to privatize
Expand All @@ -255,6 +269,14 @@ import Foundation
return this.reserve('_' + name)
}

getSpecialHandling(property: IProperty) {
return this.useAnyString(property)
? 'AnyString'
: this.useAnyInt(property)
? 'AnyInt'
: ''
}

declareProperty(indent: string, property: IProperty) {
// const optional = (property.nullable || !property.required) ? '?' : ''
const optional = property.required ? '' : '?'
Expand All @@ -273,7 +295,7 @@ import Foundation
)
}
const type = this.typeMap(property.type)
const specialHandling = this.useAnyString(property)
const specialHandling = this.getSpecialHandling(property)
let munge = ''
let declaration = `${indent}public var ${this.reserve(property.name)}: ${
type.name
Expand All @@ -282,9 +304,9 @@ import Foundation
const privy = this.reserve('_' + property.name)
const bump = this.bumper(indent)
const setter = property.required
? 'AnyString.init(newValue)'
: 'newValue.map(AnyString.init)'
munge = `${indent}private var ${privy}: AnyString${optional}\n`
? `${specialHandling}.init(newValue)`
: `newValue.map(${specialHandling}.init)`
munge = `${indent}private var ${privy}: ${specialHandling}${optional}\n`
declaration = `${indent}public var ${this.reserve(property.name)}: ${
type.name
}${optional} {
Expand Down Expand Up @@ -339,13 +361,18 @@ ${indent}}\n`
const propName = this.reserve(prop.name)
args.push(this.declareConstructorArg('', prop))
posArgs.push(this.declarePositionalArg('', prop))
if (this.useAnyString(prop)) {
const specialHandling = this.getSpecialHandling(prop)
if (specialHandling) {
const varName = this.privy(propName)
if (prop.required) {
inits.push(`${bump}${this.it(varName)} = AnyString.init(${propName})`)
inits.push(
`${bump}${this.it(varName)} = ${specialHandling}.init(${propName})`
)
} else {
inits.push(
`${bump}${this.it(varName)} = ${propName}.map(AnyString.init)`
`${bump}${this.it(
varName
)} = ${propName}.map(${specialHandling}.init)`
)
}
} else {
Expand Down Expand Up @@ -482,7 +509,7 @@ ${indent}}\n`
const keys = Object.values(type.properties).map((p) => {
let name = this.reserve(p.name)
let alias = ''
const useIt = this.useAnyString(p)
const useIt = this.useAnyString(p) || this.useAnyInt(p)
if (useIt) {
name = this.privy(name)
special = true
Expand Down
2 changes: 1 addition & 1 deletion spec/Looker.3.1.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"swagger": "2.0",
"info": {
"version": "3.1.0",
"x-looker-release-version": "21.20.8",
"x-looker-release-version": "21.20.32",
"title": "Looker API 3.1 Reference",
"description": "### Authorization\n\nThe classic method of API authorization uses Looker **API3** credentials for authorization and access control.\nLooker admins can create API3 credentials on Looker's **Admin/Users** page.\n\nAPI 4.0 adds additional ways to authenticate API requests, including OAuth and CORS requests.\n\nFor details, see [Looker API Authorization](https://looker.com/docs/r/api/authorization).\n\n\n### API Explorer\n\nThe API Explorer is a Looker-provided utility with many new and unique features for learning and using the Looker API and SDKs.\nIt is a replacement for the 'api-docs' page currently provided on Looker instances.\n\nFor details, see the [API Explorer documentation](https://looker.com/docs/r/api/explorer).\n\n\n### Looker Language SDKs\n\nThe Looker API is a RESTful system that should be usable by any programming language capable of making\nHTTPS requests. SDKs for a variety of programming languages are also provided to streamline using the API. Looker\nhas an OpenSource [sdk-codegen project](https://github.com/looker-open-source/sdk-codegen) that provides several\nlanguage SDKs. Language SDKs generated by `sdk-codegen` have an Authentication manager that can automatically\nauthenticate API requests when needed.\n\nFor details on available Looker SDKs, see [Looker API Client SDKs](https://looker.com/docs/r/api/client_sdks).\n\n\n### API Versioning\n\nFuture releases of Looker expand the latest API version release-by-release to securely expose more and more of the core\npower of the Looker platform to API client applications. API endpoints marked as \"beta\" may receive breaking changes without\nwarning (but we will try to avoid doing that). Stable (non-beta) API endpoints should not receive breaking\nchanges in future releases.\n\nFor details, see [Looker API Versioning](https://looker.com/docs/r/api/versioning).\n\n\n### Try It Out!\n\nThis section describes the existing 'api-docs' page available on Looker instances. We recommend using the\n[API Explorer](https://looker.com/docs/r/api/explorer) instead.\n\nThe 'api-docs' page served by the Looker instance includes 'Try It Out!' buttons for each API method. After logging\nin with API3 credentials, you can use the \"Try It Out!\" buttons to call the API directly from the documentation\npage to interactively explore API features and responses.\n\n**NOTE**! With great power comes great responsibility: The \"Try It Out!\" button makes API calls to your live Looker\ninstance. Be especially careful with destructive API operations such as `delete_user` or similar.\nThere is no \"undo\" for API operations. (API Explorer's \"Run It\" feature requires a check mark before running\nAPI operations that can change data.)\n\n\n### In This Release\n\nThe following are a few examples of noteworthy items that have changed between API 3.0 and API 3.1.\nFor more comprehensive coverage of API changes, please see the release notes for your Looker release.\n\n### Examples of new things added in API 3.1 (compared to API 3.0):\n\n* [Dashboard construction](#!/3.1/Dashboard/) APIs\n* [Themes](#!/3.1/Theme/) and [custom color collections](#!/3.1/ColorCollection) APIs\n* Create and run [SQL Runner](#!/3.1/Query/run_sql_query) queries\n* Create and run [merged results](#!/3.1/Query/create_merge_query) queries\n* Create and modify [dashboard filters](#!/3.1/Dashboard/create_dashboard_filter)\n* Create and modify [password requirements](#!/3.1/Auth/password_config)\n\n### Deprecated in API 3.0\n\nThe following functions and properties have been deprecated in API 3.0. They continue to exist and work in API 3.0\nfor the next several Looker releases but they have not been carried forward to API 3.1:\n\n* Dashboard Prefetch functions\n* User access_filter functions\n* User API 1.0 credentials functions\n* Space.is_root and Space.is_user_root properties. Use Space.is_shared_root and Space.is_users_root instead.\n\n### Semantic changes in API 3.1:\n\n* [all_looks()](#!/3.1/Look/all_looks) no longer includes soft-deleted looks, matching [all_dashboards()](#!/3.1/Dashboard/all_dashboards) behavior.\nYou can find soft-deleted looks using [search_looks()](#!/3.1/Look/search_looks) with the `deleted` param set to True.\n* [all_spaces()](#!/3.1/Space/all_spaces) no longer includes duplicate items\n* [search_users()](#!/3.1/User/search_users) no longer accepts Y,y,1,0,N,n for Boolean params, only \"true\" and \"false\".\n* For greater client and network compatibility, [render_task_results](#!/3.1/RenderTask/render_task_results) now returns\nHTTP status **202 Accepted** instead of HTTP status **102 Processing**\n* [all_running_queries()](#!/3.1/Query/all_running_queries) and [kill_query](#!/3.1/Query/kill_query) functions have moved into the [Query](#!/3.1/Query/) function group.\n\nThe API Explorer can be used to [interactively compare](https://looker.com/docs/r/api/explorer#comparing_api_versions) the differences between API 3.1 and 4.0.\n\n\n### API and SDK Support Policies\n\nLooker API versions and language SDKs have varying support levels. Please read the API and SDK\n[support policies](https://looker.com/docs/r/api/support-policy) for more information.\n\n\n",
"contact": {
Expand Down
2 changes: 1 addition & 1 deletion spec/Looker.3.1.oas.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.0",
"info": {
"version": "3.1.0",
"x-looker-release-version": "21.20.8",
"x-looker-release-version": "21.20.32",
"title": "Looker API 3.1 Reference",
"description": "### Authorization\n\nThe classic method of API authorization uses Looker **API3** credentials for authorization and access control.\nLooker admins can create API3 credentials on Looker's **Admin/Users** page.\n\nAPI 4.0 adds additional ways to authenticate API requests, including OAuth and CORS requests.\n\nFor details, see [Looker API Authorization](https://looker.com/docs/r/api/authorization).\n\n\n### API Explorer\n\nThe API Explorer is a Looker-provided utility with many new and unique features for learning and using the Looker API and SDKs.\nIt is a replacement for the 'api-docs' page currently provided on Looker instances.\n\nFor details, see the [API Explorer documentation](https://looker.com/docs/r/api/explorer).\n\n\n### Looker Language SDKs\n\nThe Looker API is a RESTful system that should be usable by any programming language capable of making\nHTTPS requests. SDKs for a variety of programming languages are also provided to streamline using the API. Looker\nhas an OpenSource [sdk-codegen project](https://github.com/looker-open-source/sdk-codegen) that provides several\nlanguage SDKs. Language SDKs generated by `sdk-codegen` have an Authentication manager that can automatically\nauthenticate API requests when needed.\n\nFor details on available Looker SDKs, see [Looker API Client SDKs](https://looker.com/docs/r/api/client_sdks).\n\n\n### API Versioning\n\nFuture releases of Looker expand the latest API version release-by-release to securely expose more and more of the core\npower of the Looker platform to API client applications. API endpoints marked as \"beta\" may receive breaking changes without\nwarning (but we will try to avoid doing that). Stable (non-beta) API endpoints should not receive breaking\nchanges in future releases.\n\nFor details, see [Looker API Versioning](https://looker.com/docs/r/api/versioning).\n\n\n### Try It Out!\n\nThis section describes the existing 'api-docs' page available on Looker instances. We recommend using the\n[API Explorer](https://looker.com/docs/r/api/explorer) instead.\n\nThe 'api-docs' page served by the Looker instance includes 'Try It Out!' buttons for each API method. After logging\nin with API3 credentials, you can use the \"Try It Out!\" buttons to call the API directly from the documentation\npage to interactively explore API features and responses.\n\n**NOTE**! With great power comes great responsibility: The \"Try It Out!\" button makes API calls to your live Looker\ninstance. Be especially careful with destructive API operations such as `delete_user` or similar.\nThere is no \"undo\" for API operations. (API Explorer's \"Run It\" feature requires a check mark before running\nAPI operations that can change data.)\n\n\n### In This Release\n\nThe following are a few examples of noteworthy items that have changed between API 3.0 and API 3.1.\nFor more comprehensive coverage of API changes, please see the release notes for your Looker release.\n\n### Examples of new things added in API 3.1 (compared to API 3.0):\n\n* [Dashboard construction](#!/3.1/Dashboard/) APIs\n* [Themes](#!/3.1/Theme/) and [custom color collections](#!/3.1/ColorCollection) APIs\n* Create and run [SQL Runner](#!/3.1/Query/run_sql_query) queries\n* Create and run [merged results](#!/3.1/Query/create_merge_query) queries\n* Create and modify [dashboard filters](#!/3.1/Dashboard/create_dashboard_filter)\n* Create and modify [password requirements](#!/3.1/Auth/password_config)\n\n### Deprecated in API 3.0\n\nThe following functions and properties have been deprecated in API 3.0. They continue to exist and work in API 3.0\nfor the next several Looker releases but they have not been carried forward to API 3.1:\n\n* Dashboard Prefetch functions\n* User access_filter functions\n* User API 1.0 credentials functions\n* Space.is_root and Space.is_user_root properties. Use Space.is_shared_root and Space.is_users_root instead.\n\n### Semantic changes in API 3.1:\n\n* [all_looks()](#!/3.1/Look/all_looks) no longer includes soft-deleted looks, matching [all_dashboards()](#!/3.1/Dashboard/all_dashboards) behavior.\nYou can find soft-deleted looks using [search_looks()](#!/3.1/Look/search_looks) with the `deleted` param set to True.\n* [all_spaces()](#!/3.1/Space/all_spaces) no longer includes duplicate items\n* [search_users()](#!/3.1/User/search_users) no longer accepts Y,y,1,0,N,n for Boolean params, only \"true\" and \"false\".\n* For greater client and network compatibility, [render_task_results](#!/3.1/RenderTask/render_task_results) now returns\nHTTP status **202 Accepted** instead of HTTP status **102 Processing**\n* [all_running_queries()](#!/3.1/Query/all_running_queries) and [kill_query](#!/3.1/Query/kill_query) functions have moved into the [Query](#!/3.1/Query/) function group.\n\nThe API Explorer can be used to [interactively compare](https://looker.com/docs/r/api/explorer#comparing_api_versions) the differences between API 3.1 and 4.0.\n\n\n### API and SDK Support Policies\n\nLooker API versions and language SDKs have varying support levels. Please read the API and SDK\n[support policies](https://looker.com/docs/r/api/support-policy) for more information.\n\n\n",
"contact": {
Expand Down
2 changes: 1 addition & 1 deletion spec/Looker.4.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"swagger": "2.0",
"info": {
"version": "4.0.21.20",
"x-looker-release-version": "21.20.8",
"x-looker-release-version": "21.20.32",
"title": "Looker API 4.0 (Beta) Reference",
"description": "\nWelcome to the future! API 4.0 co-exists with APIs 3.1 and 3.0. (3.0 should no longer be used.)\nThe \"beta\" tag means updates for API 4.0 may include breaking changes, but as always we will work to minimize them.\n\n### Authorization\n\nThe classic method of API authorization uses Looker **API3** credentials for authorization and access control.\nLooker admins can create API3 credentials on Looker's **Admin/Users** page.\n\nAPI 4.0 adds additional ways to authenticate API requests, including OAuth and CORS requests.\n\nFor details, see [Looker API Authorization](https://looker.com/docs/r/api/authorization).\n\n\n### API Explorer\n\nThe API Explorer is a Looker-provided utility with many new and unique features for learning and using the Looker API and SDKs.\nIt is a replacement for the 'api-docs' page currently provided on Looker instances.\n\nFor details, see the [API Explorer documentation](https://looker.com/docs/r/api/explorer).\n\n\n### Looker Language SDKs\n\nThe Looker API is a RESTful system that should be usable by any programming language capable of making\nHTTPS requests. SDKs for a variety of programming languages are also provided to streamline using the API. Looker\nhas an OpenSource [sdk-codegen project](https://github.com/looker-open-source/sdk-codegen) that provides several\nlanguage SDKs. Language SDKs generated by `sdk-codegen` have an Authentication manager that can automatically\nauthenticate API requests when needed.\n\nFor details on available Looker SDKs, see [Looker API Client SDKs](https://looker.com/docs/r/api/client_sdks).\n\n\n### API Versioning\n\nFuture releases of Looker expand the latest API version release-by-release to securely expose more and more of the core\npower of the Looker platform to API client applications. API endpoints marked as \"beta\" may receive breaking changes without\nwarning (but we will try to avoid doing that). Stable (non-beta) API endpoints should not receive breaking\nchanges in future releases.\n\nFor details, see [Looker API Versioning](https://looker.com/docs/r/api/versioning).\n\n\n### In This Release\n\nAPI 4.0 version was introduced so we can make adjustments to API functions, parameters, and response types to\nfix bugs and inconsistencies. These changes fall outside the bounds of non-breaking additive changes we can\nmake to our stable API 3.1.\n\nOne benefit of these type adjustments in API 4.0 is dramatically better support for strongly\ntyped languages like TypeScript, Kotlin, Swift, Go, C#, and more.\n\nWhile API 3.1 is still the de-facto Looker API (\"current\", \"stable\", \"default\", etc), the bulk\nof our development activity has shifted to API 4.0, where all new features are added.\n\nThe API Explorer can be used to [interactively compare](https://looker.com/docs/r/api/explorer#comparing_api_versions) the differences between API 3.1 and 4.0.\n\n\n### API and SDK Support Policies\n\nLooker API versions and language SDKs have varying support levels. Please read the API and SDK\n[support policies](https://looker.com/docs/r/api/support-policy) for more information.\n\n\n",
"contact": {
Expand Down
Loading

0 comments on commit 1487d8a

Please sign in to comment.