Overhauled the library with several new features (#5)
## Summary Updates the library to v4.5.1 of the App Store Connect API, and ships it as a breaking 2.0.0 release with pagination, API key authentication, rate limiting, and a lighter install for consumers. ## Breaking changes - **Minimum platforms:** iOS 14, macOS 11, tvOS 14, watchOS 7, and visionOS 1. - **Toolchain:** Swift 6.0+ (Xcode 16+). The package builds in the Swift 6 language mode. - **Runtime:** requires `swift-openapi-runtime` 1.11.0 or later. ## Changes - **API:** updated the OpenAPI specification to v4.5.1, covering 1,303 operations and 1,473 schemas. - **Pagination:** the spec patch adds the undocumented `cursor` query parameter to the 465 paged operations. `PagedDocumentLinks.nextCursor` reads the cursor from a page, and `PagedSequence` iterates every page. - **Authentication:** `APIKeyTokenProvider` signs ES256 tokens from an API key and reuses each one until a minute before it expires. `BearerAuthMiddleware` now accepts a token provider. - **Rate limiting:** `RateLimitMiddleware` retries `429` responses, waiting for `Retry-After` or backing off exponentially. - **Generated code:** committed to `Sources/ASConnectService/Sources/Public/Generated` instead of generated by a build plugin. Consumers now resolve 4 packages instead of 12, and Xcode no longer asks to trust a plugin. - **Tooling:** - `make oas-download` now downloads, patches, generates, and checks the docs in one go. - New `make oas-generate`, `make oas-validate`, and `make doc-check` targets. - The generator is pinned in `Tools/`, and the DocC plugin is only resolved by the documentation targets. - **Documentation:** the DocC catalog now lists every operation and schema in the spec, and the catalog and README are rewritten for the new APIs. - **Housekeeping:** Apache 2.0 license headers on every Swift file, including `Package.swift` and the tests. Reviewed-on: #5 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #5.
This commit is contained in:
1 parent
3aaf5cd7a5
commit
0431fb5133
27 files changed
+1046471
-284
No files matched your search
@@ -0,0 +1,83 @@
|
||||
# ===------------------------------------------------------------------------------------===
|
||||
#
|
||||
# This source file is part of the App Store Connect Service open source project
|
||||
#
|
||||
# Copyright (c) 2026 Röck+Cöde VoF. and the App Store Connect Service project authors
|
||||
# Licensed under Apache license v2.0
|
||||
#
|
||||
# See LICENSE for license information
|
||||
# See CONTRIBUTORS for the list of App Store Connect Service project authors
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# ===------------------------------------------------------------------------------------===
|
||||
|
||||
"""Checks that the DocC catalog lists every generated operation and schema, and nothing else.
|
||||
|
||||
Usage: python3 check-docc.py <generated sources folder> <DocC catalog folder>
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def generated_symbols(types_path):
|
||||
"""Returns the methods, operations, and schemas in the generated `Types.swift` file."""
|
||||
lines = open(types_path).read().split('\n')
|
||||
|
||||
def start(prefix):
|
||||
return next(index for index, line in enumerate(lines) if line.startswith(prefix))
|
||||
|
||||
protocol = lines[start('public protocol APIProtocol'):start('extension APIProtocol {')]
|
||||
components = lines[start('public enum Components {'):start('public enum Operations {')]
|
||||
operations = lines[start('public enum Operations {'):]
|
||||
|
||||
schema = re.compile(r' (?:@\w+ )*public (?:indirect )?(?:struct|enum|typealias) (\w+)')
|
||||
|
||||
return {
|
||||
'APIProtocol.md': {m.group(1) for line in protocol if (m := re.match(r' func (\w+)\(', line))},
|
||||
'Operations.md': {m.group(1) for line in operations if (m := re.match(r' public enum (\w+)', line))},
|
||||
'Components.md': {m.group(1) for line in components if (m := schema.match(line))},
|
||||
}
|
||||
|
||||
|
||||
def documented_symbols(catalog_path):
|
||||
"""Returns the symbols listed in the DocC catalog topics."""
|
||||
patterns = {
|
||||
'APIProtocol.md': r'``(\w+)\(_:\)``',
|
||||
'Operations.md': r'``Operations/(\w+)``',
|
||||
'Components.md': r'``Components/Schemas/(\w+)``',
|
||||
}
|
||||
|
||||
return {
|
||||
name: set(re.findall(pattern, open(f'{catalog_path}/Extensions/{name}').read()))
|
||||
for name, pattern in patterns.items()
|
||||
}
|
||||
|
||||
|
||||
def main(generated_path, catalog_path):
|
||||
generated = generated_symbols(f'{generated_path}/Types.swift')
|
||||
documented = documented_symbols(catalog_path)
|
||||
is_up_to_date = True
|
||||
|
||||
for name in generated:
|
||||
missing = sorted(generated[name] - documented[name])
|
||||
stale = sorted(documented[name] - generated[name])
|
||||
|
||||
for title, symbols in [('Missing from', missing), ('Stale in', stale)]:
|
||||
if symbols:
|
||||
is_up_to_date = False
|
||||
print(f'{title} {name} ({len(symbols)}):')
|
||||
print('\n'.join(f' - {symbol}' for symbol in symbols))
|
||||
|
||||
if is_up_to_date:
|
||||
print('The DocC catalog lists every generated operation and schema.')
|
||||
|
||||
return 0 if is_up_to_date else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 3:
|
||||
sys.exit(__doc__)
|
||||
|
||||
sys.exit(main(sys.argv[1], sys.argv[2]))
|
||||
@@ -0,0 +1,39 @@
|
||||
# ===------------------------------------------------------------------------------------===
|
||||
#
|
||||
# This source file is part of the App Store Connect Service open source project
|
||||
#
|
||||
# Copyright (c) 2026 Röck+Cöde VoF. and the App Store Connect Service project authors
|
||||
# Licensed under Apache license v2.0
|
||||
#
|
||||
# See LICENSE for license information
|
||||
# See CONTRIBUTORS for the list of App Store Connect Service project authors
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# ===------------------------------------------------------------------------------------===
|
||||
|
||||
# Patches the App Store Connect OpenAPI specification document. Each patch is safe to apply more than once.
|
||||
|
||||
# Removes empty enums (e.g. `fields[appKeywords]`), as they generate case-less Swift enums that do not compile.
|
||||
(.. | objects | select(.enum == [])) |= del(.enum)
|
||||
|
||||
# Adds the undocumented `cursor` query parameter, used by `next` links, to the operations that return paged responses.
|
||||
| ([
|
||||
.components.schemas
|
||||
| to_entries[]
|
||||
| select(.value.properties.links["$ref"] == "#/components/schemas/PagedDocumentLinks")
|
||||
| "#/components/schemas/" + .key
|
||||
]) as $paged
|
||||
| .paths[][] |= (
|
||||
if type == "object"
|
||||
and (.responses["200"].content["application/json"].schema["$ref"] as $ref | any($paged[]; . == $ref))
|
||||
and (any(.parameters[]?; .name == "cursor") | not)
|
||||
then .parameters += [{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"description": "cursor of the page to fetch, from the next link of the previous page",
|
||||
"schema": { "type": "string" },
|
||||
"style": "form"
|
||||
}]
|
||||
else . end
|
||||
)
|
||||
Reference in new issue
Block a user