@mmerterden/multi-agent-pipeline 20.6.0 → 20.8.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/CHANGELOG.md +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/council/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -3,49 +3,50 @@
|
|
|
3
3
|
"evals": [
|
|
4
4
|
{
|
|
5
5
|
"id": 1,
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"name": "apple-pay-checkout-setup",
|
|
7
|
+
"prompt": "We sell bicycle parts and want Apple Pay in our SwiftUI app. Right now we draw our own black button with the Apple logo, compute prices as Double, present PKPaymentAuthorizationController from a local variable, and dismiss it inside didAuthorizePayment. A teammate also suggests using StoreKit instead. Walk us through a correct setup.",
|
|
8
|
+
"expected_output": "Lists the capability, Merchant ID, Payment Processing Certificate and entitlement; checks canMakePayments and canMakePayments(usingNetworks:capabilities:); uses PayWithApplePayButton or PKPaymentButton; uses NSDecimalNumber for items and shipping with the business-name total last; retains the controller and clears it after dismissing in didFinish; sends the token to the server and replies with PKPaymentAuthorizationResult; keeps physical goods on Apple Pay rather than StoreKit.",
|
|
8
9
|
"files": [],
|
|
9
10
|
"assertions": [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"Explains that StoreKit is for virtual goods, app features, and digital-content subscriptions while PassKit covers physical goods, real-world services, donations, and eligible recurring payments."
|
|
11
|
+
"Covers the Apple Pay capability, a Merchant ID, the Payment Processing Certificate and the merchant entitlement",
|
|
12
|
+
"Performs both canMakePayments checks before showing the button",
|
|
13
|
+
"Replaces the custom button with PayWithApplePayButton or PKPaymentButton",
|
|
14
|
+
"Uses NSDecimalNumber for summary items and shipping, with a final total labelled with the business name",
|
|
15
|
+
"Stores the controller (its delegate is weak), dismisses only in paymentAuthorizationControllerDidFinish and then releases it",
|
|
16
|
+
"Sends payment.token to the server and completes with a PKPaymentAuthorizationResult carrying errors on failure",
|
|
17
|
+
"Explains that physical goods use Apple Pay and StoreKit is for digital goods"
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"id": 2,
|
|
22
|
-
"
|
|
23
|
-
"
|
|
22
|
+
"name": "wallet-pass-add-and-update",
|
|
23
|
+
"prompt": "Our concert app downloads a .pkpass from the server and shows a custom 'Save to Wallet' button. We gate it with PKPassLibrary.isPassLibraryAvailable(), parse with try? PKPass(data:), and when a ticket changes we create a new serial number. Sometimes replacePass seems to do nothing. What should we fix?",
|
|
24
|
+
"expected_output": "Uses AddPassToWalletButton or PKAddPassButton/PKAddPassesViewController, gates adding on canAddPasses and library work on isPassLibraryAvailable, surfaces invalid-data and invalid-signature errors from signed data, notes passes() is limited by entitlements, keeps the same pass type and serial number for updates, and checks the Bool from replacePass(with:).",
|
|
24
25
|
"files": [],
|
|
25
26
|
"assertions": [
|
|
26
|
-
"Replaces the custom
|
|
27
|
-
"Uses
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"Checks the Boolean result from `PKPassLibrary.replacePass(with:)` and handles failure."
|
|
27
|
+
"Replaces the custom button with AddPassToWalletButton, PKAddPassButton or PKAddPassesViewController",
|
|
28
|
+
"Uses canAddPasses() to decide whether adding is possible and keeps isPassLibraryAvailable() for library operations",
|
|
29
|
+
"Requires signed pass data and reports invalid-data and invalid-signature errors instead of a bare try?",
|
|
30
|
+
"Notes that passes() only returns passes the app's entitlements allow",
|
|
31
|
+
"Keeps passTypeIdentifier and serialNumber unchanged when updating a pass",
|
|
32
|
+
"Checks the Bool returned by replacePass(with:) and handles false"
|
|
33
33
|
]
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"id": 3,
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"name": "advanced-payment-requests",
|
|
38
|
+
"prompt": "For our furniture marketplace we need: a monthly protection plan, promo codes at checkout, separate payouts to each workshop in a basket, and pay-on-delivery for custom pieces. Can one PKPaymentRequest do all of that? We are also wondering whether FinanceKit or StoreKit should be involved.",
|
|
39
|
+
"expected_output": "Explains that only one advanced type fits per request; shows a PKRecurringPaymentRequest with a recurring item, interval, billing agreement and management URL; enables coupon codes with the delegate reply including shipping methods; uses PKPaymentTokenContext entries with merchant ids, name, domain and decimal amounts; builds a PKDeferredPaymentRequest with deferred date, free cancellation details and management URL; keeps FinanceKit and StoreKit out.",
|
|
39
40
|
"files": [],
|
|
40
41
|
"assertions": [
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"Uses
|
|
46
|
-
"Uses
|
|
47
|
-
"
|
|
42
|
+
"Builds a PKRecurringPaymentRequest with a PKRecurringPaymentSummaryItem, interval, billing agreement and management URL",
|
|
43
|
+
"States the one-advanced-type-per-request rule and splits the checkout into several requests",
|
|
44
|
+
"Sets supportsCouponCode and implements didChangeCouponCode",
|
|
45
|
+
"Replies with PKPaymentRequestCouponCodeUpdate including shippingMethods",
|
|
46
|
+
"Uses PKPaymentTokenContext with merchant identifier, external identifier, name, domain and NSDecimalNumber amounts",
|
|
47
|
+
"Uses PKDeferredPaymentRequest with a deferred date, free cancellation date and time zone, and a management URL",
|
|
48
|
+
"Does not implement FinanceKit or StoreKit for this flow"
|
|
48
49
|
]
|
|
49
50
|
}
|
|
50
51
|
]
|
|
51
|
-
}
|
|
52
|
+
}
|
|
@@ -1,304 +1,237 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Wallet Passes and Advanced Apple Pay
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Reference for the `passkit-wallet` skill: advanced payment request types,
|
|
4
|
+
pass bundles, pass updates and a complete SwiftUI checkout.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
type, such as `recurringPaymentRequest`, `automaticReloadPaymentRequest`,
|
|
7
|
-
`deferredPaymentRequest`, Apple Pay Later availability, or
|
|
8
|
-
`multiTokenContexts`.
|
|
6
|
+
## One advanced type per request
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
Each `PKPaymentRequest` may set only one of these:
|
|
11
9
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- [Updating Passes with Push Notifications](#updating-passes-with-push-notifications)
|
|
18
|
-
- [SwiftUI Payment Flow](#swiftui-payment-flow)
|
|
10
|
+
- `recurringPaymentRequest`
|
|
11
|
+
- `automaticReloadPaymentRequest`
|
|
12
|
+
- `deferredPaymentRequest`
|
|
13
|
+
- the Apple Pay Later availability setting
|
|
14
|
+
- `multiTokenContexts`
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
If a checkout needs two, split it into two requests.
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
## Recurring payments
|
|
23
19
|
|
|
24
20
|
```swift
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let monthlyItem = PKRecurringPaymentSummaryItem(
|
|
36
|
-
label: "Monthly Subscription",
|
|
37
|
-
amount: NSDecimalNumber(string: "9.99")
|
|
21
|
+
func membershipRequest() -> PKPaymentRequest {
|
|
22
|
+
let order = baseRequest()
|
|
23
|
+
let monthly = PKRecurringPaymentSummaryItem(label: "Studio Membership", amount: NSDecimalNumber(string: "29.00"))
|
|
24
|
+
monthly.intervalUnit = .month
|
|
25
|
+
monthly.intervalCount = 1
|
|
26
|
+
|
|
27
|
+
let plan = PKRecurringPaymentRequest(
|
|
28
|
+
paymentDescription: "Monthly studio membership",
|
|
29
|
+
regularBilling: monthly,
|
|
30
|
+
managementURL: URL(string: "https://studio.example.com/account/membership")!
|
|
38
31
|
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
request.paymentSummaryItems = [
|
|
43
|
-
monthlyItem,
|
|
44
|
-
PKPaymentSummaryItem(
|
|
45
|
-
label: "My Service",
|
|
46
|
-
amount: NSDecimalNumber(string: "9.99")
|
|
47
|
-
)
|
|
48
|
-
]
|
|
49
|
-
|
|
50
|
-
let recurringRequest = PKRecurringPaymentRequest(
|
|
51
|
-
paymentDescription: "Monthly Premium",
|
|
52
|
-
regularBilling: monthlyItem,
|
|
53
|
-
managementURL: URL(string: "https://example.com/manage")!
|
|
54
|
-
)
|
|
55
|
-
recurringRequest.billingAgreement = "You will be charged $9.99/month."
|
|
56
|
-
request.recurringPaymentRequest = recurringRequest
|
|
32
|
+
plan.billingAgreement = "Billed monthly until you cancel. Cancel any time from your account page."
|
|
33
|
+
order.recurringPaymentRequest = plan
|
|
57
34
|
|
|
58
|
-
|
|
35
|
+
let total = PKPaymentSummaryItem(label: "Clayworks Studio", amount: monthly.amount)
|
|
36
|
+
order.paymentSummaryItems = [monthly, total]
|
|
37
|
+
return order
|
|
59
38
|
}
|
|
60
39
|
```
|
|
61
40
|
|
|
62
|
-
|
|
41
|
+
The recurring item appears in the summary list and the total follows it. The
|
|
42
|
+
management URL is where the customer changes or cancels the plan. The literal
|
|
43
|
+
URL is force-unwrapped only to keep the sample short.
|
|
63
44
|
|
|
64
|
-
|
|
65
|
-
`PKPaymentRequestCouponCodeUpdate` requires a `[PKShippingMethod]`; pass current
|
|
66
|
-
or updated methods, or `[]` when unchanged.
|
|
45
|
+
## Coupon codes
|
|
67
46
|
|
|
68
47
|
```swift
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
request.supportsCouponCode = true
|
|
72
|
-
request.couponCode = "" // pre-fill if known
|
|
73
|
-
return request
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Handle coupon code entry in the delegate
|
|
77
|
-
extension PaymentCoordinator: PKPaymentAuthorizationControllerDelegate {
|
|
78
|
-
func paymentAuthorizationController(
|
|
79
|
-
_ controller: PKPaymentAuthorizationController,
|
|
80
|
-
didChangeCouponCode couponCode: String,
|
|
81
|
-
handler completion: @escaping (PKPaymentRequestCouponCodeUpdate) -> Void
|
|
82
|
-
) {
|
|
83
|
-
Task {
|
|
84
|
-
do {
|
|
85
|
-
let discount = try await validateCoupon(couponCode)
|
|
86
|
-
let updatedItems = applyDiscount(discount)
|
|
87
|
-
completion(PKPaymentRequestCouponCodeUpdate(
|
|
88
|
-
errors: nil,
|
|
89
|
-
paymentSummaryItems: updatedItems,
|
|
90
|
-
shippingMethods: currentShippingMethods
|
|
91
|
-
))
|
|
92
|
-
} catch {
|
|
93
|
-
let couponError = PKPaymentRequest.paymentCouponCodeInvalidError(
|
|
94
|
-
localizedDescription: "Invalid coupon code."
|
|
95
|
-
)
|
|
96
|
-
completion(PKPaymentRequestCouponCodeUpdate(
|
|
97
|
-
errors: [couponError],
|
|
98
|
-
paymentSummaryItems: originalItems,
|
|
99
|
-
shippingMethods: currentShippingMethods
|
|
100
|
-
))
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
48
|
+
order.supportsCouponCode = true
|
|
49
|
+
order.couponCode = savedPromo
|
|
105
50
|
```
|
|
106
51
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
52
|
+
`couponCode` is optional and pre-fills the field. Validate changes in the
|
|
53
|
+
delegate. Like the other delegate callbacks it runs on the main actor, so the
|
|
54
|
+
`Task` it starts stays there and can call `reply` and touch `basket`:
|
|
110
55
|
|
|
111
56
|
```swift
|
|
112
|
-
func
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
let furnitureContext = PKPaymentTokenContext(
|
|
136
|
-
merchantIdentifier: "merchant.com.example.furniture",
|
|
137
|
-
externalIdentifier: "furniture-order-123",
|
|
138
|
-
merchantName: "Example Furniture",
|
|
139
|
-
merchantDomain: "furniture.example.com",
|
|
140
|
-
amount: NSDecimalNumber(string: "299.00")
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
let lightingContext = PKPaymentTokenContext(
|
|
144
|
-
merchantIdentifier: "merchant.com.example.lighting",
|
|
145
|
-
externalIdentifier: "lighting-order-456",
|
|
146
|
-
merchantName: "Example Lighting",
|
|
147
|
-
merchantDomain: "lighting.example.com",
|
|
148
|
-
amount: NSDecimalNumber(string: "89.00")
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
request.multiTokenContexts = [furnitureContext, lightingContext]
|
|
152
|
-
return request
|
|
57
|
+
func paymentAuthorizationController(
|
|
58
|
+
_ sheet: PKPaymentAuthorizationController,
|
|
59
|
+
didChangeCouponCode code: String,
|
|
60
|
+
handler reply: @escaping (PKPaymentRequestCouponCodeUpdate) -> Void
|
|
61
|
+
) {
|
|
62
|
+
Task {
|
|
63
|
+
guard let discount = await Promotions.lookUp(code) else {
|
|
64
|
+
let problem = PKPaymentRequest.paymentCouponCodeInvalidError(localizedDescription: "That code is not valid.")
|
|
65
|
+
reply(PKPaymentRequestCouponCodeUpdate(
|
|
66
|
+
errors: [problem],
|
|
67
|
+
paymentSummaryItems: basket.summaryItems(),
|
|
68
|
+
shippingMethods: basket.shippingMethods
|
|
69
|
+
))
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
basket.apply(discount)
|
|
73
|
+
reply(PKPaymentRequestCouponCodeUpdate(
|
|
74
|
+
errors: nil,
|
|
75
|
+
paymentSummaryItems: basket.summaryItems(),
|
|
76
|
+
shippingMethods: basket.shippingMethods
|
|
77
|
+
))
|
|
78
|
+
}
|
|
153
79
|
}
|
|
154
80
|
```
|
|
155
81
|
|
|
156
|
-
|
|
82
|
+
`shippingMethods` is a required `[PKShippingMethod]` argument. Pass the
|
|
83
|
+
current or recalculated methods, or `[]` when shipping is unchanged. On an
|
|
84
|
+
invalid code, send the original items back with the coupon error.
|
|
85
|
+
|
|
86
|
+
## Several merchants in one checkout
|
|
157
87
|
|
|
158
|
-
|
|
88
|
+
A marketplace or booking platform can collect a separate token for each
|
|
89
|
+
merchant it sells for:
|
|
159
90
|
|
|
160
91
|
```swift
|
|
161
|
-
|
|
162
|
-
|
|
92
|
+
let hotel = PKPaymentTokenContext(
|
|
93
|
+
merchantIdentifier: "merchant.com.harborhotel",
|
|
94
|
+
externalIdentifier: "harbor-hotel",
|
|
95
|
+
merchantName: "Harbor Hotel",
|
|
96
|
+
merchantDomain: "harborhotel.example",
|
|
97
|
+
amount: NSDecimalNumber(string: "240.00")
|
|
98
|
+
)
|
|
99
|
+
let tour = PKPaymentTokenContext(
|
|
100
|
+
merchantIdentifier: "merchant.com.baytours",
|
|
101
|
+
externalIdentifier: "bay-tours",
|
|
102
|
+
merchantName: "Bay Tours",
|
|
103
|
+
merchantDomain: "baytours.example",
|
|
104
|
+
amount: NSDecimalNumber(string: "65.00")
|
|
105
|
+
)
|
|
106
|
+
order.multiTokenContexts = [hotel, tour]
|
|
107
|
+
```
|
|
163
108
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)!
|
|
109
|
+
The request itself keeps the platform's own merchant identifier; each context
|
|
110
|
+
names the merchant that actually receives that part of the payment.
|
|
167
111
|
|
|
168
|
-
|
|
169
|
-
label: "Sofa (charged at shipment)",
|
|
170
|
-
amount: NSDecimalNumber(string: "299.00")
|
|
171
|
-
)
|
|
172
|
-
deferredBilling.deferredDate = deferredDate
|
|
112
|
+
## Deferred payments
|
|
173
113
|
|
|
174
|
-
|
|
175
|
-
paymentDescription: "Made-to-order Sofa - Shipment",
|
|
176
|
-
deferredBilling: deferredBilling,
|
|
177
|
-
managementURL: URL(string: "https://example.com/orders")!
|
|
178
|
-
)
|
|
179
|
-
deferredRequest.freeCancellationDate = deferredDate
|
|
180
|
-
deferredRequest.freeCancellationDateTimeZone = .current
|
|
114
|
+
For charges taken later, such as pre-orders or made-to-order goods:
|
|
181
115
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
116
|
+
```swift
|
|
117
|
+
let balance = PKDeferredPaymentSummaryItem(label: "Custom Table (due at delivery)", amount: NSDecimalNumber(string: "480.00"))
|
|
118
|
+
balance.deferredDate = deliveryDate
|
|
119
|
+
|
|
120
|
+
let deferred = PKDeferredPaymentRequest(
|
|
121
|
+
paymentDescription: "Handmade oak table",
|
|
122
|
+
deferredBilling: balance,
|
|
123
|
+
managementURL: URL(string: "https://workshop.example.com/orders")!
|
|
124
|
+
)
|
|
125
|
+
deferred.freeCancellationDate = deliveryDate.addingTimeInterval(-7 * 24 * 60 * 60)
|
|
126
|
+
deferred.freeCancellationDateTimeZone = TimeZone(identifier: "America/Chicago")
|
|
127
|
+
order.deferredPaymentRequest = deferred
|
|
185
128
|
```
|
|
186
129
|
|
|
187
|
-
|
|
130
|
+
State when the charge happens, until when the order can be cancelled for
|
|
131
|
+
free, and where the customer manages it.
|
|
188
132
|
|
|
189
|
-
|
|
190
|
-
code separate from server-side pass generation, but check these fields when a
|
|
191
|
-
pass fails to add:
|
|
133
|
+
## Pass bundles
|
|
192
134
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
- `serialNumber` is unique for that pass type; updating a pass uses the same
|
|
196
|
-
`passTypeIdentifier` and `serialNumber`.
|
|
197
|
-
- `manifest.json` includes SHA-1 hashes for every source file, and `signature`
|
|
198
|
-
is a PKCS #7 detached signature over the manifest.
|
|
199
|
-
- `.pkpasses` bundles contain up to 10 `.pkpass` files and use the
|
|
200
|
-
`application/vnd.apple.pkpasses` MIME type.
|
|
135
|
+
A pass that can be distributed is a signed `.pkpass` bundle. Generating and
|
|
136
|
+
signing it is server work; keep that code out of the app.
|
|
201
137
|
|
|
202
|
-
|
|
138
|
+
| Field or file | Rule |
|
|
139
|
+
|---------------|------|
|
|
140
|
+
| `passTypeIdentifier` | Must match the Pass Type ID certificate used to sign |
|
|
141
|
+
| `teamIdentifier` | Must match the developer team that owns that Pass Type ID |
|
|
142
|
+
| `serialNumber` | Unique within the pass type; an update keeps both the pass type and the serial |
|
|
143
|
+
| `manifest.json` | SHA-1 hash of every file in the bundle |
|
|
144
|
+
| `signature` | Detached PKCS #7 signature over the manifest |
|
|
203
145
|
|
|
204
|
-
|
|
146
|
+
A `.pkpasses` bundle groups up to 10 `.pkpass` files and is served as
|
|
147
|
+
`application/vnd.apple.pkpasses`.
|
|
205
148
|
|
|
206
|
-
|
|
207
|
-
2. When the pass is added to Wallet, the device registers with your server
|
|
208
|
-
3. To update, send a production APNs pass-update push with an empty JSON payload
|
|
209
|
-
4. The device calls your `webServiceURL` to fetch the updated `.pkpass` bundle
|
|
149
|
+
## Keeping passes current
|
|
210
150
|
|
|
211
|
-
The pass
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
151
|
+
1. The pass JSON includes `webServiceURL` and `authenticationToken`.
|
|
152
|
+
2. When the user adds the pass, the device registers with your web service.
|
|
153
|
+
3. When the pass changes, your server sends a pass-update push through
|
|
154
|
+
production APNs with an empty JSON payload.
|
|
155
|
+
4. The device asks the web service which passes changed and downloads the new
|
|
156
|
+
`.pkpass` from `webServiceURL`.
|
|
215
157
|
|
|
216
|
-
|
|
158
|
+
The web service checks `authenticationToken` on register, unregister and
|
|
159
|
+
download calls, and uses the device library identifier to answer which serial
|
|
160
|
+
numbers changed. Everything in a pass may change except its authentication
|
|
161
|
+
token and serial number.
|
|
217
162
|
|
|
218
|
-
| Method
|
|
219
|
-
|
|
220
|
-
| POST
|
|
221
|
-
| DELETE
|
|
222
|
-
| GET
|
|
223
|
-
| GET
|
|
163
|
+
| Method and path | Purpose |
|
|
164
|
+
|-----------------|---------|
|
|
165
|
+
| `POST /v1/devices/{deviceId}/registrations/{passTypeId}/{serialNumber}` | Register a device for a pass |
|
|
166
|
+
| `DELETE /v1/devices/{deviceId}/registrations/{passTypeId}/{serialNumber}` | Unregister |
|
|
167
|
+
| `GET /v1/devices/{deviceId}/registrations/{passTypeId}` | Serial numbers that changed |
|
|
168
|
+
| `GET /v1/passes/{passTypeId}/{serialNumber}` | The latest version of a pass |
|
|
224
169
|
|
|
225
|
-
###
|
|
170
|
+
### Updating from inside the app
|
|
226
171
|
|
|
227
172
|
```swift
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
let library = PKPassLibrary()
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if library.containsPass(updatedPass) {
|
|
236
|
-
let replaced = library.replacePass(with: updatedPass)
|
|
237
|
-
if !replaced {
|
|
238
|
-
// Fall back to add-pass UI or report a recoverable update failure.
|
|
173
|
+
@MainActor
|
|
174
|
+
func install(_ fresh: PKPass, presenter: UIViewController) {
|
|
175
|
+
let library = PKPassLibrary()
|
|
176
|
+
if library.containsPass(fresh) {
|
|
177
|
+
guard library.replacePass(with: fresh) else {
|
|
178
|
+
showRetryableWalletError()
|
|
179
|
+
return
|
|
239
180
|
}
|
|
181
|
+
} else if let sheet = PKAddPassesViewController(pass: fresh) {
|
|
182
|
+
presenter.present(sheet, animated: true)
|
|
240
183
|
}
|
|
241
184
|
}
|
|
242
185
|
```
|
|
243
186
|
|
|
244
|
-
|
|
187
|
+
When `replacePass(with:)` returns `false`, fall back to the add-pass sheet or
|
|
188
|
+
tell the user the update can be retried.
|
|
245
189
|
|
|
246
|
-
|
|
190
|
+
## SwiftUI checkout screen
|
|
247
191
|
|
|
248
192
|
```swift
|
|
249
|
-
|
|
250
|
-
|
|
193
|
+
enum PaymentState: Equatable {
|
|
194
|
+
case idle, processing, paid
|
|
195
|
+
case failed(String)
|
|
196
|
+
}
|
|
251
197
|
|
|
252
|
-
struct
|
|
253
|
-
@State private var
|
|
254
|
-
@State private var
|
|
198
|
+
struct CheckoutScreen: View {
|
|
199
|
+
@State private var coordinator = PaymentCoordinator()
|
|
200
|
+
@State private var state: PaymentState = .idle
|
|
255
201
|
|
|
256
202
|
private var canPay: Bool {
|
|
257
203
|
PKPaymentAuthorizationController.canMakePayments(
|
|
258
|
-
usingNetworks:
|
|
204
|
+
usingNetworks: Checkout.networks,
|
|
259
205
|
capabilities: .threeDSecure
|
|
260
206
|
)
|
|
261
207
|
}
|
|
262
208
|
|
|
263
209
|
var body: some View {
|
|
264
|
-
VStack {
|
|
265
|
-
OrderSummaryView()
|
|
266
|
-
|
|
210
|
+
VStack(spacing: 16) {
|
|
267
211
|
if canPay {
|
|
268
|
-
PayWithApplePayButton(.
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
.payWithApplePayButtonStyle(.black)
|
|
272
|
-
.frame(height: 48)
|
|
212
|
+
PayWithApplePayButton(.checkout) { startApplePay() }
|
|
213
|
+
.frame(height: 50)
|
|
273
214
|
} else {
|
|
274
|
-
Button("
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
.buttonStyle(.borderedProminent)
|
|
215
|
+
Button("Pay with Card") { showCardForm() }
|
|
216
|
+
.buttonStyle(.borderedProminent)
|
|
278
217
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
Text(message)
|
|
282
|
-
.foregroundStyle(.red)
|
|
283
|
-
.font(.caption)
|
|
218
|
+
if case .failed(let reason) = state {
|
|
219
|
+
Text(reason).foregroundStyle(.red)
|
|
284
220
|
}
|
|
285
221
|
}
|
|
286
222
|
.padding()
|
|
287
223
|
}
|
|
288
224
|
|
|
289
225
|
@MainActor
|
|
290
|
-
private func
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
coordinator?.startPayment()
|
|
226
|
+
private func startApplePay() {
|
|
227
|
+
state = .processing
|
|
228
|
+
coordinator.pay()
|
|
295
229
|
}
|
|
296
|
-
}
|
|
297
230
|
|
|
298
|
-
|
|
299
|
-
case idle
|
|
300
|
-
case processing
|
|
301
|
-
case success
|
|
302
|
-
case error(String)
|
|
231
|
+
private func showCardForm() {}
|
|
303
232
|
}
|
|
304
233
|
```
|
|
234
|
+
|
|
235
|
+
The coordinator lives in `@State` so it, and the controller it retains, stay
|
|
236
|
+
alive while the sheet is shown. `PaymentState` covers idle, processing, paid
|
|
237
|
+
and a failure with a message.
|