Skip to content
This repository was archived by the owner on Oct 16, 2025. It is now read-only.

Commit a657b0f

Browse files
hyochanclaude
andcommitted
feat(swift): add public initializers for Input types
Generate explicit public initializers for all Swift Input types to enable direct instantiation across module boundaries. ## Problem Swift's Codable structs don't expose public memberwise initializers across module boundaries. Input types like `RequestSubscriptionIosProps` only exposed `init(from: Decoder)`, making them impossible to instantiate directly when using OpenIAP as a Swift package dependency. ## Solution Modified the Swift code generator to automatically add public initializers for all Input types with: - All parameters with appropriate types - Optional parameters defaulting to `nil` - Required parameters without defaults ## Example ```swift // Before: workaround needed let json = ["sku": "product", ...] let data = try JSONSerialization.data(withJSONObject: json) let props = try JSONDecoder().decode(RequestSubscriptionIosProps.self, from: data) // After: direct instantiation let props = RequestSubscriptionIosProps(sku: "product") ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8427d41 commit a657b0f

File tree

2 files changed

+167
-0
lines changed

2 files changed

+167
-0
lines changed

scripts/generate-swift-types.mjs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,23 @@ const printInput = (inputType) => {
453453
const propertyName = escapeSwiftName(field.name);
454454
lines.push(` public var ${propertyName}: ${propertyType}`);
455455
}
456+
// Generate public initializer
457+
lines.push('');
458+
const initParams = fields.map((field) => {
459+
const { type, optional } = swiftTypeFor(field.type);
460+
const propertyType = type + (optional ? '?' : '');
461+
const propertyName = escapeSwiftName(field.name);
462+
const defaultValue = optional ? ' = nil' : '';
463+
return ` ${propertyName}: ${propertyType}${defaultValue}`;
464+
}).join(',\n');
465+
lines.push(' public init(');
466+
lines.push(initParams);
467+
lines.push(' ) {');
468+
for (const field of fields) {
469+
const propertyName = escapeSwiftName(field.name);
470+
lines.push(` self.${propertyName} = ${propertyName}`);
471+
}
472+
lines.push(' }');
456473
}
457474
lines.push('}', '');
458475
};

src/generated/Types.swift

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,13 +478,29 @@ public struct AndroidSubscriptionOfferInput: Codable {
478478
public var offerToken: String
479479
/// Product SKU
480480
public var sku: String
481+
482+
public init(
483+
offerToken: String,
484+
sku: String
485+
) {
486+
self.offerToken = offerToken
487+
self.sku = sku
488+
}
481489
}
482490

483491
public struct DeepLinkOptions: Codable {
484492
/// Android package name to target (required on Android)
485493
public var packageNameAndroid: String?
486494
/// Android SKU to open (required on Android)
487495
public var skuAndroid: String?
496+
497+
public init(
498+
packageNameAndroid: String? = nil,
499+
skuAndroid: String? = nil
500+
) {
501+
self.packageNameAndroid = packageNameAndroid
502+
self.skuAndroid = skuAndroid
503+
}
488504
}
489505

490506
public struct DiscountOfferInputIOS: Codable {
@@ -498,18 +514,46 @@ public struct DiscountOfferInputIOS: Codable {
498514
public var signature: String
499515
/// Timestamp of discount offer
500516
public var timestamp: Double
517+
518+
public init(
519+
identifier: String,
520+
keyIdentifier: String,
521+
nonce: String,
522+
signature: String,
523+
timestamp: Double
524+
) {
525+
self.identifier = identifier
526+
self.keyIdentifier = keyIdentifier
527+
self.nonce = nonce
528+
self.signature = signature
529+
self.timestamp = timestamp
530+
}
501531
}
502532

503533
/// Connection initialization configuration
504534
public struct InitConnectionConfig: Codable {
505535
/// Alternative billing mode for Android
506536
/// If not specified, defaults to NONE (standard Google Play billing)
507537
public var alternativeBillingModeAndroid: AlternativeBillingModeAndroid?
538+
539+
public init(
540+
alternativeBillingModeAndroid: AlternativeBillingModeAndroid? = nil
541+
) {
542+
self.alternativeBillingModeAndroid = alternativeBillingModeAndroid
543+
}
508544
}
509545

510546
public struct ProductRequest: Codable {
511547
public var skus: [String]
512548
public var type: ProductQueryType?
549+
550+
public init(
551+
skus: [String],
552+
type: ProductQueryType? = nil
553+
) {
554+
self.skus = skus
555+
self.type = type
556+
}
513557
}
514558

515559
public typealias PurchaseInput = Purchase
@@ -519,20 +563,48 @@ public struct PurchaseOptions: Codable {
519563
public var alsoPublishToEventListenerIOS: Bool?
520564
/// Limit to currently active items on iOS
521565
public var onlyIncludeActiveItemsIOS: Bool?
566+
567+
public init(
568+
alsoPublishToEventListenerIOS: Bool? = nil,
569+
onlyIncludeActiveItemsIOS: Bool? = nil
570+
) {
571+
self.alsoPublishToEventListenerIOS = alsoPublishToEventListenerIOS
572+
self.onlyIncludeActiveItemsIOS = onlyIncludeActiveItemsIOS
573+
}
522574
}
523575

524576
public struct ReceiptValidationAndroidOptions: Codable {
525577
public var accessToken: String
526578
public var isSub: Bool?
527579
public var packageName: String
528580
public var productToken: String
581+
582+
public init(
583+
accessToken: String,
584+
isSub: Bool? = nil,
585+
packageName: String,
586+
productToken: String
587+
) {
588+
self.accessToken = accessToken
589+
self.isSub = isSub
590+
self.packageName = packageName
591+
self.productToken = productToken
592+
}
529593
}
530594

531595
public struct ReceiptValidationProps: Codable {
532596
/// Android-specific validation options
533597
public var androidOptions: ReceiptValidationAndroidOptions?
534598
/// Product SKU to validate
535599
public var sku: String
600+
601+
public init(
602+
androidOptions: ReceiptValidationAndroidOptions? = nil,
603+
sku: String
604+
) {
605+
self.androidOptions = androidOptions
606+
self.sku = sku
607+
}
536608
}
537609

538610
public struct RequestPurchaseAndroidProps: Codable {
@@ -544,6 +616,18 @@ public struct RequestPurchaseAndroidProps: Codable {
544616
public var obfuscatedProfileIdAndroid: String?
545617
/// List of product SKUs
546618
public var skus: [String]
619+
620+
public init(
621+
isOfferPersonalized: Bool? = nil,
622+
obfuscatedAccountIdAndroid: String? = nil,
623+
obfuscatedProfileIdAndroid: String? = nil,
624+
skus: [String]
625+
) {
626+
self.isOfferPersonalized = isOfferPersonalized
627+
self.obfuscatedAccountIdAndroid = obfuscatedAccountIdAndroid
628+
self.obfuscatedProfileIdAndroid = obfuscatedProfileIdAndroid
629+
self.skus = skus
630+
}
547631
}
548632

549633
public struct RequestPurchaseIosProps: Codable {
@@ -559,6 +643,22 @@ public struct RequestPurchaseIosProps: Codable {
559643
public var sku: String
560644
/// Discount offer to apply
561645
public var withOffer: DiscountOfferInputIOS?
646+
647+
public init(
648+
andDangerouslyFinishTransactionAutomatically: Bool? = nil,
649+
appAccountToken: String? = nil,
650+
externalPurchaseUrl: String? = nil,
651+
quantity: Int? = nil,
652+
sku: String,
653+
withOffer: DiscountOfferInputIOS? = nil
654+
) {
655+
self.andDangerouslyFinishTransactionAutomatically = andDangerouslyFinishTransactionAutomatically
656+
self.appAccountToken = appAccountToken
657+
self.externalPurchaseUrl = externalPurchaseUrl
658+
self.quantity = quantity
659+
self.sku = sku
660+
self.withOffer = withOffer
661+
}
562662
}
563663

564664
public struct RequestPurchaseProps: Codable {
@@ -636,6 +736,14 @@ public struct RequestPurchasePropsByPlatforms: Codable {
636736
public var android: RequestPurchaseAndroidProps?
637737
/// iOS-specific purchase parameters
638738
public var ios: RequestPurchaseIosProps?
739+
740+
public init(
741+
android: RequestPurchaseAndroidProps? = nil,
742+
ios: RequestPurchaseIosProps? = nil
743+
) {
744+
self.android = android
745+
self.ios = ios
746+
}
639747
}
640748

641749
public struct RequestSubscriptionAndroidProps: Codable {
@@ -653,6 +761,24 @@ public struct RequestSubscriptionAndroidProps: Codable {
653761
public var skus: [String]
654762
/// Subscription offers
655763
public var subscriptionOffers: [AndroidSubscriptionOfferInput]?
764+
765+
public init(
766+
isOfferPersonalized: Bool? = nil,
767+
obfuscatedAccountIdAndroid: String? = nil,
768+
obfuscatedProfileIdAndroid: String? = nil,
769+
purchaseTokenAndroid: String? = nil,
770+
replacementModeAndroid: Int? = nil,
771+
skus: [String],
772+
subscriptionOffers: [AndroidSubscriptionOfferInput]? = nil
773+
) {
774+
self.isOfferPersonalized = isOfferPersonalized
775+
self.obfuscatedAccountIdAndroid = obfuscatedAccountIdAndroid
776+
self.obfuscatedProfileIdAndroid = obfuscatedProfileIdAndroid
777+
self.purchaseTokenAndroid = purchaseTokenAndroid
778+
self.replacementModeAndroid = replacementModeAndroid
779+
self.skus = skus
780+
self.subscriptionOffers = subscriptionOffers
781+
}
656782
}
657783

658784
public struct RequestSubscriptionIosProps: Codable {
@@ -663,13 +789,37 @@ public struct RequestSubscriptionIosProps: Codable {
663789
public var quantity: Int?
664790
public var sku: String
665791
public var withOffer: DiscountOfferInputIOS?
792+
793+
public init(
794+
andDangerouslyFinishTransactionAutomatically: Bool? = nil,
795+
appAccountToken: String? = nil,
796+
externalPurchaseUrl: String? = nil,
797+
quantity: Int? = nil,
798+
sku: String,
799+
withOffer: DiscountOfferInputIOS? = nil
800+
) {
801+
self.andDangerouslyFinishTransactionAutomatically = andDangerouslyFinishTransactionAutomatically
802+
self.appAccountToken = appAccountToken
803+
self.externalPurchaseUrl = externalPurchaseUrl
804+
self.quantity = quantity
805+
self.sku = sku
806+
self.withOffer = withOffer
807+
}
666808
}
667809

668810
public struct RequestSubscriptionPropsByPlatforms: Codable {
669811
/// Android-specific subscription parameters
670812
public var android: RequestSubscriptionAndroidProps?
671813
/// iOS-specific subscription parameters
672814
public var ios: RequestSubscriptionIosProps?
815+
816+
public init(
817+
android: RequestSubscriptionAndroidProps? = nil,
818+
ios: RequestSubscriptionIosProps? = nil
819+
) {
820+
self.android = android
821+
self.ios = ios
822+
}
673823
}
674824

675825
// MARK: - Unions

0 commit comments

Comments
 (0)