@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,256 @@
|
|
|
1
|
+
// SwiftData in views: `@Query`, the `modelContext` environment value and the
|
|
2
|
+
// `.modelContainer` / `.modelContext` modifiers for views and scenes.
|
|
3
|
+
|
|
4
|
+
import Foundation
|
|
5
|
+
import Observation
|
|
6
|
+
import SwiftUI
|
|
7
|
+
|
|
8
|
+
/// What to fetch: a predicate, a sort order and a window of the results.
|
|
9
|
+
public struct FetchDescriptor<T: PersistentModel> {
|
|
10
|
+
public var predicate: Predicate<T>?
|
|
11
|
+
public var sortBy: [SortDescriptor<T>]
|
|
12
|
+
public var fetchLimit: Int?
|
|
13
|
+
public var fetchOffset: Int?
|
|
14
|
+
public var includePendingChanges = true
|
|
15
|
+
public var propertiesToFetch: [PartialKeyPath<T>] = []
|
|
16
|
+
public var relationshipKeyPathsForPrefetching: [PartialKeyPath<T>] = []
|
|
17
|
+
|
|
18
|
+
public init(predicate: Predicate<T>? = nil, sortBy: [SortDescriptor<T>] = []) {
|
|
19
|
+
self.predicate = predicate
|
|
20
|
+
self.sortBy = sortBy
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// MARK: - Environment
|
|
25
|
+
|
|
26
|
+
private enum _ModelContextKey: EnvironmentKey {
|
|
27
|
+
static var defaultValue: ModelContext { _ModelContextFallback.context }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// What `modelContext` is outside any `.modelContainer`: an empty in-memory
|
|
31
|
+
/// container's context, as in SwiftUI.
|
|
32
|
+
@MainActor
|
|
33
|
+
enum _ModelContextFallback {
|
|
34
|
+
nonisolated(unsafe) private static var shared: ModelContext?
|
|
35
|
+
|
|
36
|
+
nonisolated static var context: ModelContext {
|
|
37
|
+
if let shared { return shared }
|
|
38
|
+
let container = try! ModelContainer(for: Schema([]), configurations: [ModelConfiguration(isStoredInMemoryOnly: true)])
|
|
39
|
+
let context = ModelContext(container)
|
|
40
|
+
shared = context
|
|
41
|
+
return context
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
extension EnvironmentValues {
|
|
46
|
+
/// The context `@Query` fetches from and views insert into.
|
|
47
|
+
public var modelContext: ModelContext {
|
|
48
|
+
get { self[_ModelContextKey.self] }
|
|
49
|
+
set { self[_ModelContextKey.self] = newValue }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// MARK: - @Query
|
|
54
|
+
|
|
55
|
+
/// The models a fetch returns, kept current: the view re-runs when its
|
|
56
|
+
/// context changes (an insert, a delete, a property set, a save).
|
|
57
|
+
///
|
|
58
|
+
/// `Result` is always `[Element]`; tying the two lets `@Query var books: [Book]`
|
|
59
|
+
/// declare the wrapper with no initial value and assign it in `init`.
|
|
60
|
+
@propertyWrapper
|
|
61
|
+
public struct Query<Element: PersistentModel, Result>: DynamicProperty where Result: Sequence, Result.Element == Element {
|
|
62
|
+
let descriptor: FetchDescriptor<Element>
|
|
63
|
+
let animation: Animation?
|
|
64
|
+
let box = _QueryBox<Element>()
|
|
65
|
+
|
|
66
|
+
init(descriptor: FetchDescriptor<Element>, animation: Animation?) {
|
|
67
|
+
self.descriptor = descriptor
|
|
68
|
+
self.animation = animation
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// Every model of the type, unsorted. Declared here, without a
|
|
72
|
+
/// constraint, so that `@Query var items: [Item]` gives a view's
|
|
73
|
+
/// memberwise initializer a default for `items`, as Apple's does.
|
|
74
|
+
public init() {
|
|
75
|
+
self.init(descriptor: FetchDescriptor(), animation: nil)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public var wrappedValue: Result { box.results(for: descriptor) as! Result }
|
|
79
|
+
|
|
80
|
+
/// The error of the last fetch, if it failed.
|
|
81
|
+
public var fetchError: (any Error)? { box.error }
|
|
82
|
+
|
|
83
|
+
/// The context the query fetches from.
|
|
84
|
+
public var modelContext: ModelContext { box.context ?? _ModelContextFallback.context }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
extension Query: _EnvironmentReading {
|
|
88
|
+
public func _resolve(in environment: EnvironmentValues) {
|
|
89
|
+
box.context = environment.modelContext
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
extension Query where Result == [Element] {
|
|
94
|
+
|
|
95
|
+
public init(_ descriptor: FetchDescriptor<Element>, animation: Animation = .default) {
|
|
96
|
+
self.init(descriptor: descriptor, animation: animation)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public init(_ descriptor: FetchDescriptor<Element>, transaction: Transaction?) {
|
|
100
|
+
self.init(descriptor: descriptor, animation: nil)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public init(filter: Predicate<Element>? = nil, sort: [SortDescriptor<Element>] = [], animation: Animation = .default) {
|
|
104
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: sort), animation: animation)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public init(filter: Predicate<Element>? = nil, sort: [SortDescriptor<Element>] = [], transaction: Transaction?) {
|
|
108
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: sort), animation: nil)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public init(filter: Predicate<Element>? = nil, sort: SortDescriptor<Element>, animation: Animation = .default) {
|
|
112
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: [sort]), animation: animation)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public init<Value: Comparable>(filter: Predicate<Element>? = nil, sort keyPath: any KeyPath<Element, Value> & Sendable, order: SortOrder = .forward, animation: Animation = .default) {
|
|
116
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: [SortDescriptor(keyPath, order: order)]), animation: animation)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public init<Value: Comparable>(filter: Predicate<Element>? = nil, sort keyPath: any KeyPath<Element, Value?> & Sendable, order: SortOrder = .forward, animation: Animation = .default) {
|
|
120
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: [SortDescriptor(keyPath, order: order)]), animation: animation)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public init<Value: Comparable>(filter: Predicate<Element>? = nil, sort keyPath: any KeyPath<Element, Value> & Sendable, order: SortOrder = .forward, transaction: Transaction?) {
|
|
124
|
+
self.init(descriptor: FetchDescriptor(predicate: filter, sortBy: [SortDescriptor(keyPath, order: order)]), animation: nil)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// A query's context and its last results, which stay valid until the
|
|
129
|
+
/// context changes.
|
|
130
|
+
public final class _QueryBox<Element: PersistentModel> {
|
|
131
|
+
var context: ModelContext?
|
|
132
|
+
var error: (any Error)?
|
|
133
|
+
private var cached: [Element]?
|
|
134
|
+
private weak var cachedContext: ModelContext?
|
|
135
|
+
private var cachedGeneration = -1
|
|
136
|
+
|
|
137
|
+
func results(for descriptor: FetchDescriptor<Element>) -> [Element] {
|
|
138
|
+
let context = context ?? _ModelContextFallback.context
|
|
139
|
+
// Reading the generation makes the view's body depend on the context.
|
|
140
|
+
let generation = context.signal.generation
|
|
141
|
+
if let cached, cachedContext === context, cachedGeneration == generation { return cached }
|
|
142
|
+
let results: [Element]
|
|
143
|
+
do {
|
|
144
|
+
results = try context.fetch(descriptor)
|
|
145
|
+
error = nil
|
|
146
|
+
} catch {
|
|
147
|
+
self.error = error
|
|
148
|
+
results = []
|
|
149
|
+
}
|
|
150
|
+
cached = results
|
|
151
|
+
cachedContext = context
|
|
152
|
+
cachedGeneration = generation
|
|
153
|
+
return results
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// MARK: - Modifiers
|
|
158
|
+
|
|
159
|
+
/// Puts a container's main context into the environment.
|
|
160
|
+
struct _ModelContainerModifier: ViewModifier {
|
|
161
|
+
let context: ModelContext
|
|
162
|
+
|
|
163
|
+
func body(content: Content) -> some View {
|
|
164
|
+
content.environment(\.modelContext, context)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/// The containers `.modelContainer(for:)` made, so that a body that runs
|
|
169
|
+
/// again gets the same container.
|
|
170
|
+
@MainActor
|
|
171
|
+
enum _ModifierContainers {
|
|
172
|
+
private static var made: [String: ModelContainer] = [:]
|
|
173
|
+
|
|
174
|
+
static func container(for types: [any PersistentModel.Type], inMemory: Bool, autosave: Bool,
|
|
175
|
+
onSetup: (Result<ModelContainer, any Error>) -> Void) -> ModelContainer {
|
|
176
|
+
let key = types.map { String(reflecting: $0) }.sorted().joined(separator: ",") + (inMemory ? "|memory" : "")
|
|
177
|
+
if let container = made[key] { return container }
|
|
178
|
+
let container: ModelContainer
|
|
179
|
+
do {
|
|
180
|
+
container = try ModelContainer(for: Schema(types), configurations: [ModelConfiguration(isStoredInMemoryOnly: inMemory)])
|
|
181
|
+
onSetup(.success(container))
|
|
182
|
+
} catch {
|
|
183
|
+
onSetup(.failure(error))
|
|
184
|
+
container = try! ModelContainer(for: Schema(types), configurations: [ModelConfiguration(isStoredInMemoryOnly: true)])
|
|
185
|
+
}
|
|
186
|
+
container.mainContext.autosaveEnabled = autosave
|
|
187
|
+
made[key] = container
|
|
188
|
+
return container
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
extension View {
|
|
193
|
+
/// Supplies the container's main context to the views below.
|
|
194
|
+
public func modelContainer(_ container: ModelContainer) -> some View {
|
|
195
|
+
modifier(_ModelContainerModifier(context: container.mainContext))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Supplies a container for these model types (made once) to the views below.
|
|
199
|
+
public func modelContainer(
|
|
200
|
+
for modelType: any PersistentModel.Type,
|
|
201
|
+
inMemory: Bool = false,
|
|
202
|
+
isAutosaveEnabled: Bool = true,
|
|
203
|
+
isUndoEnabled: Bool = false,
|
|
204
|
+
onSetup: @escaping (Result<ModelContainer, any Error>) -> Void = { _ in }
|
|
205
|
+
) -> some View {
|
|
206
|
+
modelContainer(_ModifierContainers.container(for: [modelType], inMemory: inMemory, autosave: isAutosaveEnabled, onSetup: onSetup))
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public func modelContainer(
|
|
210
|
+
for modelTypes: [any PersistentModel.Type],
|
|
211
|
+
inMemory: Bool = false,
|
|
212
|
+
isAutosaveEnabled: Bool = true,
|
|
213
|
+
isUndoEnabled: Bool = false,
|
|
214
|
+
onSetup: @escaping (Result<ModelContainer, any Error>) -> Void = { _ in }
|
|
215
|
+
) -> some View {
|
|
216
|
+
modelContainer(_ModifierContainers.container(for: modelTypes, inMemory: inMemory, autosave: isAutosaveEnabled, onSetup: onSetup))
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/// Supplies a context to the views below.
|
|
220
|
+
public func modelContext(_ modelContext: ModelContext) -> some View {
|
|
221
|
+
modifier(_ModelContainerModifier(context: modelContext))
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
extension Scene {
|
|
226
|
+
/// Supplies the container's main context to the scene's views.
|
|
227
|
+
public func modelContainer(_ container: ModelContainer) -> some Scene {
|
|
228
|
+
_modifyingRootView(_ModelContainerModifier(context: container.mainContext))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Supplies a container for these model types to the scene's views.
|
|
232
|
+
public func modelContainer(
|
|
233
|
+
for modelType: any PersistentModel.Type,
|
|
234
|
+
inMemory: Bool = false,
|
|
235
|
+
isAutosaveEnabled: Bool = true,
|
|
236
|
+
isUndoEnabled: Bool = false,
|
|
237
|
+
onSetup: @escaping (Result<ModelContainer, any Error>) -> Void = { _ in }
|
|
238
|
+
) -> some Scene {
|
|
239
|
+
modelContainer(_ModifierContainers.container(for: [modelType], inMemory: inMemory, autosave: isAutosaveEnabled, onSetup: onSetup))
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public func modelContainer(
|
|
243
|
+
for modelTypes: [any PersistentModel.Type],
|
|
244
|
+
inMemory: Bool = false,
|
|
245
|
+
isAutosaveEnabled: Bool = true,
|
|
246
|
+
isUndoEnabled: Bool = false,
|
|
247
|
+
onSetup: @escaping (Result<ModelContainer, any Error>) -> Void = { _ in }
|
|
248
|
+
) -> some Scene {
|
|
249
|
+
modelContainer(_ModifierContainers.container(for: modelTypes, inMemory: inMemory, autosave: isAutosaveEnabled, onSetup: onSetup))
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/// Supplies a context to the scene's views.
|
|
253
|
+
public func modelContext(_ modelContext: ModelContext) -> some Scene {
|
|
254
|
+
_modifyingRootView(_ModelContainerModifier(context: modelContext))
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// The schema of a container: the model types, their persisted properties and
|
|
2
|
+
// the options `@Attribute` and `@Relationship` gave them. `@Model` generates
|
|
3
|
+
// each type's `schemaMetadata`; the store reads it to encode, decode and
|
|
4
|
+
// relate records.
|
|
5
|
+
|
|
6
|
+
import Foundation
|
|
7
|
+
|
|
8
|
+
public final class Schema: Hashable, @unchecked Sendable {
|
|
9
|
+
public struct Version: Hashable, Comparable, Codable, Sendable, CustomStringConvertible {
|
|
10
|
+
public let major: Int
|
|
11
|
+
public let minor: Int
|
|
12
|
+
public let patch: Int
|
|
13
|
+
|
|
14
|
+
public init(_ major: Int, _ minor: Int, _ patch: Int) {
|
|
15
|
+
self.major = major
|
|
16
|
+
self.minor = minor
|
|
17
|
+
self.patch = patch
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static func < (lhs: Version, rhs: Version) -> Bool {
|
|
21
|
+
(lhs.major, lhs.minor, lhs.patch) < (rhs.major, rhs.minor, rhs.patch)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public var description: String { "\(major).\(minor).\(patch)" }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// One model type of the schema.
|
|
28
|
+
public struct Entity: Hashable, @unchecked Sendable {
|
|
29
|
+
public let name: String
|
|
30
|
+
let type: any PersistentModel.Type
|
|
31
|
+
|
|
32
|
+
public var properties: [PropertyMetadata] { _Entity.of(type).properties }
|
|
33
|
+
|
|
34
|
+
public static func == (lhs: Entity, rhs: Entity) -> Bool { lhs.name == rhs.name }
|
|
35
|
+
public func hash(into hasher: inout Hasher) { hasher.combine(name) }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// A persisted property of a model, as `@Model` describes it.
|
|
39
|
+
public struct PropertyMetadata: @unchecked Sendable {
|
|
40
|
+
public let name: String
|
|
41
|
+
public let keypath: AnyKeyPath
|
|
42
|
+
public let defaultValue: Any?
|
|
43
|
+
/// The `Schema.Attribute` or `Schema.Relationship` the property was
|
|
44
|
+
/// declared with, if any.
|
|
45
|
+
public let metadata: Any?
|
|
46
|
+
let property: _Property
|
|
47
|
+
|
|
48
|
+
public init<Model: PersistentModel, Value>(name: String, keyPath: KeyPath<Model, Value>, defaultValue: Value? = nil, metadata: Any? = nil) {
|
|
49
|
+
self.name = name
|
|
50
|
+
keypath = keyPath
|
|
51
|
+
self.defaultValue = defaultValue
|
|
52
|
+
self.metadata = metadata
|
|
53
|
+
property = _Property(name: name, keyPath: keyPath, defaultValue: defaultValue, metadata: metadata)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Options of a persisted attribute.
|
|
58
|
+
public struct Attribute: @unchecked Sendable {
|
|
59
|
+
public struct Option: Hashable, Sendable {
|
|
60
|
+
let name: String
|
|
61
|
+
/// Records may not share a value: inserting a model whose value
|
|
62
|
+
/// another record has updates that record instead (an upsert).
|
|
63
|
+
public static let unique = Option(name: "unique")
|
|
64
|
+
public static let externalStorage = Option(name: "externalStorage")
|
|
65
|
+
public static let allowsCloudEncryption = Option(name: "allowsCloudEncryption")
|
|
66
|
+
public static let preserveValueOnDeletion = Option(name: "preserveValueOnDeletion")
|
|
67
|
+
public static let ephemeral = Option(name: "ephemeral")
|
|
68
|
+
public static let spotlight = Option(name: "spotlight")
|
|
69
|
+
public static func transformable(by transformerName: String) -> Option { Option(name: "transformable") }
|
|
70
|
+
public static func transformable(by transformerType: Any.Type) -> Option { Option(name: "transformable") }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public let options: [Option]
|
|
74
|
+
public let originalName: String?
|
|
75
|
+
public let hashModifier: String?
|
|
76
|
+
|
|
77
|
+
public init(_ options: Option..., originalName: String? = nil, hashModifier: String? = nil) {
|
|
78
|
+
self.options = options
|
|
79
|
+
self.originalName = originalName
|
|
80
|
+
self.hashModifier = hashModifier
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public var isUnique: Bool { options.contains(.unique) }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Options of a relationship between models.
|
|
87
|
+
public struct Relationship: @unchecked Sendable {
|
|
88
|
+
public enum DeleteRule: Hashable, Codable, Sendable {
|
|
89
|
+
/// Deleting the model deletes the related models.
|
|
90
|
+
case cascade
|
|
91
|
+
/// A model with related models cannot be deleted (its save fails).
|
|
92
|
+
case deny
|
|
93
|
+
/// Nothing happens to the related models.
|
|
94
|
+
case noAction
|
|
95
|
+
/// The related models stop referring to the deleted one.
|
|
96
|
+
case nullify
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public struct Option: Hashable, Sendable {
|
|
100
|
+
let name: String
|
|
101
|
+
public static let unique = Option(name: "unique")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public let options: [Option]
|
|
105
|
+
public let deleteRule: DeleteRule
|
|
106
|
+
public let minimumModelCount: Int?
|
|
107
|
+
public let maximumModelCount: Int?
|
|
108
|
+
public let originalName: String?
|
|
109
|
+
public let inverseKeyPath: AnyKeyPath?
|
|
110
|
+
public let hashModifier: String?
|
|
111
|
+
|
|
112
|
+
public init(
|
|
113
|
+
_ options: Option...,
|
|
114
|
+
deleteRule: DeleteRule = .nullify,
|
|
115
|
+
minimumModelCount: Int? = 0,
|
|
116
|
+
maximumModelCount: Int? = 0,
|
|
117
|
+
originalName: String? = nil,
|
|
118
|
+
inverse: AnyKeyPath? = nil,
|
|
119
|
+
hashModifier: String? = nil
|
|
120
|
+
) {
|
|
121
|
+
self.options = options
|
|
122
|
+
self.deleteRule = deleteRule
|
|
123
|
+
self.minimumModelCount = minimumModelCount
|
|
124
|
+
self.maximumModelCount = maximumModelCount
|
|
125
|
+
self.originalName = originalName
|
|
126
|
+
inverseKeyPath = inverse
|
|
127
|
+
self.hashModifier = hashModifier
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public let entities: [Entity]
|
|
132
|
+
public let version: Version
|
|
133
|
+
|
|
134
|
+
public init(_ types: [any PersistentModel.Type], version: Version = Version(1, 0, 0)) {
|
|
135
|
+
var seen = Set<ObjectIdentifier>()
|
|
136
|
+
var entities: [Entity] = []
|
|
137
|
+
// The listed types and every type they relate to, as SwiftData infers them.
|
|
138
|
+
var queue = types
|
|
139
|
+
while !queue.isEmpty {
|
|
140
|
+
let type = queue.removeFirst()
|
|
141
|
+
guard seen.insert(ObjectIdentifier(type)).inserted else { continue }
|
|
142
|
+
let entity = _Entity.of(type)
|
|
143
|
+
entities.append(Entity(name: entity.name, type: type))
|
|
144
|
+
queue += entity.properties.compactMap { $0.property.relatedType }
|
|
145
|
+
}
|
|
146
|
+
self.entities = entities
|
|
147
|
+
self.version = version
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public convenience init(_ types: any PersistentModel.Type..., version: Version = Version(1, 0, 0)) {
|
|
151
|
+
self.init(types, version: version)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public convenience init(versionedSchema: any VersionedSchema.Type) {
|
|
155
|
+
self.init(versionedSchema.models, version: versionedSchema.versionIdentifier)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public static func == (lhs: Schema, rhs: Schema) -> Bool { lhs.entities == rhs.entities && lhs.version == rhs.version }
|
|
159
|
+
public func hash(into hasher: inout Hasher) {
|
|
160
|
+
hasher.combine(entities)
|
|
161
|
+
hasher.combine(version)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public var entitiesByName: [String: Entity] {
|
|
165
|
+
Dictionary(entities.map { ($0.name, $0) }, uniquingKeysWith: { first, _ in first })
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/// A version of an app's schema, for migration plans.
|
|
170
|
+
public protocol VersionedSchema {
|
|
171
|
+
static var versionIdentifier: Schema.Version { get }
|
|
172
|
+
static var models: [any PersistentModel.Type] { get }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// How to migrate between versioned schemas. Records are decoded on demand
|
|
176
|
+
/// (a property missing from a record takes its initial value), which covers
|
|
177
|
+
/// what a lightweight migration does; custom stages' closures run against the
|
|
178
|
+
/// container's main context.
|
|
179
|
+
public protocol SchemaMigrationPlan {
|
|
180
|
+
static var schemas: [any VersionedSchema.Type] { get }
|
|
181
|
+
static var stages: [MigrationStage] { get }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public enum MigrationStage: @unchecked Sendable {
|
|
185
|
+
case lightweight(fromVersion: any VersionedSchema.Type, toVersion: any VersionedSchema.Type)
|
|
186
|
+
case custom(
|
|
187
|
+
fromVersion: any VersionedSchema.Type,
|
|
188
|
+
toVersion: any VersionedSchema.Type,
|
|
189
|
+
willMigrate: ((ModelContext) throws -> Void)?,
|
|
190
|
+
didMigrate: ((ModelContext) throws -> Void)?
|
|
191
|
+
)
|
|
192
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// A store: the saved records of one `ModelConfiguration`, kept in memory for
|
|
2
|
+
// the run. The page reads the app's IndexedDB database before it starts the
|
|
3
|
+
// module and hands every store in through `SB_SWIFTDATA`; each save sends
|
|
4
|
+
// what changed back as a `swiftdata` op, which the page writes to IndexedDB
|
|
5
|
+
// (docs/ops-protocol.md, "Phase 18"). Fetches are evaluated here, against
|
|
6
|
+
// the records and the contexts' unsaved changes, so they stay synchronous as
|
|
7
|
+
// SwiftData's are.
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import SwiftUI
|
|
11
|
+
|
|
12
|
+
/// A saved model: its entity name and its properties' JSON.
|
|
13
|
+
struct _Record: Equatable {
|
|
14
|
+
var entity: String
|
|
15
|
+
var values: [String: _JSON]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
final class _Store {
|
|
19
|
+
/// The store's name: the configuration URL's last path component
|
|
20
|
+
/// (`default.store`).
|
|
21
|
+
let identifier: String
|
|
22
|
+
/// Whether saves reach the host; in-memory stores keep nothing.
|
|
23
|
+
let persistent: Bool
|
|
24
|
+
private(set) var records: [Int64: _Record] = [:]
|
|
25
|
+
/// Record keys per entity, in insertion order.
|
|
26
|
+
private var keysByEntity: [String: [Int64]] = [:]
|
|
27
|
+
private var contexts: [_WeakContext] = []
|
|
28
|
+
|
|
29
|
+
private init(identifier: String, persistent: Bool, records: [Int64: _Record]) {
|
|
30
|
+
self.identifier = identifier
|
|
31
|
+
self.persistent = persistent
|
|
32
|
+
self.records = records
|
|
33
|
+
for key in records.keys.sorted() { keysByEntity[records[key]!.entity, default: []].append(key) }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// MARK: Opening
|
|
37
|
+
|
|
38
|
+
nonisolated(unsafe) private static var opened: [String: _Store] = [:]
|
|
39
|
+
|
|
40
|
+
/// The persistent store with this name (shared by every container that
|
|
41
|
+
/// opens it), or a new in-memory store.
|
|
42
|
+
static func open(identifier: String, inMemory: Bool) -> _Store {
|
|
43
|
+
if inMemory { return _Store(identifier: identifier, persistent: false, records: [:]) }
|
|
44
|
+
if let store = opened[identifier] { return store }
|
|
45
|
+
let store = _Store(identifier: identifier, persistent: true, records: launchRecords[identifier] ?? [:])
|
|
46
|
+
opened[identifier] = store
|
|
47
|
+
return store
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// The stores the host handed in (`SB_SWIFTDATA`):
|
|
51
|
+
/// `{"<store>": [{"id": 1, "entity": "Book", "values": {…}}, …]}`.
|
|
52
|
+
nonisolated(unsafe) private static var launchRecords: [String: [Int64: _Record]] = {
|
|
53
|
+
guard let text = _environment("SB_SWIFTDATA"), !text.isEmpty else { return [:] }
|
|
54
|
+
guard let json = try? _JSON.parse(text), case .object(let stores) = json else {
|
|
55
|
+
print("[SwiftData] ignoring malformed SB_SWIFTDATA")
|
|
56
|
+
return [:]
|
|
57
|
+
}
|
|
58
|
+
var result: [String: [Int64: _Record]] = [:]
|
|
59
|
+
for (name, items) in stores {
|
|
60
|
+
guard case .array(let items) = items else { continue }
|
|
61
|
+
var records: [Int64: _Record] = [:]
|
|
62
|
+
for item in items {
|
|
63
|
+
guard case .object(let fields) = item, case .number(let id)? = fields["id"],
|
|
64
|
+
case .string(let entity)? = fields["entity"] else { continue }
|
|
65
|
+
var values: [String: _JSON] = [:]
|
|
66
|
+
if case .object(let stored)? = fields["values"] { values = stored }
|
|
67
|
+
records[Int64(id)] = _Record(entity: entity, values: values)
|
|
68
|
+
}
|
|
69
|
+
result[name] = records
|
|
70
|
+
}
|
|
71
|
+
return result
|
|
72
|
+
}()
|
|
73
|
+
|
|
74
|
+
// MARK: Keys
|
|
75
|
+
|
|
76
|
+
/// Model keys are unique across every store of the app, increasing, and
|
|
77
|
+
/// continue after the largest key the host handed in.
|
|
78
|
+
nonisolated(unsafe) private static var nextPrimaryKey: Int64 = {
|
|
79
|
+
let largest = launchRecords.values.flatMap(\.keys).max() ?? 0
|
|
80
|
+
return largest + 1
|
|
81
|
+
}()
|
|
82
|
+
|
|
83
|
+
static func allocatePrimaryKey() -> Int64 {
|
|
84
|
+
defer { nextPrimaryKey += 1 }
|
|
85
|
+
return nextPrimaryKey
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Clears every opened store's in-memory state (tests).
|
|
89
|
+
static func _resetForTesting(launch: [String: [Int64: _Record]] = [:]) {
|
|
90
|
+
opened = [:]
|
|
91
|
+
launchRecords = launch
|
|
92
|
+
nextPrimaryKey = (launch.values.flatMap(\.keys).max() ?? 0) + 1
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// MARK: Reading
|
|
96
|
+
|
|
97
|
+
func keys(of entity: String) -> [Int64] { keysByEntity[entity] ?? [] }
|
|
98
|
+
|
|
99
|
+
func record(_ key: Int64) -> _Record? { records[key] }
|
|
100
|
+
|
|
101
|
+
// MARK: Contexts
|
|
102
|
+
|
|
103
|
+
func register(_ context: ModelContext) {
|
|
104
|
+
contexts.removeAll { $0.context == nil }
|
|
105
|
+
contexts.append(_WeakContext(context: context))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// MARK: Writing
|
|
109
|
+
|
|
110
|
+
/// Applies one save: `put` records (new or changed) and `delete` keys,
|
|
111
|
+
/// tells the host, and lets the store's other contexts catch up.
|
|
112
|
+
func commit(put: [(Int64, _Record)], delete: [Int64], clear: Bool = false, from origin: ModelContext?) {
|
|
113
|
+
if clear {
|
|
114
|
+
records.removeAll()
|
|
115
|
+
keysByEntity.removeAll()
|
|
116
|
+
}
|
|
117
|
+
for key in delete {
|
|
118
|
+
guard let removed = records.removeValue(forKey: key) else { continue }
|
|
119
|
+
keysByEntity[removed.entity]?.removeAll { $0 == key }
|
|
120
|
+
}
|
|
121
|
+
for (key, record) in put {
|
|
122
|
+
if records[key] == nil { keysByEntity[record.entity, default: []].append(key) }
|
|
123
|
+
records[key] = record
|
|
124
|
+
}
|
|
125
|
+
if persistent {
|
|
126
|
+
var change: [String: _JSON] = ["store": .string(identifier)]
|
|
127
|
+
if clear { change["clear"] = .bool(true) }
|
|
128
|
+
change["put"] = .array(put.map { key, record in
|
|
129
|
+
.object(["id": .number(Double(key)), "entity": .string(record.entity), "values": .object(record.values)])
|
|
130
|
+
})
|
|
131
|
+
change["delete"] = .array(delete.map { .number(Double($0)) })
|
|
132
|
+
let json = _JSON.object(change)
|
|
133
|
+
MainActor.assumeIsolated { _Runtime.shared.storeSwiftData(json) }
|
|
134
|
+
}
|
|
135
|
+
let changed = Set(put.map(\.0))
|
|
136
|
+
let deleted = Set(delete)
|
|
137
|
+
for weak in contexts {
|
|
138
|
+
guard let context = weak.context, context !== origin else { continue }
|
|
139
|
+
context._storeDidChange(changed: changed, deleted: deleted, cleared: clear)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
struct _WeakContext {
|
|
145
|
+
weak var context: ModelContext?
|
|
146
|
+
}
|