Skip to content

Releases: tddworks/asc-cli

asc v0.17.0

21 Apr 13:12

Choose a tag to compare

Added

  • GET /api/v1/apps?include=icon — enriches each app in the response with its primary build's iconAsset (templateUrl, width, height). Icon fetch is opt-in to keep the default list-apps path fast. Without ?include=icon, behaviour is unchanged. Template URL placeholders ({w}, {h}, {f}) can be substituted client-side to render at any size (e.g. 120x120bb.png).
  • Domain types ImageAsset, App.iconAsset — new optional iconAsset on App (omitted from JSON when nil), new ImageAsset value type under Domain/Shared/ with url(maxSize:format:) helper. Populated from SDK Build.iconAssetToken via /v1/apps/{id}/appStoreVersions?include=build
  • AppRepository.fetchAppIcon(appId:) — returns ImageAsset? by joining the latest app version to its build. Returns nil when no version has an attached build
  • GET /api/v1/apps/{appId}/app-infos — new REST route backed by AppInfoRepository. Previously the affordance on App advertised this path but the controller returned 404. AppInfo is now Presentable and uses structuredAffordances, so responses include _links to app-info localizations, age rating, and the enclosing app-infos list
  • AppInfo.appStoreState / AppInfo.state — app-infos responses now include lifecycle fields (appStoreState uses legacy ASC version states like READY_FOR_SALE; state uses the newer AppInfo.State enum like READY_FOR_DISTRIBUTION, PREPARE_FOR_SUBMISSION). Agents can use these to pick the live-version app-info vs the version-being-prepared. Computed booleans isLive and isEditable expose the common decisions
  • AppInfo.appStoreAgeRating — computed App Store age rating (e.g. FOUR_PLUS, NINE_PLUS, TWELVE_PLUS, SEVENTEEN_PLUS) now surfaced on app-infos responses. This is what the App Store listing page displays; cheaper than fetching the full ageRatingDeclaration when only the label is needed
  • asc app-categories get --category-id <id> + GET /api/v1/app-categories/{id} — fetch a single App Store category by ID. AppInfo responses now include getPrimaryCategory, getSecondaryCategory, and four subcategory affordances (conditional on the respective ID being set), each pointing at the new endpoint. Backed by new AppCategoryRepository.getCategory(id:)
  • GET /api/v1/app-categories — list categories exposed at the REST layer (previously CLI-only). Optional ?platform= query param mirrors the CLI flag
  • GET /api/v1/app-infos/{appInfoId}/localizations — new REST route backed by AppInfoRepository.listLocalizations. AppInfoLocalization is now Presentable with structuredAffordances including update/delete links
  • Unified REST path resolver — removed the global {param → segment} alias table from RESTPathResolver. New single rule: for resource actions (get/update/delete/submit/…), the command name IS the REST segment. CLI flag aliases (e.g. --localization-id, --product-id) are presentation concerns and no longer drive REST routing. Fixes ambiguity where the same CLI flag belonged to multiple resources
  • GET /api/v1/age-rating/{appInfoId} — fetch the age rating declaration for an app-info. Previously only asc age-rating get worked; the REST route was advertised via _links.getAgeRating but returned 404. AgeRatingDeclaration is now Presentable with structuredAffordances
  • PATCH /api/v1/app-infos/{appInfoId} — update app-info categories (primary, secondary, up to two subcategories each) via REST. JSON body accepts primaryCategoryId, primarySubcategoryOneId, primarySubcategoryTwoId, secondaryCategoryId, secondarySubcategoryOneId, secondarySubcategoryTwoId — any subset. Returns the updated AppInfo with _links that now include getPrimaryCategory / getSecondaryCategory pointing at the new values
  • GET /api/v1/version-localizations/{localizationId}/screenshot-sets and GET /api/v1/screenshot-sets/{setId}/screenshots — screenshot-related _links on AppStoreVersionLocalization and AppScreenshotSet responses now resolve to working REST endpoints. AppStoreVersionLocalization, AppScreenshotSet, and AppScreenshot now use structuredAffordances (replacing raw affordances); the latter two also gained Presentable conformance

Changed

  • REST controllers split by resource (SRP/OCP refactor) — the former AppsController was a god controller accumulating 15+ routes across 8 unrelated resources (apps, versions, localizations, screenshot-sets, screenshots, builds, testflight, reviews, iap, subscription-groups, app-infos, app-info-localizations, app-categories, age-rating). Now split into 13 focused controllers, one per REST resource type — AppsController, VersionsController, VersionLocalizationsController, ScreenshotSetsController, ScreenshotsController, BuildsController, TestFlightController, CustomerReviewsController, IAPController, SubscriptionGroupsController, AppInfosController, AppCategoriesController, AgeRatingController. Each takes only the 1–2 repositories it actually needs. RESTRoutes.configure composes them with one line per resource. Adding a new resource no longer requires editing an existing controller

Fixed

  • RESTPathResolver.ensureInitialized race — the initialized flag was being set before the domain route registrations ran, so concurrent callers could observe initialized == true while the routes dictionary was still empty. Now uses a separate initLock and sets the flag only after all _*Routes registrations complete. Fixes intermittent test failures where screenshot/localization _links resolved to top-level paths under parallel test execution
  • include=primaryCategory,… on app-infos request — added to SDKAppInfoRepository.listAppInfos alongside fields[appInfos]. The ASC API returns only relationship links with fields[] alone; include= is required to populate relationships.primaryCategory.data.id so the mapper can surface primaryCategoryId etc.

Fixed

  • AppInfo.primaryCategoryId / secondary categories missing from /v1/apps/{id}/appInfos — the ASC API returns relationship data sparsely unless the client requests the explicit sparse fieldset. SDKAppInfoRepository.listAppInfos now passes fields[appInfos]=primaryCategory,primarySubcategoryOne,primarySubcategoryTwo,secondaryCategory,secondarySubcategoryOne,secondarySubcategoryTwo, so the mapped AppInfo carries the category IDs

asc v0.16.9

20 Apr 15:58

Choose a tag to compare

Added

  • asc review-submissions list — list App Store review submissions for an app. Required --app-id; optional --state <CSV> (e.g. WAITING_FOR_REVIEW,IN_REVIEW,READY_FOR_REVIEW or UNRESOLVED_ISSUES) and --limit. Backed by SubmissionRepository.listSubmissions(appId:states:limit:)
  • asc certificates list filtering flags--limit (server-side), --expired-only (client-side, drops unexpired certs), --before <ISO8601> (client-side, keeps certs with expirationDate strictly before the cutoff)
  • REST endpoint GET /api/v1/apps/{appId}/review-submissions — new ReviewSubmissionsController in the asc web-server. Supports ?state=…&limit=… query params; mirrors the CLI. No fleet route — Apple's OpenAPI spec marks filter[app] as required, so review submissions can only be listed per-app
  • REST endpoint GET /api/v1/certificates query params — now honours ?type=&limit=&expired-only=&before= (previously ignored). before accepts both full ISO8601 (2026-11-01T00:00:00Z) and date-only (2026-11-01, interpreted as midnight UTC). Same filter semantics as the CLI
  • REST endpoint GET /api/v1/builds — fleet listing with optional ?app-id=&platform=&version=&limit= query params. /api/v1/apps/{appId}/builds still works for the nested form

Changed

  • CertificateRepository.listCertificates signature now takes (certificateType:limit:) — forwards limit to the SDK
  • ReviewSubmission REST links — affordance migrated from raw affordances dictionary to structuredAffordances, so REST responses now render _links correctly (e.g. /api/v1/apps/{appId}/versions)

asc v0.1.68

14 Apr 13:39

Choose a tag to compare

Added

  • asc testflight groups create — create external or internal TestFlight beta groups (--internal flag toggles internal; --public-link-enabled / --feedback-enabled for external groups)
  • asc init review contact flags--contact-first-name, --contact-last-name, --contact-phone, --contact-email save review contact info to .asc/project.json for reuse across versions
  • ProjectConfig review contact fields — optional contactFirstName, contactLastName, contactPhone, contactEmail with hasReviewContact computed property
  • setReviewContact / updateReviewContact affordancesProjectConfig now suggests setting review contact when missing

asc v0.1.67

13 Apr 11:57

Choose a tag to compare

Bug fixes and improvements.

asc v0.1.66

09 Apr 07:14

Choose a tag to compare

Added

  • ThemeDesign domain model — composes from Gallery-native types (GalleryPalette + [Decoration]) for structured theme output. Generated by AI once, applied deterministically to all screenshots
  • ThemeDesignApplier — re-renders through GalleryHTMLRenderer.renderScreen() pipeline with overridden palette and merged decorations (no HTML patching)
  • GalleryPalette.textColor — optional explicit text color, overrides the auto-detect heuristic
  • Decoration.label() shape — text/emoji decorative elements (e.g. Decoration(shape: .label("✨"), ...))
  • DecorationAnimation — float, drift, pulse, spin, twinkle animations for decorations
  • ScreenLayout.withDecorations() — creates a copy with additional decorations
  • GalleryHTMLRenderer.renderDecorations() — renders ScreenLayout.decorations (previously dead code) using cqi units
  • buildDesignContext() on ScreenTheme — prompt method that instructs AI to return ThemeDesign JSON
  • design() on ThemeProvider/ThemeRepository — generate a ThemeDesign from AI in one call
  • --design-only / --apply-design CLI flags — batch theme workflow
  • REST endpointsPOST /app-shots/themes/design and POST /app-shots/themes/apply-design

Changed

  • GalleryHTMLRenderer refactored to Mustache templates — all HTML extracted from Swift into 7 .mustache template files using swift-mustache. The renderer only builds context dictionaries; all HTML, CSS colors (via CSS custom properties in theme-vars.mustache), and keyframe animations live in templates. Templates are pre-compiled at startup via MustacheLibrary for performance. Preview rendering is cached per template ID.
  • DecorationShape.displayCharacter — computed property on the model instead of renderer logic
  • GalleryPalette.isLight + headlineColor — theme detection and text color derivation moved from renderer to palette
  • Decoration extended — new optional fields: color, background, borderRadius, animation
  • Theme selection no longer requires auto-compose — clicking a theme applies immediately to slides with existing preview HTML via ThemeDesign (1 AI call for design, then deterministic apply to all slides)
  • Blitz plugin: design() implemented — generates ThemeDesign via compose bridge mode: "design", enabling the fast design→apply-design flow

asc v0.1.65

06 Apr 03:45

Choose a tag to compare

Changed

  • Presentable protocol — domain models own their table headers and row values; eliminates headers:/rowMapper: boilerplate from 37 list commands
  • REST controllers with DI — routes rewritten as controller structs (AppsController, CodeSigningController, etc.) with injected repo dependencies; repos created once at server startup, not per request
  • No more Command.parse([]) in REST layer — controllers call domain repos and operations directly; CLI and REST are equal thin adapters
  • AffordanceRegistry uses structured Affordance — plugin affordances now render to both CLI commands and REST _links (previously CLI-only)
  • ScreenshotTemplate domain operationsapply(content:), renderFragment(content:) as rich domain methods; ThemedPage value type for page wrapping
  • ScreenshotTemplate Codable includes previewHTML and deviceCount — REST consumers get preview data without special handling

asc v0.1.64

05 Apr 11:35

Choose a tag to compare

Added

  • REST API with HATEOASGET /api/v1 entry point plus 12 resource endpoints (apps, versions, builds, testflight, certificates, bundle-ids, devices, profiles, simulators, plugins, territories) calling domain repositories directly (in-process, no subprocess), returning JSON with _links for agent navigation
  • APIRoot model — HATEOAS entry point at GET /api/v1 listing all available top-level resources with navigable _links
  • Structured Affordance type — single source of truth for both CLI commands and REST links; models define affordances once, rendered to either format by OutputFormatter
  • APILink and AffordanceMode — domain types supporting dual-mode affordance rendering (.cli"affordances", .rest"_links")
  • RESTPathResolver — resolves CLI command + params into REST API paths using a route table covering 35+ resource types across the full domain hierarchy
  • HTML-to-PNG export--preview image option on asc app-shots templates apply and asc app-shots themes apply renders composed HTML to PNG via WebKit, with --image-output for custom output path
  • HTMLRenderer protocol@Mockable domain protocol for HTML-to-image rendering, implemented by WebKitHTMLRenderer using WKWebView snapshot

asc v0.1.63

02 Apr 10:30

Choose a tag to compare

Added

  • Plugin Marketplaceasc plugins market list and asc plugins market search --query X to browse and search plugins from tddworks/asc-registry
  • Multi-source plugin registryPluginSource protocol with GitHubPluginSource implementation; composable sources in PluginMarketRepository
  • asc plugins install --name X — download and install .plugin bundles from the marketplace
  • asc plugins uninstall --name X — remove installed plugin bundles (matches by slug or registry ID)
  • Plugins page in Command Center — web UI with Installed and Marketplace tabs, stats bar, install/uninstall with loading spinners
  • Enriched plugin manifestmanifest.json now supports description, author, repositoryURL, categories; installed plugins display the same rich info as marketplace listings
  • Centralized plugin affordance mergingAffordanceRegistry affordances merged automatically in OutputFormatter via WithPluginAffordances; domain models no longer need manual registry calls
  • Example pluginexamples/hello-plugin/ demonstrates AffordanceRegistry, server routes, and UI affordance handlers
  • Plugin registry repotddworks/asc-registry with registry.json and release assets for ASC Pro + Hello Plugin

Changed

  • Unified Plugin model — merged Plugin and MarketPlugin into a single model with isInstalled, downloadURL?, slug? fields
  • Refactored plugin system — replaced event-based script plugins with dylib .plugin bundle management
  • Removed event plugin system — deleted PluginEvent, PluginEventPayload, PluginResult, PluginRunner, PluginEventBus and all infrastructure
  • Removed event bus from commandsBuildsUpload and VersionsSubmit no longer emit plugin events
  • Apps page affordance buttons — plugin affordances (e.g. greet from Hello Plugin) render as clickable buttons via appAffordanceHandlers registry

asc v0.1.62

02 Apr 05:10

Choose a tag to compare

Added

  • asc web-server — Swift/Hummingbird HTTP+WebSocket server replacing Node.js. Single binary, zero external dependencies, HTTPS with self-signed cert
  • Plugin architecture.plugin bundles in ~/.asc/plugins/ extend the CLI with routes, commands, affordances, and UI. Dylibs built with dynamic_lookup (~300KB)
  • AffordanceRegistry — plugins extend domain model affordances at runtime (e.g. pro plugin adds stream to booted simulators)
  • Affordance-driven UI — web app renders buttons from CAEOAS affordances, not hardcoded features. Plugins register handlers via window.simAffordanceHandlers
  • Command Center Simulators page — device list with search/filter, stats cards, affordance-driven actions

asc v0.1.61

31 Mar 11:35

Choose a tag to compare

Added

  • Screenshot image URLsasc screenshots list now returns imageUrl for each screenshot, so you can view and render real App Store images directly from CLI output
  • Screenshot platform filtering — filter and browse screenshots by platform (iPhone, iPad, etc.) in the web UI
  • Simulator screenshot capture — capture and browse simulator screenshots in the web gallery
  • Simulator live streaming — stream your simulator screen in real-time via MJPEG to the browser

Changed

  • Simulator interaction feedback — improved tap ripple effect and gesture responsiveness in the streaming UI