@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,38 @@
|
|
|
1
|
+
// Model actors (`@ModelActor`, Macros.swift): an actor that works with a
|
|
2
|
+
// context of its own. Apple's runs on its model executor; here it runs on the
|
|
3
|
+
// main actor's executor, as everything in the browser runs on one thread, so
|
|
4
|
+
// the context (which, like the runtime, lives on the main actor) is used
|
|
5
|
+
// where it expects to be.
|
|
6
|
+
|
|
7
|
+
/// What runs a model actor's work: here, the holder of its context.
|
|
8
|
+
public protocol ModelExecutor: AnyObject, Sendable {
|
|
9
|
+
var modelContext: ModelContext { get }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/// The executor `@ModelActor` makes, holding the actor's context.
|
|
13
|
+
public final class DefaultSerialModelExecutor: ModelExecutor, @unchecked Sendable {
|
|
14
|
+
public let modelContext: ModelContext
|
|
15
|
+
|
|
16
|
+
public init(modelContext: ModelContext) {
|
|
17
|
+
self.modelContext = modelContext
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// An actor with a model container and a context of its own.
|
|
22
|
+
public protocol ModelActor: Actor {
|
|
23
|
+
nonisolated var modelContainer: ModelContainer { get }
|
|
24
|
+
nonisolated var modelExecutor: any ModelExecutor { get }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
extension ModelActor {
|
|
28
|
+
/// The main actor's executor (see the file comment).
|
|
29
|
+
public nonisolated var unownedExecutor: UnownedSerialExecutor { MainActor.sharedUnownedExecutor }
|
|
30
|
+
|
|
31
|
+
/// The actor's context, which its executor holds.
|
|
32
|
+
public var modelContext: ModelContext { modelExecutor.modelContext }
|
|
33
|
+
|
|
34
|
+
/// The model with `id` in the actor's context, if it is there.
|
|
35
|
+
public subscript<T: PersistentModel>(id: PersistentIdentifier, as type: T.Type) -> T? {
|
|
36
|
+
modelContext.registeredModel(for: id)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Containers and their configurations. A configuration names a store; a
|
|
2
|
+
// persistent store is saved to the page's IndexedDB (one database per app,
|
|
3
|
+
// docs/ops-protocol.md, "Phase 18"), an in-memory one keeps nothing.
|
|
4
|
+
|
|
5
|
+
import Foundation
|
|
6
|
+
import SwiftUI
|
|
7
|
+
|
|
8
|
+
/// Where and how a container stores its models.
|
|
9
|
+
public struct ModelConfiguration: Hashable, Identifiable, @unchecked Sendable {
|
|
10
|
+
public enum CloudKitDatabase: Hashable, Sendable {
|
|
11
|
+
case automatic
|
|
12
|
+
case none
|
|
13
|
+
case `private`(String)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public enum GroupContainer: Hashable, Sendable {
|
|
17
|
+
case automatic
|
|
18
|
+
case none
|
|
19
|
+
case identifier(String)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public var name: String
|
|
23
|
+
public var url: URL
|
|
24
|
+
public var isStoredInMemoryOnly: Bool
|
|
25
|
+
public var allowsSave: Bool
|
|
26
|
+
public var schema: Schema?
|
|
27
|
+
public var cloudKitDatabase: CloudKitDatabase
|
|
28
|
+
public var groupContainer: GroupContainer
|
|
29
|
+
|
|
30
|
+
public var id: String { name }
|
|
31
|
+
|
|
32
|
+
public init(
|
|
33
|
+
_ name: String? = nil,
|
|
34
|
+
schema: Schema? = nil,
|
|
35
|
+
isStoredInMemoryOnly: Bool = false,
|
|
36
|
+
allowsSave: Bool = true,
|
|
37
|
+
groupContainer: GroupContainer = .automatic,
|
|
38
|
+
cloudKitDatabase: CloudKitDatabase = .automatic
|
|
39
|
+
) {
|
|
40
|
+
let name = name ?? "default"
|
|
41
|
+
self.name = name
|
|
42
|
+
url = URL(fileURLWithPath: "/swiftdata/\(name).store")
|
|
43
|
+
self.isStoredInMemoryOnly = isStoredInMemoryOnly
|
|
44
|
+
self.allowsSave = allowsSave
|
|
45
|
+
self.schema = schema
|
|
46
|
+
self.cloudKitDatabase = cloudKitDatabase
|
|
47
|
+
self.groupContainer = groupContainer
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public init(
|
|
51
|
+
_ name: String? = nil,
|
|
52
|
+
schema: Schema? = nil,
|
|
53
|
+
url: URL,
|
|
54
|
+
allowsSave: Bool = true,
|
|
55
|
+
cloudKitDatabase: CloudKitDatabase = .automatic
|
|
56
|
+
) {
|
|
57
|
+
self.name = name ?? url.deletingPathExtension().lastPathComponent
|
|
58
|
+
self.url = url
|
|
59
|
+
isStoredInMemoryOnly = false
|
|
60
|
+
self.allowsSave = allowsSave
|
|
61
|
+
self.schema = schema
|
|
62
|
+
self.cloudKitDatabase = cloudKitDatabase
|
|
63
|
+
groupContainer = .automatic
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public init(for forTypes: any PersistentModel.Type..., isStoredInMemoryOnly: Bool = false) {
|
|
67
|
+
self.init(schema: Schema(forTypes), isStoredInMemoryOnly: isStoredInMemoryOnly)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public init(isStoredInMemoryOnly: Bool) {
|
|
71
|
+
self.init(nil, isStoredInMemoryOnly: isStoredInMemoryOnly)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// The name the store goes by in IndexedDB and in `swiftdata` ops.
|
|
75
|
+
var storeIdentifier: String { url.lastPathComponent }
|
|
76
|
+
|
|
77
|
+
public static func == (lhs: ModelConfiguration, rhs: ModelConfiguration) -> Bool {
|
|
78
|
+
lhs.name == rhs.name && lhs.url == rhs.url && lhs.isStoredInMemoryOnly == rhs.isStoredInMemoryOnly
|
|
79
|
+
&& lhs.allowsSave == rhs.allowsSave
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public func hash(into hasher: inout Hasher) {
|
|
83
|
+
hasher.combine(name)
|
|
84
|
+
hasher.combine(url)
|
|
85
|
+
hasher.combine(isStoredInMemoryOnly)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// The models of a schema and the store that keeps them.
|
|
90
|
+
public final class ModelContainer: @unchecked Sendable {
|
|
91
|
+
public let schema: Schema
|
|
92
|
+
public let configurations: [ModelConfiguration]
|
|
93
|
+
let store: _Store
|
|
94
|
+
private var _mainContext: ModelContext?
|
|
95
|
+
|
|
96
|
+
public init(for schema: Schema, migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: [ModelConfiguration] = []) throws {
|
|
97
|
+
let configuration = configurations.first ?? ModelConfiguration(schema: schema)
|
|
98
|
+
self.schema = schema
|
|
99
|
+
self.configurations = configurations.isEmpty ? [configuration] : configurations
|
|
100
|
+
store = _Store.open(identifier: configuration.storeIdentifier, inMemory: configuration.isStoredInMemoryOnly)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public convenience init(for schema: Schema, migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: ModelConfiguration...) throws {
|
|
104
|
+
try self.init(for: schema, migrationPlan: migrationPlan, configurations: configurations)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public convenience init(for forTypes: any PersistentModel.Type..., migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: ModelConfiguration...) throws {
|
|
108
|
+
try self.init(for: Schema(forTypes), migrationPlan: migrationPlan, configurations: configurations)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public convenience init(for forTypes: any PersistentModel.Type..., migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: [ModelConfiguration]) throws {
|
|
112
|
+
try self.init(for: Schema(forTypes), migrationPlan: migrationPlan, configurations: configurations)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// The context bound to the main actor, which saves on its own after
|
|
116
|
+
/// every event that changed it (`autosaveEnabled`).
|
|
117
|
+
@MainActor public var mainContext: ModelContext {
|
|
118
|
+
if let context = _mainContext { return context }
|
|
119
|
+
let context = ModelContext(self)
|
|
120
|
+
context.autosaveEnabled = true
|
|
121
|
+
_mainContext = context
|
|
122
|
+
return context
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// Deletes every model of the container's store.
|
|
126
|
+
public func deleteAllData() {
|
|
127
|
+
store.commit(put: [], delete: [], clear: true, from: nil)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
// A context: the live models of a store, and the changes not yet saved.
|
|
2
|
+
//
|
|
3
|
+
// It keeps one object per record (fetching twice returns the same model),
|
|
4
|
+
// tracks inserted, changed and deleted models, keeps the two sides of a
|
|
5
|
+
// relationship in step, and saves into its store. The main context saves on
|
|
6
|
+
// its own at the end of every event that changed it, like SwiftData's
|
|
7
|
+
// autosave; `@Query` re-runs when the context changes.
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import Observation
|
|
11
|
+
import SwiftUI
|
|
12
|
+
|
|
13
|
+
public struct SwiftDataError: Error, Equatable, CustomStringConvertible, Sendable {
|
|
14
|
+
public struct Code: Hashable, Sendable {
|
|
15
|
+
let name: String
|
|
16
|
+
public static let unsupportedPredicate = Code(name: "unsupportedPredicate")
|
|
17
|
+
public static let unsupportedSortDescriptor = Code(name: "unsupportedSortDescriptor")
|
|
18
|
+
public static let modelValidationFailure = Code(name: "modelValidationFailure")
|
|
19
|
+
public static let loadIssueModelContainer = Code(name: "loadIssueModelContainer")
|
|
20
|
+
static let _decodeFailed = Code(name: "decodeFailed")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public let code: Code
|
|
24
|
+
let message: String
|
|
25
|
+
|
|
26
|
+
init(_ code: Code, _ message: String) {
|
|
27
|
+
self.code = code
|
|
28
|
+
self.message = message
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public static let unsupportedPredicate = SwiftDataError(.unsupportedPredicate, "the predicate is not supported")
|
|
32
|
+
public static let modelValidationFailure = SwiftDataError(.modelValidationFailure, "a model failed validation")
|
|
33
|
+
public static let loadIssueModelContainer = SwiftDataError(.loadIssueModelContainer, "the container could not be loaded")
|
|
34
|
+
|
|
35
|
+
public static func == (lhs: SwiftDataError, rhs: SwiftDataError) -> Bool { lhs.code == rhs.code }
|
|
36
|
+
|
|
37
|
+
public var description: String { "SwiftDataError(\(code.name)): \(message)" }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Bumped on every change to a context's models; `@Query` reads it so that
|
|
41
|
+
/// the views showing a query re-run when the context changes.
|
|
42
|
+
@Observable
|
|
43
|
+
final class _ChangeSignal {
|
|
44
|
+
var generation = 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public final class ModelContext: Equatable, Hashable {
|
|
48
|
+
public let container: ModelContainer
|
|
49
|
+
let store: _Store
|
|
50
|
+
/// Whether the context saves on its own after each event that changed
|
|
51
|
+
/// it. On for a container's `mainContext`, off for contexts an app makes.
|
|
52
|
+
public var autosaveEnabled = false
|
|
53
|
+
|
|
54
|
+
/// The context's live models, by identity.
|
|
55
|
+
private var registered: [PersistentIdentifier: any PersistentModel] = [:]
|
|
56
|
+
/// Inserted, not yet saved, in order.
|
|
57
|
+
private var inserted: [PersistentIdentifier] = []
|
|
58
|
+
private var insertedSet: Set<PersistentIdentifier> = []
|
|
59
|
+
private var changed: Set<PersistentIdentifier> = []
|
|
60
|
+
private var deleted: [PersistentIdentifier: any PersistentModel] = [:]
|
|
61
|
+
private var autosaveScheduled = false
|
|
62
|
+
let signal = _ChangeSignal()
|
|
63
|
+
|
|
64
|
+
public init(_ container: ModelContainer) {
|
|
65
|
+
self.container = container
|
|
66
|
+
store = container.store
|
|
67
|
+
store.register(self)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public static func == (lhs: ModelContext, rhs: ModelContext) -> Bool { lhs === rhs }
|
|
71
|
+
public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
|
|
72
|
+
|
|
73
|
+
public static let willSave = Notification.Name("SwiftData.ModelContext.willSave")
|
|
74
|
+
public static let didSave = Notification.Name("SwiftData.ModelContext.didSave")
|
|
75
|
+
|
|
76
|
+
// MARK: State
|
|
77
|
+
|
|
78
|
+
public var hasChanges: Bool { !inserted.isEmpty || !changed.isEmpty || !deleted.isEmpty }
|
|
79
|
+
|
|
80
|
+
public var insertedModelsArray: [any PersistentModel] { inserted.compactMap { registered[$0] } }
|
|
81
|
+
public var changedModelsArray: [any PersistentModel] { changed.sorted().compactMap { registered[$0] } }
|
|
82
|
+
public var deletedModelsArray: [any PersistentModel] { deleted.keys.sorted().compactMap { deleted[$0] } }
|
|
83
|
+
|
|
84
|
+
func _hasChanges(_ id: PersistentIdentifier) -> Bool {
|
|
85
|
+
insertedSet.contains(id) || changed.contains(id) || deleted[id] != nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Nothing is deferred: changes apply as they are made.
|
|
89
|
+
public func processPendingChanges() {}
|
|
90
|
+
|
|
91
|
+
// MARK: Inserting
|
|
92
|
+
|
|
93
|
+
/// Adds a model to the context, with the models its relationships hold.
|
|
94
|
+
/// It is saved at the next `save()` (or autosave).
|
|
95
|
+
public func insert<T: PersistentModel>(_ model: T) {
|
|
96
|
+
_insert(model)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func _insert(_ model: any PersistentModel) {
|
|
100
|
+
let backing = model.persistentBackingData
|
|
101
|
+
if backing.context === self {
|
|
102
|
+
// A deleted model inserted again is no longer deleted.
|
|
103
|
+
if backing.isDeleted, deleted.removeValue(forKey: backing.identifier) != nil {
|
|
104
|
+
backing.isDeleted = false
|
|
105
|
+
registered[backing.identifier] = model
|
|
106
|
+
noteChange()
|
|
107
|
+
}
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
if backing.context != nil {
|
|
111
|
+
print("[SwiftData] a \(backing.entity.name) from another context was inserted; it now belongs to this one")
|
|
112
|
+
}
|
|
113
|
+
backing.context = self
|
|
114
|
+
backing.storeIdentifier = store.identifier
|
|
115
|
+
backing.isDeleted = false
|
|
116
|
+
if let key = backing.primaryKey, store.record(key) != nil {
|
|
117
|
+
// The model was identified before its store opened and took a key
|
|
118
|
+
// a stored record already has.
|
|
119
|
+
backing.primaryKey = _Store.allocatePrimaryKey()
|
|
120
|
+
}
|
|
121
|
+
let id = backing.identifier
|
|
122
|
+
registered[id] = model
|
|
123
|
+
if insertedSet.insert(id).inserted { inserted.append(id) }
|
|
124
|
+
for property in backing.entity.relationships {
|
|
125
|
+
for target in backing.relatedModels(property) {
|
|
126
|
+
_insert(target)
|
|
127
|
+
if let inverse = backing.entity.inverse(of: property) {
|
|
128
|
+
link(target, inverse, to: model)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
noteChange()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// MARK: Deleting
|
|
136
|
+
|
|
137
|
+
/// Removes a model from the store at the next save, applying its
|
|
138
|
+
/// relationships' delete rules.
|
|
139
|
+
public func delete<T: PersistentModel>(_ model: T) {
|
|
140
|
+
_delete(model)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private func _delete(_ model: any PersistentModel) {
|
|
144
|
+
let backing = model.persistentBackingData
|
|
145
|
+
guard backing.context === self, !backing.isDeleted else { return }
|
|
146
|
+
let id = backing.identifier
|
|
147
|
+
let related = backing.entity.relationships.map { ($0, backing.relatedModels($0)) }
|
|
148
|
+
backing.isDeleted = true
|
|
149
|
+
if insertedSet.remove(id) != nil {
|
|
150
|
+
inserted.removeAll { $0 == id }
|
|
151
|
+
registered[id] = nil
|
|
152
|
+
} else {
|
|
153
|
+
deleted[id] = model
|
|
154
|
+
changed.remove(id)
|
|
155
|
+
registered[id] = nil
|
|
156
|
+
}
|
|
157
|
+
for (property, targets) in related {
|
|
158
|
+
switch property.deleteRule {
|
|
159
|
+
case .cascade:
|
|
160
|
+
for target in targets { _delete(target) }
|
|
161
|
+
case .nullify, .deny:
|
|
162
|
+
guard let inverse = backing.entity.inverse(of: property) else { continue }
|
|
163
|
+
for target in targets where !target.persistentBackingData.isDeleted {
|
|
164
|
+
unlink(target, inverse, from: model)
|
|
165
|
+
}
|
|
166
|
+
case .noAction:
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
noteChange()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// Deletes every model of a type that matches the predicate.
|
|
174
|
+
public func delete<T: PersistentModel>(model: T.Type, where predicate: Predicate<T>? = nil, includeSubclasses: Bool = true) throws {
|
|
175
|
+
for item in try fetch(FetchDescriptor<T>(predicate: predicate)) { delete(item) }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// MARK: Fetching
|
|
179
|
+
|
|
180
|
+
public func fetch<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [T] {
|
|
181
|
+
var results = try matches(descriptor)
|
|
182
|
+
if !descriptor.sortBy.isEmpty { results.sort(using: descriptor.sortBy) }
|
|
183
|
+
let offset = max(0, descriptor.fetchOffset ?? 0)
|
|
184
|
+
if offset > 0 { results = Array(results.dropFirst(offset)) }
|
|
185
|
+
if let limit = descriptor.fetchLimit, limit >= 0, results.count > limit { results = Array(results.prefix(limit)) }
|
|
186
|
+
return results
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public func fetch<T: PersistentModel>(_ descriptor: FetchDescriptor<T>, batchSize: Int) throws -> FetchResultsCollection<T> {
|
|
190
|
+
FetchResultsCollection(models: try fetch(descriptor))
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public func fetchCount<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> Int {
|
|
194
|
+
var count = try matches(descriptor).count
|
|
195
|
+
count = max(0, count - max(0, descriptor.fetchOffset ?? 0))
|
|
196
|
+
if let limit = descriptor.fetchLimit, limit >= 0 { count = min(count, limit) }
|
|
197
|
+
return count
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public func fetchIdentifiers<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [PersistentIdentifier] {
|
|
201
|
+
try fetch(descriptor).map(\.persistentModelID)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public func enumerate<T: PersistentModel>(_ descriptor: FetchDescriptor<T>, batchSize: Int = 5000, allowEscapingMutations: Bool = false, block: (T) throws -> Void) throws {
|
|
205
|
+
for model in try fetch(descriptor) { try block(model) }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// The models of `T` the context can see (saved and, unless the
|
|
209
|
+
/// descriptor says otherwise, inserted), filtered by its predicate.
|
|
210
|
+
private func matches<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [T] {
|
|
211
|
+
let entity = _Entity.of(T.self)
|
|
212
|
+
var candidates: [T] = []
|
|
213
|
+
for key in store.keys(of: entity.name) {
|
|
214
|
+
if let model = _model(primaryKey: key, type: T.self) as? T { candidates.append(model) }
|
|
215
|
+
}
|
|
216
|
+
if descriptor.includePendingChanges {
|
|
217
|
+
for id in inserted where id.entityName == entity.name {
|
|
218
|
+
if let model = registered[id] as? T, store.record(id.primaryKey) == nil { candidates.append(model) }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
guard let predicate = descriptor.predicate else { return candidates }
|
|
222
|
+
return try candidates.filter { try predicate.evaluate($0) }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// The live model for a stored record (materialized on first use), or
|
|
226
|
+
/// nil when the record is gone or deleted in this context.
|
|
227
|
+
func _model(primaryKey: Int64, type: any PersistentModel.Type) -> (any PersistentModel)? {
|
|
228
|
+
let entity = _Entity.of(type)
|
|
229
|
+
let id = PersistentIdentifier(entityName: entity.name, storeIdentifier: store.identifier, primaryKey: primaryKey)
|
|
230
|
+
if let model = registered[id] { return model }
|
|
231
|
+
guard deleted[id] == nil, let record = store.record(primaryKey), record.entity == entity.name else { return nil }
|
|
232
|
+
let backing = _ModelBacking(type: type, primaryKey: primaryKey, storeIdentifier: store.identifier, stored: record.values)
|
|
233
|
+
backing.context = self
|
|
234
|
+
let model = type.init(backingData: backing)
|
|
235
|
+
registered[id] = model
|
|
236
|
+
return model
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/// The model with this identifier, if the context has it or its store
|
|
240
|
+
/// has its record.
|
|
241
|
+
public func registeredModel<T: PersistentModel>(for id: PersistentIdentifier) -> T? {
|
|
242
|
+
registered[id] as? T
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public func model(for id: PersistentIdentifier) -> any PersistentModel {
|
|
246
|
+
if let model = registered[id] { return model }
|
|
247
|
+
guard let entity = _Entity.byEntityName[id.entityName], let model = _model(primaryKey: id.primaryKey, type: entity.type) else {
|
|
248
|
+
fatalError("SwiftData: no \(id.entityName) with identifier \(id) in this context")
|
|
249
|
+
}
|
|
250
|
+
return model
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// MARK: Saving
|
|
254
|
+
|
|
255
|
+
/// Writes the context's changes to its store; a persistent store sends
|
|
256
|
+
/// them to the page, which keeps them in IndexedDB.
|
|
257
|
+
public func save() throws {
|
|
258
|
+
guard hasChanges else { return }
|
|
259
|
+
guard container.configurations.first?.allowsSave ?? true else { return }
|
|
260
|
+
var put: [(Int64, _Record)] = []
|
|
261
|
+
var removed: [Int64] = deleted.keys.map(\.primaryKey).sorted()
|
|
262
|
+
var replaced: [any PersistentModel] = []
|
|
263
|
+
let ids = inserted + changed.sorted().filter { !insertedSet.contains($0) }
|
|
264
|
+
for id in ids {
|
|
265
|
+
guard let model = registered[id] else { continue }
|
|
266
|
+
let backing = model.persistentBackingData
|
|
267
|
+
var values: [String: _JSON] = [:]
|
|
268
|
+
for metadata in backing.entity.properties {
|
|
269
|
+
values[metadata.name] = backing.json(of: metadata.property)
|
|
270
|
+
}
|
|
271
|
+
// `@Attribute(.unique)`: a new model whose value a stored record
|
|
272
|
+
// already has replaces that record.
|
|
273
|
+
if insertedSet.contains(id) {
|
|
274
|
+
for unique in backing.entity.uniqueAttributes {
|
|
275
|
+
guard let value = values[unique.name] else { continue }
|
|
276
|
+
for key in store.keys(of: backing.entity.name) where key != id.primaryKey && store.record(key)?.values[unique.name] == value {
|
|
277
|
+
removed.append(key)
|
|
278
|
+
let otherID = PersistentIdentifier(entityName: backing.entity.name, storeIdentifier: store.identifier, primaryKey: key)
|
|
279
|
+
if let other = registered[otherID] { replaced.append(other) }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
put.append((id.primaryKey, _Record(entity: backing.entity.name, values: values)))
|
|
284
|
+
}
|
|
285
|
+
for model in deleted.values { model.persistentBackingData.context = nil }
|
|
286
|
+
for model in replaced {
|
|
287
|
+
let backing = model.persistentBackingData
|
|
288
|
+
backing.isDeleted = true
|
|
289
|
+
registered[backing.identifier] = nil
|
|
290
|
+
backing.context = nil
|
|
291
|
+
}
|
|
292
|
+
// Saved records are read back from the store: a model keeps its live
|
|
293
|
+
// values, and the store's JSON is what a later fetch decodes.
|
|
294
|
+
inserted.removeAll()
|
|
295
|
+
insertedSet.removeAll()
|
|
296
|
+
changed.removeAll()
|
|
297
|
+
deleted.removeAll()
|
|
298
|
+
store.commit(put: put, delete: removed, from: self)
|
|
299
|
+
noteChange(autosave: false)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/// Discards unsaved changes: inserted models leave the context, deleted
|
|
303
|
+
/// ones return, and changed ones read their saved values again.
|
|
304
|
+
public func rollback() {
|
|
305
|
+
for id in inserted {
|
|
306
|
+
guard let model = registered.removeValue(forKey: id) else { continue }
|
|
307
|
+
model.persistentBackingData.context = nil
|
|
308
|
+
}
|
|
309
|
+
for (id, model) in deleted where store.record(id.primaryKey) != nil {
|
|
310
|
+
model.persistentBackingData.isDeleted = false
|
|
311
|
+
registered[id] = model
|
|
312
|
+
}
|
|
313
|
+
for id in changed { reload(id) }
|
|
314
|
+
for (id, _) in deleted { reload(id) }
|
|
315
|
+
inserted.removeAll()
|
|
316
|
+
insertedSet.removeAll()
|
|
317
|
+
changed.removeAll()
|
|
318
|
+
deleted.removeAll()
|
|
319
|
+
noteChange(autosave: false)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/// Runs `block` and saves.
|
|
323
|
+
public func transaction(block: () throws -> Void) throws {
|
|
324
|
+
try block()
|
|
325
|
+
try save()
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/// Resets a registered model to its stored record.
|
|
329
|
+
private func reload(_ id: PersistentIdentifier) {
|
|
330
|
+
guard let model = registered[id], let record = store.record(id.primaryKey) else { return }
|
|
331
|
+
let backing = model.persistentBackingData
|
|
332
|
+
backing.slots = record.values.mapValues { .stored($0) }
|
|
333
|
+
for metadata in backing.entity.properties { metadata.property.notify(model) }
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// Another context saved to the store: models this context has not
|
|
337
|
+
/// changed take the saved values, deleted records' models leave.
|
|
338
|
+
func _storeDidChange(changed saved: Set<Int64>, deleted removed: Set<Int64>, cleared: Bool) {
|
|
339
|
+
for (id, model) in registered where !insertedSet.contains(id) {
|
|
340
|
+
if cleared || removed.contains(id.primaryKey) {
|
|
341
|
+
registered[id] = nil
|
|
342
|
+
model.persistentBackingData.isDeleted = true
|
|
343
|
+
model.persistentBackingData.context = nil
|
|
344
|
+
changed.remove(id)
|
|
345
|
+
} else if saved.contains(id.primaryKey), !changed.contains(id) {
|
|
346
|
+
reload(id)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if cleared {
|
|
350
|
+
for (_, model) in deleted { model.persistentBackingData.context = nil }
|
|
351
|
+
deleted.removeAll()
|
|
352
|
+
}
|
|
353
|
+
noteChange(autosave: false)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// MARK: Changes
|
|
357
|
+
|
|
358
|
+
/// A persisted attribute of a registered model was set.
|
|
359
|
+
func _modelDidChange(_ model: any PersistentModel) {
|
|
360
|
+
let id = model.persistentModelID
|
|
361
|
+
if !insertedSet.contains(id) { changed.insert(id) }
|
|
362
|
+
noteChange()
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/// A relationship of `model` changed from `old` to `new`: models it now
|
|
366
|
+
/// holds join the context, and the inverse follows on both sides.
|
|
367
|
+
func _relationship(_ property: _Property, of model: any PersistentModel, changedFrom old: [any PersistentModel], to new: [any PersistentModel]) {
|
|
368
|
+
let inverse = model.persistentBackingData.entity.inverse(of: property)
|
|
369
|
+
for target in new where !old.contains(where: { $0 === target }) {
|
|
370
|
+
_insert(target)
|
|
371
|
+
if let inverse { link(target, inverse, to: model) }
|
|
372
|
+
}
|
|
373
|
+
guard let inverse else { return }
|
|
374
|
+
for target in old where !new.contains(where: { $0 === target }) {
|
|
375
|
+
unlink(target, inverse, from: model)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/// Makes `target`'s `inverse` hold `model`.
|
|
380
|
+
private func link(_ target: any PersistentModel, _ inverse: _Property, to model: any PersistentModel) {
|
|
381
|
+
let backing = target.persistentBackingData
|
|
382
|
+
let current = backing.relatedModels(inverse)
|
|
383
|
+
if current.contains(where: { $0 === model }) { return }
|
|
384
|
+
if inverse.kind == .toMany {
|
|
385
|
+
setRaw(target, inverse, inverse.make(current + [model]))
|
|
386
|
+
} else {
|
|
387
|
+
setRaw(target, inverse, inverse.make([model]))
|
|
388
|
+
// A to-one inverse that held another model: that model's side
|
|
389
|
+
// of the relationship lets go of `target`.
|
|
390
|
+
if let previous = current.first, let forward = backing.entity.inverse(of: inverse) {
|
|
391
|
+
unlink(previous, forward, from: target)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/// Makes `target`'s `inverse` stop holding `model`.
|
|
397
|
+
private func unlink(_ target: any PersistentModel, _ inverse: _Property, from model: any PersistentModel) {
|
|
398
|
+
let backing = target.persistentBackingData
|
|
399
|
+
let current = backing.relatedModels(inverse)
|
|
400
|
+
guard current.contains(where: { $0 === model }) else { return }
|
|
401
|
+
let remaining = current.filter { $0 !== model }
|
|
402
|
+
if inverse.kind == .toOne, remaining.isEmpty, !inverse.isOptional { return }
|
|
403
|
+
setRaw(target, inverse, inverse.make(remaining))
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/// Sets a relationship without running its own inverse bookkeeping, and
|
|
407
|
+
/// tells its observers.
|
|
408
|
+
private func setRaw(_ target: any PersistentModel, _ property: _Property, _ value: Any) {
|
|
409
|
+
let backing = target.persistentBackingData
|
|
410
|
+
backing.slots[property.name] = .live(value)
|
|
411
|
+
property.notify(target)
|
|
412
|
+
if backing.context === self, !backing.isDeleted { _modelDidChange(target) }
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
private func noteChange(autosave: Bool = true) {
|
|
416
|
+
signal.generation += 1
|
|
417
|
+
if autosave { scheduleAutosave() }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private func scheduleAutosave() {
|
|
421
|
+
guard autosaveEnabled, !autosaveScheduled else { return }
|
|
422
|
+
autosaveScheduled = true
|
|
423
|
+
// Models and contexts belong to the main actor in practice (there is
|
|
424
|
+
// one thread on wasm); the box only carries the context across.
|
|
425
|
+
let box = _UncheckedWeakContext(context: self)
|
|
426
|
+
MainActor.assumeIsolated {
|
|
427
|
+
_Runtime.shared._afterUpdate { box.context?.autosave() }
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private func autosave() {
|
|
432
|
+
autosaveScheduled = false
|
|
433
|
+
do {
|
|
434
|
+
try save()
|
|
435
|
+
} catch {
|
|
436
|
+
print("[SwiftData] autosave failed: \(error)")
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private struct _UncheckedWeakContext: @unchecked Sendable {
|
|
442
|
+
weak var context: ModelContext?
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/// The results of a batched fetch (all of them: the store is in memory).
|
|
446
|
+
public struct FetchResultsCollection<Element: PersistentModel>: RandomAccessCollection {
|
|
447
|
+
let models: [Element]
|
|
448
|
+
public var startIndex: Int { models.startIndex }
|
|
449
|
+
public var endIndex: Int { models.endIndex }
|
|
450
|
+
public subscript(position: Int) -> Element { models[position] }
|
|
451
|
+
}
|