@swiftbrowser/swift 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +214 -0
- package/README.md +10 -2
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +61 -0
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/FoundationBridge/Bundle.swift +119 -0
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +29 -0
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Locale.swift +86 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +53 -0
- package/Sources/FoundationBridge/UITextChecker.swift +30 -0
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/FoundationBridge/UserDefaults.swift +183 -0
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +181 -0
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +221 -0
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +285 -0
- package/Sources/SwiftUI/API/App.swift +87 -0
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +237 -0
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +300 -0
- package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +92 -0
- package/Sources/SwiftUI/API/EditMode.swift +212 -0
- package/Sources/SwiftUI/API/Effects.swift +388 -0
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +439 -0
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +137 -0
- package/Sources/SwiftUI/API/Font.swift +131 -0
- package/Sources/SwiftUI/API/Gauge.swift +290 -0
- package/Sources/SwiftUI/API/Geometry.swift +89 -0
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +342 -0
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +188 -0
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
- package/Sources/SwiftUI/API/Layout.swift +220 -0
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +331 -0
- package/Sources/SwiftUI/API/Menu.swift +58 -0
- package/Sources/SwiftUI/API/Modifiers.swift +313 -0
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +386 -0
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
- package/Sources/SwiftUI/API/OnChange.swift +48 -0
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +185 -0
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +122 -0
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +517 -0
- package/Sources/SwiftUI/API/Publishers.swift +107 -0
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +84 -0
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +144 -0
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +263 -0
- package/Sources/SwiftUI/API/Tasks.swift +35 -0
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Timeline.swift +212 -0
- package/Sources/SwiftUI/API/Toolbar.swift +251 -0
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +215 -0
- package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
- package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +325 -0
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +660 -0
- package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Charts/Marks.swift +204 -0
- package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
- package/Sources/SwiftUI/Charts/Scales.swift +326 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
- package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
- package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +2 -0
- package/index.mjs +16 -0
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +30 -4
- package/sync-sources.mjs +33 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// `import SafariServices` for the browser: `SFSafariViewController`, the
|
|
2
|
+
// in-app Safari sheet, becomes a new tab. Presenting one (any view
|
|
3
|
+
// controller's `present`) asks the page to open its URL as a link would (an
|
|
4
|
+
// `openURL` host request; docs/ops-protocol.md, "Rich text"), and the
|
|
5
|
+
// controller is then done: it dismisses itself and tells its delegate
|
|
6
|
+
// `safariViewControllerDidFinish`, since the tab is the viewer's own from
|
|
7
|
+
// there. A URL that is not http(s) is refused, as on iOS (where the
|
|
8
|
+
// initializer raises). The configuration and tint colors are kept with
|
|
9
|
+
// nothing to style; Reader mode is the browser's own.
|
|
10
|
+
|
|
11
|
+
import Foundation
|
|
12
|
+
import FoundationBridge
|
|
13
|
+
import SwiftUI
|
|
14
|
+
import UIKit
|
|
15
|
+
|
|
16
|
+
/// The in-app browser: a new tab on the page (see the top of this file).
|
|
17
|
+
@MainActor
|
|
18
|
+
open class SFSafariViewController: UIViewController {
|
|
19
|
+
/// How the controller is set up; kept, with nothing in a tab to apply it to.
|
|
20
|
+
@MainActor
|
|
21
|
+
open class Configuration {
|
|
22
|
+
open var entersReaderIfAvailable = false
|
|
23
|
+
open var barCollapsingEnabled = true
|
|
24
|
+
public init() {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public enum DismissButtonStyle: Int, Sendable {
|
|
28
|
+
case done = 0, close, cancel
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Opens a URL on the page; tests replace it.
|
|
32
|
+
static var openOnPage: @MainActor (URL) -> Void = { url in
|
|
33
|
+
_Runtime.shared._openLinkOnPage(url.absoluteString)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public let url: URL
|
|
37
|
+
public let configuration: Configuration
|
|
38
|
+
open weak var delegate: (any SFSafariViewControllerDelegate)?
|
|
39
|
+
open var preferredBarTintColor: UIColor?
|
|
40
|
+
open var preferredControlTintColor: UIColor?
|
|
41
|
+
open var dismissButtonStyle: DismissButtonStyle = .done
|
|
42
|
+
private var opened = false
|
|
43
|
+
|
|
44
|
+
public init(url URL: URL, configuration: Configuration = Configuration()) {
|
|
45
|
+
self.url = URL
|
|
46
|
+
self.configuration = configuration
|
|
47
|
+
super.init(nibName: nil, bundle: nil)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@available(*, deprecated, renamed: "init(url:configuration:)")
|
|
51
|
+
public convenience init(url URL: URL, entersReaderIfAvailable: Bool) {
|
|
52
|
+
let configuration = Configuration()
|
|
53
|
+
configuration.entersReaderIfAvailable = entersReaderIfAvailable
|
|
54
|
+
self.init(url: URL, configuration: configuration)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public required init?(coder: NSCoder) { nil }
|
|
58
|
+
|
|
59
|
+
/// Presented: the URL opens in a new tab, and the controller finishes.
|
|
60
|
+
open override func viewDidAppear(_ animated: Bool) {
|
|
61
|
+
super.viewDidAppear(animated)
|
|
62
|
+
guard !opened else { return }
|
|
63
|
+
opened = true
|
|
64
|
+
if let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" {
|
|
65
|
+
Self.openOnPage(url)
|
|
66
|
+
delegate?.safariViewControllerWillOpenInBrowser(self)
|
|
67
|
+
}
|
|
68
|
+
dismiss(animated: animated)
|
|
69
|
+
delegate?.safariViewControllerDidFinish(self)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Nothing to warm up: the browser loads the page when the tab opens.
|
|
73
|
+
public static func prewarmConnections(to URLs: [URL]) -> PrewarmingToken { PrewarmingToken() }
|
|
74
|
+
|
|
75
|
+
public final class PrewarmingToken: Sendable {
|
|
76
|
+
public func invalidate() {}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// What a Safari view controller tells its owner. Every method is optional.
|
|
81
|
+
@MainActor
|
|
82
|
+
public protocol SFSafariViewControllerDelegate: AnyObject {
|
|
83
|
+
/// The controller is done: in the browser, right after it opened its tab.
|
|
84
|
+
func safariViewControllerDidFinish(_ controller: SFSafariViewController)
|
|
85
|
+
/// Never called: the page cannot see another site's tab load.
|
|
86
|
+
func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool)
|
|
87
|
+
/// Never called, for the same reason.
|
|
88
|
+
func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL)
|
|
89
|
+
/// Called as the URL opens in its tab.
|
|
90
|
+
func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
extension SFSafariViewControllerDelegate {
|
|
94
|
+
public func safariViewControllerDidFinish(_ controller: SFSafariViewController) {}
|
|
95
|
+
public func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) {}
|
|
96
|
+
public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {}
|
|
97
|
+
public func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) {}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// MARK: - Authentication sessions (deprecated)
|
|
101
|
+
|
|
102
|
+
/// `SFAuthenticationSession`, iOS 11's sign-in session, deprecated for
|
|
103
|
+
/// AuthenticationServices' `ASWebAuthenticationSession`: not here. An app
|
|
104
|
+
/// that still uses it fails to compile with this message.
|
|
105
|
+
@available(*, unavailable, message: "use AuthenticationServices' ASWebAuthenticationSession, which the browser has")
|
|
106
|
+
public final class SFAuthenticationSession {}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
// `import Security` for the browser: the keychain's item functions
|
|
2
|
+
// (`SecItemAdd`, `SecItemCopyMatching`, `SecItemUpdate`, `SecItemDelete`) over
|
|
3
|
+
// a store of generic and internet passwords. The store is a file in the app's
|
|
4
|
+
// home (`$HOME/Library/Keychains/keychain.json`, `/data` in the browser),
|
|
5
|
+
// which the page keeps across launches like the app's other files. That makes
|
|
6
|
+
// it as private as the rest of the page's storage for its origin, not
|
|
7
|
+
// encrypted, and with one access group: the app's.
|
|
8
|
+
//
|
|
9
|
+
// Queries are dictionaries keyed by the `kSec…` constants, as on Apple
|
|
10
|
+
// platforms, and the constants have Apple's values ("acct", "svce", …), so
|
|
11
|
+
// code that spells them as strings works too. Certificates, keys, identities
|
|
12
|
+
// and access control are not here.
|
|
13
|
+
|
|
14
|
+
import Foundation
|
|
15
|
+
// `OSStatus`, `CFString`, `CFDictionary`…
|
|
16
|
+
@_exported import CoreFoundationTypes
|
|
17
|
+
|
|
18
|
+
public let errSecSuccess: OSStatus = 0
|
|
19
|
+
public let noErr: OSStatus = 0
|
|
20
|
+
public let errSecUnimplemented: OSStatus = -4
|
|
21
|
+
public let errSecParam: OSStatus = -50
|
|
22
|
+
public let errSecAllocate: OSStatus = -108
|
|
23
|
+
public let errSecDuplicateItem: OSStatus = -25299
|
|
24
|
+
public let errSecInvalidValue: OSStatus = -67695
|
|
25
|
+
public let errSecItemNotFound: OSStatus = -25300
|
|
26
|
+
public let errSecInteractionNotAllowed: OSStatus = -25308
|
|
27
|
+
public let errSecDecode: OSStatus = -26275
|
|
28
|
+
public let errSecAuthFailed: OSStatus = -25293
|
|
29
|
+
public let errSecMissingEntitlement: OSStatus = -34018
|
|
30
|
+
|
|
31
|
+
// Item classes.
|
|
32
|
+
public let kSecClass: CFString = "class"
|
|
33
|
+
public let kSecClassGenericPassword: CFString = "genp"
|
|
34
|
+
public let kSecClassInternetPassword: CFString = "inet"
|
|
35
|
+
|
|
36
|
+
// Attributes.
|
|
37
|
+
public let kSecAttrAccount: CFString = "acct"
|
|
38
|
+
public let kSecAttrService: CFString = "svce"
|
|
39
|
+
public let kSecAttrServer: CFString = "srvr"
|
|
40
|
+
public let kSecAttrProtocol: CFString = "ptcl"
|
|
41
|
+
public let kSecAttrPort: CFString = "port"
|
|
42
|
+
public let kSecAttrPath: CFString = "path"
|
|
43
|
+
public let kSecAttrLabel: CFString = "labl"
|
|
44
|
+
public let kSecAttrDescription: CFString = "desc"
|
|
45
|
+
public let kSecAttrComment: CFString = "icmt"
|
|
46
|
+
public let kSecAttrGeneric: CFString = "gena"
|
|
47
|
+
public let kSecAttrAccessGroup: CFString = "agrp"
|
|
48
|
+
public let kSecAttrSynchronizable: CFString = "sync"
|
|
49
|
+
public let kSecAttrSynchronizableAny: CFString = "syna"
|
|
50
|
+
public let kSecAttrCreationDate: CFString = "cdat"
|
|
51
|
+
public let kSecAttrModificationDate: CFString = "mdat"
|
|
52
|
+
public let kSecAttrAccessible: CFString = "pdmn"
|
|
53
|
+
public let kSecAttrAccessibleWhenUnlocked: CFString = "ak"
|
|
54
|
+
public let kSecAttrAccessibleAfterFirstUnlock: CFString = "ck"
|
|
55
|
+
public let kSecAttrAccessibleWhenUnlockedThisDeviceOnly: CFString = "aku"
|
|
56
|
+
public let kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: CFString = "cku"
|
|
57
|
+
public let kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: CFString = "akpu"
|
|
58
|
+
public let kSecAttrAccessibleAlways: CFString = "dk"
|
|
59
|
+
public let kSecAttrAccessibleAlwaysThisDeviceOnly: CFString = "dku"
|
|
60
|
+
|
|
61
|
+
// Values, returns and search.
|
|
62
|
+
public let kSecValueData: CFString = "v_Data"
|
|
63
|
+
public let kSecValueRef: CFString = "v_Ref"
|
|
64
|
+
public let kSecValuePersistentRef: CFString = "v_PersistentRef"
|
|
65
|
+
public let kSecReturnData: CFString = "r_Data"
|
|
66
|
+
public let kSecReturnAttributes: CFString = "r_Attributes"
|
|
67
|
+
public let kSecReturnRef: CFString = "r_Ref"
|
|
68
|
+
public let kSecReturnPersistentRef: CFString = "r_PersistentRef"
|
|
69
|
+
public let kSecMatchLimit: CFString = "m_Limit"
|
|
70
|
+
public let kSecMatchLimitOne: CFString = "m_LimitOne"
|
|
71
|
+
public let kSecMatchLimitAll: CFString = "m_LimitAll"
|
|
72
|
+
public let kSecUseDataProtectionKeychain: CFString = "nleg"
|
|
73
|
+
public let kSecUseAuthenticationUI: CFString = "u_AuthUI"
|
|
74
|
+
|
|
75
|
+
/// Adds an item; `result` receives what the attributes' `kSecReturn…` keys ask for.
|
|
76
|
+
public func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus {
|
|
77
|
+
_Keychain.shared.add(attributes, result)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Finds the items matching the query; `result` receives what its `kSecReturn…` keys ask for.
|
|
81
|
+
public func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus {
|
|
82
|
+
_Keychain.shared.copyMatching(query, result)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Changes the attributes (and data) of every item matching the query.
|
|
86
|
+
public func SecItemUpdate(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus {
|
|
87
|
+
_Keychain.shared.update(query, attributesToUpdate)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Deletes every item matching the query.
|
|
91
|
+
public func SecItemDelete(_ query: CFDictionary) -> OSStatus {
|
|
92
|
+
_Keychain.shared.delete(query)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public func SecCopyErrorMessageString(_ status: OSStatus, _ reserved: UnsafeMutableRawPointer?) -> CFString? {
|
|
96
|
+
switch status {
|
|
97
|
+
case errSecSuccess: "No error."
|
|
98
|
+
case errSecParam: "One or more parameters passed to a function were not valid."
|
|
99
|
+
case errSecDuplicateItem: "The specified item already exists in the keychain."
|
|
100
|
+
case errSecItemNotFound: "The specified item could not be found in the keychain."
|
|
101
|
+
case errSecUnimplemented: "Function or operation not implemented."
|
|
102
|
+
case errSecDecode: "Unable to decode the provided data."
|
|
103
|
+
default: "OSStatus \(status)"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// The keychain's items, kept in a file in the app's home.
|
|
108
|
+
final class _Keychain: @unchecked Sendable {
|
|
109
|
+
nonisolated(unsafe) static var shared = _Keychain(file: _Keychain.defaultFile)
|
|
110
|
+
|
|
111
|
+
static var defaultFile: URL {
|
|
112
|
+
let home = ProcessInfo.processInfo.environment["HOME"].flatMap { $0.hasPrefix("/") ? $0 : nil } ?? "/data"
|
|
113
|
+
return URL(fileURLWithPath: home).appendingPathComponent("Library/Keychains/keychain.json")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// The attributes an item is matched on and returns, besides its data.
|
|
117
|
+
static let attributeKeys: Set<String> = [
|
|
118
|
+
kSecClass, kSecAttrAccount, kSecAttrService, kSecAttrServer, kSecAttrProtocol, kSecAttrPort, kSecAttrPath,
|
|
119
|
+
kSecAttrLabel, kSecAttrDescription, kSecAttrComment, kSecAttrGeneric, kSecAttrAccessGroup,
|
|
120
|
+
kSecAttrSynchronizable, kSecAttrAccessible,
|
|
121
|
+
]
|
|
122
|
+
static let classes: Set<String> = [kSecClassGenericPassword, kSecClassInternetPassword]
|
|
123
|
+
/// The access group of items added without one.
|
|
124
|
+
static let defaultGroup = "app"
|
|
125
|
+
|
|
126
|
+
struct Item: Codable {
|
|
127
|
+
var id: Int
|
|
128
|
+
var attributes: [String: _Value]
|
|
129
|
+
var data: Data?
|
|
130
|
+
var created: Double
|
|
131
|
+
var modified: Double
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// An attribute value the store keeps: what the attributes Apple defines can hold.
|
|
135
|
+
enum _Value: Codable, Equatable {
|
|
136
|
+
case string(String), number(Double), bool(Bool), data(Data)
|
|
137
|
+
|
|
138
|
+
init?(_ value: Any) {
|
|
139
|
+
switch value {
|
|
140
|
+
case let v as String: self = .string(v)
|
|
141
|
+
case let v as Bool: self = .bool(v)
|
|
142
|
+
case let v as Int: self = .number(Double(v))
|
|
143
|
+
case let v as Double: self = .number(v)
|
|
144
|
+
case let v as Data: self = .data(v)
|
|
145
|
+
default: return nil
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
var any: Any {
|
|
150
|
+
switch self {
|
|
151
|
+
case .string(let v): v
|
|
152
|
+
case .number(let v): v == v.rounded() ? Int(v) as Any : v as Any
|
|
153
|
+
case .bool(let v): v
|
|
154
|
+
case .data(let v): v
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
struct Store: Codable {
|
|
160
|
+
var nextID = 1
|
|
161
|
+
var items: [Item] = []
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let file: URL
|
|
165
|
+
private var loaded: Store?
|
|
166
|
+
|
|
167
|
+
init(file: URL) { self.file = file }
|
|
168
|
+
|
|
169
|
+
private var store: Store {
|
|
170
|
+
get {
|
|
171
|
+
if let loaded { return loaded }
|
|
172
|
+
let read = (try? Data(contentsOf: file)).flatMap { try? JSONDecoder().decode(Store.self, from: $0) } ?? Store()
|
|
173
|
+
loaded = read
|
|
174
|
+
return read
|
|
175
|
+
}
|
|
176
|
+
set {
|
|
177
|
+
loaded = newValue
|
|
178
|
+
try? FileManager.default.createDirectory(at: file.deletingLastPathComponent(), withIntermediateDirectories: true)
|
|
179
|
+
if let data = try? JSONEncoder().encode(newValue) { try? data.write(to: file) }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// MARK: Item functions
|
|
184
|
+
|
|
185
|
+
func add(_ attributes: [String: Any], _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus {
|
|
186
|
+
guard let itemClass = attributes[kSecClass] as? String, Self.classes.contains(itemClass) else { return errSecParam }
|
|
187
|
+
var values: [String: _Value] = [:]
|
|
188
|
+
for (key, value) in attributes where Self.attributeKeys.contains(key) {
|
|
189
|
+
guard let stored = _Value(value) else { return errSecParam }
|
|
190
|
+
values[key] = stored
|
|
191
|
+
}
|
|
192
|
+
values[kSecAttrAccessGroup] = values[kSecAttrAccessGroup] ?? .string(Self.defaultGroup)
|
|
193
|
+
values[kSecAttrSynchronizable] = .bool(Self.isTrue(attributes[kSecAttrSynchronizable]))
|
|
194
|
+
values[kSecAttrAccessible] = values[kSecAttrAccessible] ?? .string(kSecAttrAccessibleWhenUnlocked)
|
|
195
|
+
var store = self.store
|
|
196
|
+
if store.items.contains(where: { Self.sameIdentity($0.attributes, values) }) { return errSecDuplicateItem }
|
|
197
|
+
let now = Date().timeIntervalSince1970
|
|
198
|
+
let item = Item(id: store.nextID, attributes: values, data: attributes[kSecValueData] as? Data, created: now, modified: now)
|
|
199
|
+
store.nextID += 1
|
|
200
|
+
store.items.append(item)
|
|
201
|
+
self.store = store
|
|
202
|
+
if let result { result.pointee = Self.answer([item], to: attributes, one: true) }
|
|
203
|
+
return errSecSuccess
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
func copyMatching(_ query: [String: Any], _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus {
|
|
207
|
+
guard query[kSecClass] is String else { return errSecParam }
|
|
208
|
+
let one = (query[kSecMatchLimit] as? String) != kSecMatchLimitAll
|
|
209
|
+
var found = store.items.filter { Self.matches($0, query) }
|
|
210
|
+
if found.isEmpty { return errSecItemNotFound }
|
|
211
|
+
if one { found = [found[0]] }
|
|
212
|
+
if let result { result.pointee = Self.answer(found, to: query, one: one) }
|
|
213
|
+
return errSecSuccess
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
func update(_ query: [String: Any], _ changes: [String: Any]) -> OSStatus {
|
|
217
|
+
guard query[kSecClass] is String else { return errSecParam }
|
|
218
|
+
var store = self.store
|
|
219
|
+
let indices = store.items.indices.filter { Self.matches(store.items[$0], query) }
|
|
220
|
+
if indices.isEmpty { return errSecItemNotFound }
|
|
221
|
+
let now = Date().timeIntervalSince1970
|
|
222
|
+
for index in indices {
|
|
223
|
+
for (key, value) in changes {
|
|
224
|
+
if key == kSecValueData {
|
|
225
|
+
store.items[index].data = value as? Data
|
|
226
|
+
} else if Self.attributeKeys.contains(key), key != kSecClass {
|
|
227
|
+
guard let stored = key == kSecAttrSynchronizable ? .bool(Self.isTrue(value)) : _Value(value) else { return errSecParam }
|
|
228
|
+
store.items[index].attributes[key] = stored
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
store.items[index].modified = now
|
|
232
|
+
}
|
|
233
|
+
// An update must not make two items the same.
|
|
234
|
+
for index in indices {
|
|
235
|
+
let item = store.items[index]
|
|
236
|
+
if store.items.contains(where: { $0.id != item.id && Self.sameIdentity($0.attributes, item.attributes) }) {
|
|
237
|
+
return errSecDuplicateItem
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
self.store = store
|
|
241
|
+
return errSecSuccess
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
func delete(_ query: [String: Any]) -> OSStatus {
|
|
245
|
+
guard query[kSecClass] is String else { return errSecParam }
|
|
246
|
+
var store = self.store
|
|
247
|
+
let before = store.items.count
|
|
248
|
+
store.items.removeAll { Self.matches($0, query) }
|
|
249
|
+
if store.items.count == before { return errSecItemNotFound }
|
|
250
|
+
self.store = store
|
|
251
|
+
return errSecSuccess
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// MARK: Matching
|
|
255
|
+
|
|
256
|
+
static func isTrue(_ value: Any?) -> Bool {
|
|
257
|
+
switch value {
|
|
258
|
+
case let v as Bool: v
|
|
259
|
+
case let v as Int: v != 0
|
|
260
|
+
case let v as String: v == "1" || v == "true"
|
|
261
|
+
default: false
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/// Whether the item has the query's attributes. Without
|
|
266
|
+
/// `kSecAttrSynchronizable` a query finds the items that do not
|
|
267
|
+
/// synchronize; `kSecAttrSynchronizableAny` finds both.
|
|
268
|
+
static func matches(_ item: Item, _ query: [String: Any]) -> Bool {
|
|
269
|
+
if let ref = query[kSecValuePersistentRef] as? Data, ref != persistentRef(item) { return false }
|
|
270
|
+
for (key, value) in query where attributeKeys.contains(key) && key != kSecAttrSynchronizable && key != kSecAttrAccessible {
|
|
271
|
+
guard let wanted = _Value(value), item.attributes[key] == wanted else { return false }
|
|
272
|
+
}
|
|
273
|
+
let synchronizes = item.attributes[kSecAttrSynchronizable] == .bool(true)
|
|
274
|
+
switch query[kSecAttrSynchronizable] {
|
|
275
|
+
case let any as String where any == kSecAttrSynchronizableAny: return true
|
|
276
|
+
case let value?: return isTrue(value) == synchronizes
|
|
277
|
+
case nil: return !synchronizes
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/// Two items are the same item when their class and primary key attributes match.
|
|
282
|
+
static func sameIdentity(_ a: [String: _Value], _ b: [String: _Value]) -> Bool {
|
|
283
|
+
let keys = [kSecClass, kSecAttrAccount, kSecAttrService, kSecAttrServer, kSecAttrProtocol, kSecAttrPort, kSecAttrPath,
|
|
284
|
+
kSecAttrAccessGroup, kSecAttrSynchronizable]
|
|
285
|
+
return keys.allSatisfy { a[$0] == b[$0] }
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
static func persistentRef(_ item: Item) -> Data { Data("keychain-item-\(item.id)".utf8) }
|
|
289
|
+
|
|
290
|
+
/// What the query's `kSecReturn…` keys ask for: the data, a persistent
|
|
291
|
+
/// reference, or a dictionary of attributes (with those when asked too);
|
|
292
|
+
/// an array of them when the match limit is all.
|
|
293
|
+
static func answer(_ items: [Item], to query: [String: Any], one: Bool) -> CFTypeRef? {
|
|
294
|
+
let wantsData = isTrue(query[kSecReturnData])
|
|
295
|
+
let wantsAttributes = isTrue(query[kSecReturnAttributes])
|
|
296
|
+
let wantsRef = isTrue(query[kSecReturnPersistentRef]) || isTrue(query[kSecReturnRef])
|
|
297
|
+
func value(of item: Item) -> Any? {
|
|
298
|
+
if wantsAttributes {
|
|
299
|
+
var dictionary: [String: Any] = item.attributes.mapValues(\.any)
|
|
300
|
+
dictionary[kSecAttrCreationDate] = Date(timeIntervalSince1970: item.created)
|
|
301
|
+
dictionary[kSecAttrModificationDate] = Date(timeIntervalSince1970: item.modified)
|
|
302
|
+
if wantsData { dictionary[kSecValueData] = item.data ?? Data() }
|
|
303
|
+
if wantsRef { dictionary[kSecValuePersistentRef] = persistentRef(item) }
|
|
304
|
+
return dictionary
|
|
305
|
+
}
|
|
306
|
+
if wantsData { return item.data ?? Data() }
|
|
307
|
+
if wantsRef { return persistentRef(item) }
|
|
308
|
+
return nil
|
|
309
|
+
}
|
|
310
|
+
if one { return items.first.flatMap(value(of:)).map { $0 as AnyObject } }
|
|
311
|
+
// Typed arrays, so `result as? [[String: Any]]` (or `[Data]`) reads them back.
|
|
312
|
+
if wantsAttributes { return items.compactMap { value(of: $0) as? [String: Any] } as AnyObject }
|
|
313
|
+
if wantsData || wantsRef { return items.compactMap { value(of: $0) as? Data } as AnyObject }
|
|
314
|
+
return nil
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// MARK: - Randomness
|
|
319
|
+
|
|
320
|
+
/// A random number generator; the default one is the only one.
|
|
321
|
+
public typealias SecRandomRef = OpaquePointer
|
|
322
|
+
nonisolated(unsafe) public let kSecRandomDefault: SecRandomRef? = nil
|
|
323
|
+
|
|
324
|
+
/// Fills `bytes` with `count` cryptographically secure random bytes (the
|
|
325
|
+
/// system's generator: `crypto.getRandomValues` in the browser). On Apple
|
|
326
|
+
/// platforms Foundation brings this along, and FoundationBridge re-exports it.
|
|
327
|
+
public func SecRandomCopyBytes(_ rnd: SecRandomRef?, _ count: Int, _ bytes: UnsafeMutableRawPointer) -> Int32 {
|
|
328
|
+
var generator = SystemRandomNumberGenerator()
|
|
329
|
+
let buffer = bytes.bindMemory(to: UInt8.self, capacity: count)
|
|
330
|
+
for index in 0..<count { buffer[index] = generator.next() }
|
|
331
|
+
return errSecSuccess
|
|
332
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// StoreKit 2's App Store: whether payments can be made, the storefront,
|
|
2
|
+
// StoreKit's errors, purchase intents, App Store messages, external purchase
|
|
3
|
+
// links and the sheets StoreKit presents. A web app has no App Store behind
|
|
4
|
+
// it: payments cannot be made, the storefront is unknown, no intents or
|
|
5
|
+
// messages arrive (their sequences end at once), external purchase links
|
|
6
|
+
// are not eligible, and the sheets (manage subscriptions, redeem an offer
|
|
7
|
+
// code) are not shown: the calls that present them fail with
|
|
8
|
+
// `StoreKitError.unsupported`.
|
|
9
|
+
|
|
10
|
+
import Foundation
|
|
11
|
+
import SwiftUI
|
|
12
|
+
// As on iOS, StoreKit brings UIKit along: its sheets present in UIKit's scenes.
|
|
13
|
+
@_exported import UIKit
|
|
14
|
+
|
|
15
|
+
/// The scene StoreKit presents its sheets in.
|
|
16
|
+
public typealias _StoreKitScene = UIWindowScene
|
|
17
|
+
|
|
18
|
+
/// The App Store, as far as the browser has one.
|
|
19
|
+
public enum AppStore {
|
|
20
|
+
/// The environment a transaction happened in.
|
|
21
|
+
public struct Environment: Hashable, Sendable, RawRepresentable {
|
|
22
|
+
public let rawValue: String
|
|
23
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
24
|
+
public static let production = Environment(rawValue: "Production")
|
|
25
|
+
public static let sandbox = Environment(rawValue: "Sandbox")
|
|
26
|
+
public static let xcode = Environment(rawValue: "Xcode")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// The platform an app was first bought on.
|
|
30
|
+
public struct Platform: Hashable, Sendable, RawRepresentable {
|
|
31
|
+
public let rawValue: String
|
|
32
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
33
|
+
public static let iOS = Platform(rawValue: "iOS")
|
|
34
|
+
public static let macOS = Platform(rawValue: "macOS")
|
|
35
|
+
public static let tvOS = Platform(rawValue: "tvOS")
|
|
36
|
+
public static let visionOS = Platform(rawValue: "visionOS")
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// False: the browser has no App Store to pay through.
|
|
40
|
+
public static var canMakePayments: Bool { false }
|
|
41
|
+
|
|
42
|
+
/// The device's identifier for verifying transactions: none in the browser.
|
|
43
|
+
public static var deviceVerificationID: UUID? { nil }
|
|
44
|
+
|
|
45
|
+
/// Nothing to sync with; returns at once.
|
|
46
|
+
public static func sync() async throws {}
|
|
47
|
+
|
|
48
|
+
/// The manage-subscriptions sheet does not exist in the browser: throws
|
|
49
|
+
/// `StoreKitError.unsupported`.
|
|
50
|
+
@MainActor public static func showManageSubscriptions(in scene: UIWindowScene) async throws {
|
|
51
|
+
throw StoreKitError.unsupported
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@MainActor public static func showManageSubscriptions(in scene: UIWindowScene, subscriptionGroupID: String) async throws {
|
|
55
|
+
throw StoreKitError.unsupported
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// The offer-code sheet does not exist in the browser: throws
|
|
59
|
+
/// `StoreKitError.unsupported`.
|
|
60
|
+
@MainActor public static func presentOfferCodeRedeemSheet(in scene: UIWindowScene) async throws {
|
|
61
|
+
throw StoreKitError.unsupported
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Asks for a review: a no-op, as `requestReview` is.
|
|
65
|
+
@MainActor public static func requestReview(in scene: UIWindowScene) {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// The App Store region. The browser's is unknown: `current` is nil and
|
|
69
|
+
/// `updates` ends at once.
|
|
70
|
+
public struct Storefront: Identifiable, Hashable, Sendable {
|
|
71
|
+
public let countryCode: String
|
|
72
|
+
public let id: String
|
|
73
|
+
public var currency: Locale.Currency? { nil }
|
|
74
|
+
|
|
75
|
+
public static var current: Storefront? { get async { nil } }
|
|
76
|
+
|
|
77
|
+
public static var updates: Storefronts { Storefronts() }
|
|
78
|
+
|
|
79
|
+
public struct Storefronts: AsyncSequence, Sendable {
|
|
80
|
+
public typealias Element = Storefront
|
|
81
|
+
public struct AsyncIterator: AsyncIteratorProtocol {
|
|
82
|
+
public mutating func next() async -> Storefront? { nil }
|
|
83
|
+
}
|
|
84
|
+
public func makeAsyncIterator() -> AsyncIterator { AsyncIterator() }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// StoreKit 2's errors.
|
|
89
|
+
public enum StoreKitError: LocalizedError, Sendable {
|
|
90
|
+
case unknown
|
|
91
|
+
case userCancelled
|
|
92
|
+
case networkError(URLError)
|
|
93
|
+
case systemError(any Error)
|
|
94
|
+
case notAvailableInStorefront
|
|
95
|
+
case notEntitled
|
|
96
|
+
case unsupported
|
|
97
|
+
case invalidPresentationContext
|
|
98
|
+
|
|
99
|
+
public var errorDescription: String? {
|
|
100
|
+
switch self {
|
|
101
|
+
case .unknown: "An unknown error occurred."
|
|
102
|
+
case .userCancelled: "The user cancelled."
|
|
103
|
+
case .networkError(let error): error.localizedDescription
|
|
104
|
+
case .systemError(let error): error.localizedDescription
|
|
105
|
+
case .notAvailableInStorefront: "The item is not available in this storefront."
|
|
106
|
+
case .notEntitled: "The app is not entitled to this."
|
|
107
|
+
case .unsupported: "The App Store is not available in the browser."
|
|
108
|
+
case .invalidPresentationContext: "There is no context to present the App Store's sheet in."
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// A purchase someone started on the App Store, outside the app. None
|
|
114
|
+
/// arrive in the browser: `intents` ends at once.
|
|
115
|
+
public struct PurchaseIntent: Identifiable, Equatable, Sendable {
|
|
116
|
+
public let product: Product
|
|
117
|
+
public let offer: Product.SubscriptionOffer?
|
|
118
|
+
public var id: Product.ID { product.id }
|
|
119
|
+
|
|
120
|
+
public static var intents: PurchaseIntents { PurchaseIntents() }
|
|
121
|
+
|
|
122
|
+
public struct PurchaseIntents: AsyncSequence, Sendable {
|
|
123
|
+
public typealias Element = PurchaseIntent
|
|
124
|
+
public struct AsyncIterator: AsyncIteratorProtocol {
|
|
125
|
+
public mutating func next() async -> PurchaseIntent? { nil }
|
|
126
|
+
}
|
|
127
|
+
public func makeAsyncIterator() -> AsyncIterator { AsyncIterator() }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// A message the App Store wants to show (a price increase, a billing
|
|
132
|
+
/// issue). None arrive in the browser: `messages` ends at once.
|
|
133
|
+
public struct Message: Hashable, Sendable {
|
|
134
|
+
public struct Reason: Hashable, Sendable, RawRepresentable {
|
|
135
|
+
public let rawValue: String
|
|
136
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
137
|
+
public static let generic = Reason(rawValue: "generic")
|
|
138
|
+
public static let priceIncreaseConsent = Reason(rawValue: "priceIncreaseConsent")
|
|
139
|
+
public static let billingIssue = Reason(rawValue: "billingIssue")
|
|
140
|
+
public static let winBackOffer = Reason(rawValue: "winBackOffer")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public let reason: Reason
|
|
144
|
+
|
|
145
|
+
@MainActor public func display(in scene: UIWindowScene) throws {
|
|
146
|
+
throw StoreKitError.unsupported
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public static var messages: Messages { Messages() }
|
|
150
|
+
|
|
151
|
+
public struct Messages: AsyncSequence, Sendable {
|
|
152
|
+
public typealias Element = Message
|
|
153
|
+
public struct AsyncIterator: AsyncIteratorProtocol {
|
|
154
|
+
public mutating func next() async -> Message? { nil }
|
|
155
|
+
}
|
|
156
|
+
public func makeAsyncIterator() -> AsyncIterator { AsyncIterator() }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Shows an App Store message over the current scene (iOS 16), from the
|
|
161
|
+
/// environment's `displayStoreKitMessage`. No message arrives in the
|
|
162
|
+
/// browser; one passed in is not shown, which is not an error.
|
|
163
|
+
public struct DisplayMessageAction: Sendable {
|
|
164
|
+
public init() {}
|
|
165
|
+
|
|
166
|
+
@MainActor public func callAsFunction(_ message: Message) throws {}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private struct _DisplayStoreKitMessageKey: EnvironmentKey {
|
|
170
|
+
static let defaultValue = DisplayMessageAction()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
extension EnvironmentValues {
|
|
174
|
+
public var displayStoreKitMessage: DisplayMessageAction {
|
|
175
|
+
get { self[_DisplayStoreKitMessageKey.self] }
|
|
176
|
+
set { self[_DisplayStoreKitMessageKey.self] = newValue }
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/// Links to buying outside the App Store (iOS 18.1). A web app is not
|
|
181
|
+
/// eligible: `isEligible` is false and the notice and tokens are unsupported.
|
|
182
|
+
public enum ExternalPurchaseCustomLink {
|
|
183
|
+
public struct NoticeType: Hashable, Sendable, RawRepresentable {
|
|
184
|
+
public let rawValue: String
|
|
185
|
+
public init(rawValue: String) { self.rawValue = rawValue }
|
|
186
|
+
public static let browser = NoticeType(rawValue: "browser")
|
|
187
|
+
public static let withinApp = NoticeType(rawValue: "withinApp")
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public enum NoticeResult: Hashable, Sendable {
|
|
191
|
+
case continued, cancelled
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public struct Token: Hashable, Sendable {
|
|
195
|
+
public let value: String
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public static var isEligible: Bool { get async { false } }
|
|
199
|
+
|
|
200
|
+
public static func token(for tokenType: String) async throws -> Token? {
|
|
201
|
+
throw StoreKitError.unsupported
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@MainActor public static func showNotice(type: NoticeType) async throws -> NoticeResult {
|
|
205
|
+
throw StoreKitError.unsupported
|
|
206
|
+
}
|
|
207
|
+
}
|