@devo-bmad-custom/agent-orchestration 1.0.2 → 1.0.4
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/lib/installer.js +33 -0
- package/package.json +1 -1
- package/src/.agents/skills/audit-website/README.md +20 -20
- package/src/.agents/skills/audit-website/SKILL.md +470 -470
- package/src/.agents/skills/audit-website/agents/openai.yaml +6 -6
- package/src/.agents/skills/audit-website/assets/icon-small.svg +41 -41
- package/src/.agents/skills/audit-website/references/OUTPUT-FORMAT.md +250 -250
- package/src/.agents/skills/clean-code-standards/SKILL.md +104 -104
- package/src/.agents/skills/excalidraw-dark-standard/SKILL.md +281 -281
- package/src/.agents/skills/frontend-responsive-design-standards/SKILL.md +434 -434
- package/src/.agents/skills/java-fundamentals/SKILL.md +116 -116
- package/src/.agents/skills/java-performance/SKILL.md +119 -119
- package/src/.agents/skills/next-best-practices/SKILL.md +153 -153
- package/src/.agents/skills/next-best-practices/async-patterns.md +87 -87
- package/src/.agents/skills/next-best-practices/bundling.md +180 -180
- package/src/.agents/skills/next-best-practices/data-patterns.md +297 -297
- package/src/.agents/skills/next-best-practices/debug-tricks.md +105 -105
- package/src/.agents/skills/next-best-practices/directives.md +73 -73
- package/src/.agents/skills/next-best-practices/error-handling.md +227 -227
- package/src/.agents/skills/next-best-practices/file-conventions.md +140 -140
- package/src/.agents/skills/next-best-practices/font.md +245 -245
- package/src/.agents/skills/next-best-practices/functions.md +108 -108
- package/src/.agents/skills/next-best-practices/hydration-error.md +91 -91
- package/src/.agents/skills/next-best-practices/image.md +173 -173
- package/src/.agents/skills/next-best-practices/metadata.md +301 -301
- package/src/.agents/skills/next-best-practices/parallel-routes.md +287 -287
- package/src/.agents/skills/next-best-practices/route-handlers.md +146 -146
- package/src/.agents/skills/next-best-practices/rsc-boundaries.md +159 -159
- package/src/.agents/skills/next-best-practices/runtime-selection.md +39 -39
- package/src/.agents/skills/next-best-practices/scripts.md +141 -141
- package/src/.agents/skills/next-best-practices/self-hosting.md +371 -371
- package/src/.agents/skills/next-best-practices/suspense-boundaries.md +67 -67
- package/src/.agents/skills/nextjs-app-router-patterns/SKILL.md +537 -537
- package/src/.agents/skills/postgresql-optimization/SKILL.md +404 -404
- package/src/.agents/skills/python-backend/SKILL.md +153 -153
- package/src/.agents/skills/python-fundamentals/SKILL.md +234 -234
- package/src/.agents/skills/python-performance/SKILL.md +404 -404
- package/src/.agents/skills/react-expert/SKILL.md +335 -335
- package/src/.agents/skills/redis-best-practices/SKILL.md +438 -438
- package/src/.agents/skills/security-best-practices/SKILL.md +288 -288
- package/src/.agents/skills/security-review/LICENSE +22 -22
- package/src/.agents/skills/security-review/SKILL.md +312 -312
- package/src/.agents/skills/security-review/infrastructure/docker.md +432 -432
- package/src/.agents/skills/security-review/languages/javascript.md +388 -388
- package/src/.agents/skills/security-review/languages/python.md +363 -363
- package/src/.agents/skills/security-review/references/api-security.md +519 -519
- package/src/.agents/skills/security-review/references/authentication.md +353 -353
- package/src/.agents/skills/security-review/references/authorization.md +372 -372
- package/src/.agents/skills/security-review/references/business-logic.md +443 -443
- package/src/.agents/skills/security-review/references/cryptography.md +329 -329
- package/src/.agents/skills/security-review/references/csrf.md +398 -398
- package/src/.agents/skills/security-review/references/data-protection.md +378 -378
- package/src/.agents/skills/security-review/references/deserialization.md +410 -410
- package/src/.agents/skills/security-review/references/error-handling.md +436 -436
- package/src/.agents/skills/security-review/references/file-security.md +457 -457
- package/src/.agents/skills/security-review/references/injection.md +259 -259
- package/src/.agents/skills/security-review/references/logging.md +433 -433
- package/src/.agents/skills/security-review/references/misconfiguration.md +435 -435
- package/src/.agents/skills/security-review/references/modern-threats.md +475 -475
- package/src/.agents/skills/security-review/references/ssrf.md +415 -415
- package/src/.agents/skills/security-review/references/supply-chain.md +405 -405
- package/src/.agents/skills/security-review/references/xss.md +336 -336
- package/src/.agents/skills/subagent-driven-development/SKILL.md +275 -275
- package/src/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -26
- package/src/.agents/skills/subagent-driven-development/implementer-prompt.md +113 -113
- package/src/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -61
- package/src/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/src/.agents/skills/systematic-debugging/SKILL.md +296 -296
- package/src/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/src/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/src/.agents/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/src/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/src/.agents/skills/systematic-debugging/test-academic.md +14 -14
- package/src/.agents/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/src/.agents/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/src/.agents/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/src/.agents/skills/typescript-best-practices/SKILL.md +373 -373
- package/src/.agents/skills/ui-ux-pro-custom/SKILL.md +348 -348
- package/src/.agents/skills/ui-ux-pro-custom/data/charts.csv +26 -26
- package/src/.agents/skills/ui-ux-pro-custom/data/colors.csv +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/icons.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/SKILL.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/accessibility.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/animation.md +466 -466
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/composition-locals.md +231 -231
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/deprecated-patterns.md +323 -323
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/lists-scrolling.md +400 -400
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/modifiers.md +331 -331
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/navigation.md +416 -416
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/performance.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/side-effects.md +516 -516
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/foundation-source.md +13327 -13327
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/material3-source.md +19097 -19097
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/navigation-source.md +2947 -2947
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/runtime-source.md +11316 -11316
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/ui-source.md +7896 -7896
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/state-management.md +377 -377
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/styles-experimental.md +470 -470
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/theming-material3.md +349 -349
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/view-composition.md +595 -595
- package/src/.agents/skills/ui-ux-pro-custom/data/landing.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/data/mobile-ui-layout.md +654 -654
- package/src/.agents/skills/ui-ux-pro-custom/data/products.csv +96 -96
- package/src/.agents/skills/ui-ux-pro-custom/data/react-performance.csv +45 -45
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/astro.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/flutter.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/html-tailwind.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/jetpack-compose.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nextjs.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxt-ui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxtjs.csv +59 -59
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react-native.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/shadcn.csv +61 -61
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/svelte.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/swiftui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/vue.csv +50 -50
- package/src/.agents/skills/ui-ux-pro-custom/data/styles.csv +68 -68
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/SKILL.md +438 -438
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/references/alarmkit-patterns.md +584 -584
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-clips/SKILL.md +436 -436
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/SKILL.md +489 -489
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/references/appintents-advanced.md +1076 -1076
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/SKILL.md +340 -340
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/privacy-manifest.md +90 -90
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/review-checklists.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-conversion.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-optimization.md +344 -344
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/foundation-models.md +508 -508
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/mlx-swift.md +285 -285
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/references/keychain-biometric.md +211 -211
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/SKILL.md +499 -499
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/references/background-task-patterns.md +390 -390
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/SKILL.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/references/callkit-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/SKILL.md +492 -492
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/references/cloudkit-patterns.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/codable-patterns/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/SKILL.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/references/contacts-patterns.md +409 -409
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/references/ble-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/SKILL.md +388 -388
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/references/motion-patterns.md +405 -405
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/SKILL.md +495 -495
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/references/nfc-patterns.md +420 -420
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/SKILL.md +459 -459
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/references/coreml-swift-integration.md +765 -765
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/SKILL.md +422 -422
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/instruments-guide.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/lldb-patterns.md +298 -298
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/device-integrity/SKILL.md +477 -477
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/SKILL.md +460 -460
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/references/energykit-patterns.md +541 -541
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/references/eventkit-patterns.md +326 -326
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/references/healthkit-patterns.md +602 -602
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/references/matter-commissioning.md +455 -455
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/SKILL.md +301 -301
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/references/a11y-patterns.md +140 -140
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/SKILL.md +418 -418
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/formatstyle-locale.md +627 -627
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/string-catalogs.md +462 -462
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/SKILL.md +441 -441
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/background-websocket.md +862 -862
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/lightweight-clients.md +93 -93
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/network-framework.md +563 -563
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/urlsession-patterns.md +1116 -1116
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/app-review-guidelines.md +174 -174
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/cryptokit-advanced.md +296 -296
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/file-storage-patterns.md +354 -354
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/privacy-manifest.md +117 -117
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/references/live-activity-patterns.md +868 -868
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/corelocation-patterns.md +730 -730
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/mapkit-patterns.md +748 -748
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/metrickit-diagnostics/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/SKILL.md +395 -395
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/references/musickit-patterns.md +363 -363
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/SKILL.md +412 -412
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/references/translation-patterns.md +311 -311
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/SKILL.md +398 -398
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/references/wallet-passes.md +254 -254
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/SKILL.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/paperkit-integration.md +376 -376
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/pencilkit-patterns.md +302 -302
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/SKILL.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/references/permissionkit-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/av-playback.md +701 -701
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/camera-capture.md +774 -774
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/image-loading-caching.md +869 -869
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/photospicker-patterns.md +597 -597
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/notification-patterns.md +677 -677
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/rich-notifications.md +745 -745
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/references/realitykit-patterns.md +480 -480
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/references/shareplay-patterns.md +544 -544
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/speech-recognition/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/SKILL.md +478 -478
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/app-review-guidelines.md +58 -58
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/storekit-advanced.md +755 -755
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/SKILL.md +487 -487
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/references/charts-patterns.md +895 -895
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/SKILL.md +408 -408
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/approachable-concurrency.md +80 -80
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swift-6-2-concurrency.md +233 -233
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swiftui-concurrency.md +187 -187
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/synchronization-primitives.md +341 -341
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/references/swift-patterns-extended.md +505 -505
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/references/testing-patterns.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/SKILL.md +334 -334
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/core-data-coexistence.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-advanced.md +975 -975
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-queries.md +675 -675
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/SKILL.md +481 -481
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/animation-advanced.md +804 -804
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/core-animation-bridge.md +553 -553
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/SKILL.md +450 -450
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/references/gesture-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/SKILL.md +336 -336
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/form.md +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/grids.md +69 -69
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/list.md +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/scrollview.md +147 -147
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/SKILL.md +325 -325
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/references/liquid-glass.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/SKILL.md +262 -262
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/deeplinks.md +207 -207
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/navigationstack.md +177 -177
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/sheets.md +169 -169
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/tabview.md +178 -178
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/SKILL.md +381 -381
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/architecture-patterns.md +486 -486
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/deprecated-migration.md +1097 -1097
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/design-polish.md +780 -780
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/platform-and-sharing.md +696 -696
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +46 -46
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +29 -29
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-hangs-in-your-app.md +33 -33
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-improving-swiftui-performance.md +52 -52
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/SKILL.md +428 -428
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/hosting-migration.md +534 -534
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/representable-recipes.md +1133 -1133
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/SKILL.md +494 -494
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/references/tipkit-patterns.md +782 -782
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/SKILL.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/vision-requests.md +736 -736
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/visionkit-scanner.md +738 -738
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/SKILL.md +410 -410
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/references/weatherkit-patterns.md +567 -567
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/SKILL.md +497 -497
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/references/widgetkit-advanced.md +871 -871
- package/src/.agents/skills/ui-ux-pro-custom/data/typography.csv +57 -57
- package/src/.agents/skills/ui-ux-pro-custom/data/ui-reasoning.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/ux-guidelines.csv +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/web-interface.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/scripts/core.py +253 -253
- package/src/.agents/skills/ui-ux-pro-custom/scripts/design_system.py +1067 -1067
- package/src/.agents/skills/ui-ux-pro-custom/scripts/search.py +114 -114
- package/src/.agents/skills/ux-audit/SKILL.md +150 -150
- package/src/.agents/skills/websocket-engineer/SKILL.md +168 -168
- package/src/.agents/skills/websocket-engineer/references/alternatives.md +391 -391
- package/src/.agents/skills/websocket-engineer/references/patterns.md +400 -400
- package/src/.agents/skills/websocket-engineer/references/protocol.md +195 -195
- package/src/.agents/skills/websocket-engineer/references/scaling.md +333 -333
- package/src/.agents/skills/websocket-engineer/references/security.md +474 -474
- package/src/.agents/skills/writing-skills/SKILL.md +655 -655
- package/src/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -1150
- package/src/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/src/.agents/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/src/.agents/skills/writing-skills/persuasion-principles.md +187 -187
- package/src/.agents/skills/writing-skills/render-graphs.js +168 -168
- package/src/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -384
- package/src/.claude/commands/master-orchestrator.md +15 -0
- package/src/_memory/config.yaml +11 -11
- package/src/_memory/master-orchestrator-sidecar/instructions.md +97 -47
- package/src/_memory/skills/nimbalyst-tracking/SKILL.md +103 -103
- package/src/_memory/skills/writing-skills/SKILL.md +655 -655
- package/src/bmb/agents/agent-builder.md +59 -59
- package/src/bmb/agents/module-builder.md +60 -60
- package/src/bmb/agents/workflow-builder.md +61 -61
- package/src/bmb/config.yaml +12 -12
- package/src/bmb/module-help.csv +13 -13
- package/src/bmb/workflows/agent/data/agent-architecture.md +258 -258
- package/src/bmb/workflows/agent/data/agent-compilation.md +185 -185
- package/src/bmb/workflows/agent/data/agent-menu-patterns.md +189 -189
- package/src/bmb/workflows/agent/data/agent-metadata.md +133 -133
- package/src/bmb/workflows/agent/data/agent-validation.md +111 -111
- package/src/bmb/workflows/agent/data/brainstorm-context.md +96 -96
- package/src/bmb/workflows/agent/data/communication-presets.csv +61 -61
- package/src/bmb/workflows/agent/data/critical-actions.md +75 -75
- package/src/bmb/workflows/agent/data/persona-properties.md +252 -252
- package/src/bmb/workflows/agent/data/principles-crafting.md +142 -142
- package/src/bmb/workflows/agent/data/reference/module-examples/architect.md +68 -68
- package/src/bmb/workflows/agent/data/reference/with-sidecar/journal-keeper/journal-keeper-sidecar/entries/yy-mm-dd-entry-template.md +16 -16
- package/src/bmb/workflows/agent/data/understanding-agent-types.md +126 -126
- package/src/bmb/workflows/agent/steps-c/step-01-brainstorm.md +129 -129
- package/src/bmb/workflows/agent/steps-c/step-02-discovery.md +170 -170
- package/src/bmb/workflows/agent/steps-c/step-03-sidecar-metadata.md +309 -309
- package/src/bmb/workflows/agent/steps-c/step-04-persona.md +213 -213
- package/src/bmb/workflows/agent/steps-c/step-05-commands-menu.md +179 -179
- package/src/bmb/workflows/agent/steps-c/step-06-activation.md +278 -278
- package/src/bmb/workflows/agent/steps-c/step-07-build-agent.md +316 -316
- package/src/bmb/workflows/agent/steps-c/step-08-celebrate.md +247 -247
- package/src/bmb/workflows/agent/steps-e/e-01-load-existing.md +221 -221
- package/src/bmb/workflows/agent/steps-e/e-02-discover-edits.md +195 -195
- package/src/bmb/workflows/agent/steps-e/e-04-sidecar-metadata.md +126 -126
- package/src/bmb/workflows/agent/steps-e/e-05-persona.md +135 -135
- package/src/bmb/workflows/agent/steps-e/e-06-commands-menu.md +123 -123
- package/src/bmb/workflows/agent/steps-e/e-07-activation.md +124 -124
- package/src/bmb/workflows/agent/steps-e/e-08-edit-agent.md +197 -197
- package/src/bmb/workflows/agent/steps-e/e-09-celebrate.md +155 -155
- package/src/bmb/workflows/agent/steps-v/v-01-load-review.md +137 -137
- package/src/bmb/workflows/agent/steps-v/v-02a-validate-metadata.md +116 -116
- package/src/bmb/workflows/agent/steps-v/v-02b-validate-persona.md +124 -124
- package/src/bmb/workflows/agent/steps-v/v-02c-validate-menu.md +127 -127
- package/src/bmb/workflows/agent/steps-v/v-02d-validate-structure.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-02e-validate-sidecar.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-03-summary.md +104 -104
- package/src/bmb/workflows/agent/templates/agent-plan.template.md +5 -5
- package/src/bmb/workflows/agent/templates/agent-template.md +89 -89
- package/src/bmb/workflows/agent/workflow-create-agent.md +72 -72
- package/src/bmb/workflows/agent/workflow-edit-agent.md +75 -75
- package/src/bmb/workflows/agent/workflow-validate-agent.md +73 -73
- package/src/bmb/workflows/module/data/agent-architecture.md +179 -179
- package/src/bmb/workflows/module/data/agent-spec-template.md +79 -79
- package/src/bmb/workflows/module/data/module-standards.md +263 -263
- package/src/bmb/workflows/module/data/module-yaml-conventions.md +392 -392
- package/src/bmb/workflows/module/module-help-generate.md +254 -254
- package/src/bmb/workflows/module/steps-b/step-01-welcome.md +148 -148
- package/src/bmb/workflows/module/steps-b/step-02-spark.md +141 -141
- package/src/bmb/workflows/module/steps-b/step-03-module-type.md +149 -149
- package/src/bmb/workflows/module/steps-b/step-04-vision.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-05-identity.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-06-users.md +86 -86
- package/src/bmb/workflows/module/steps-b/step-07-value.md +76 -76
- package/src/bmb/workflows/module/steps-b/step-08-agents.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-09-workflows.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-10-tools.md +91 -91
- package/src/bmb/workflows/module/steps-b/step-11-scenarios.md +84 -84
- package/src/bmb/workflows/module/steps-b/step-12-creative.md +95 -95
- package/src/bmb/workflows/module/steps-b/step-13-review.md +105 -105
- package/src/bmb/workflows/module/steps-b/step-14-finalize.md +117 -117
- package/src/bmb/workflows/module/steps-c/step-01-load-brief.md +179 -179
- package/src/bmb/workflows/module/steps-c/step-01b-continue.md +82 -82
- package/src/bmb/workflows/module/steps-c/step-02-structure.md +105 -105
- package/src/bmb/workflows/module/steps-c/step-03-config.md +119 -119
- package/src/bmb/workflows/module/steps-c/step-04-agents.md +168 -168
- package/src/bmb/workflows/module/steps-c/step-05-workflows.md +184 -184
- package/src/bmb/workflows/module/steps-c/step-06-docs.md +401 -401
- package/src/bmb/workflows/module/steps-c/step-07-complete.md +152 -152
- package/src/bmb/workflows/module/steps-e/step-01-load-target.md +81 -81
- package/src/bmb/workflows/module/steps-e/step-02-select-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-03-apply-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-04-review.md +80 -80
- package/src/bmb/workflows/module/steps-e/step-05-confirm.md +75 -75
- package/src/bmb/workflows/module/steps-v/step-01-load-target.md +96 -96
- package/src/bmb/workflows/module/steps-v/step-02-file-structure.md +93 -93
- package/src/bmb/workflows/module/steps-v/step-03-module-yaml.md +99 -99
- package/src/bmb/workflows/module/steps-v/step-04-agent-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-05-workflow-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-06-documentation.md +143 -143
- package/src/bmb/workflows/module/steps-v/step-07-installation.md +102 -102
- package/src/bmb/workflows/module/steps-v/step-08-report.md +197 -197
- package/src/bmb/workflows/module/templates/brief-template.md +154 -154
- package/src/bmb/workflows/module/templates/workflow-spec-template.md +96 -96
- package/src/bmb/workflows/module/workflow-create-module-brief.md +71 -71
- package/src/bmb/workflows/module/workflow-create-module.md +86 -86
- package/src/bmb/workflows/module/workflow-edit-module.md +66 -66
- package/src/bmb/workflows/module/workflow-validate-module.md +66 -66
- package/src/bmb/workflows/workflow/data/architecture.md +150 -150
- package/src/bmb/workflows/workflow/data/common-workflow-tools.csv +19 -19
- package/src/bmb/workflows/workflow/data/csv-data-file-standards.md +53 -53
- package/src/bmb/workflows/workflow/data/frontmatter-standards.md +184 -184
- package/src/bmb/workflows/workflow/data/input-discovery-standards.md +191 -191
- package/src/bmb/workflows/workflow/data/intent-vs-prescriptive-spectrum.md +44 -44
- package/src/bmb/workflows/workflow/data/menu-handling-standards.md +133 -133
- package/src/bmb/workflows/workflow/data/output-format-standards.md +135 -135
- package/src/bmb/workflows/workflow/data/step-file-rules.md +235 -235
- package/src/bmb/workflows/workflow/data/step-type-patterns.md +257 -257
- package/src/bmb/workflows/workflow/data/subprocess-optimization-patterns.md +188 -188
- package/src/bmb/workflows/workflow/data/trimodal-workflow-structure.md +164 -164
- package/src/bmb/workflows/workflow/data/workflow-chaining-standards.md +222 -222
- package/src/bmb/workflows/workflow/data/workflow-examples.md +232 -232
- package/src/bmb/workflows/workflow/data/workflow-type-criteria.md +134 -134
- package/src/bmb/workflows/workflow/steps-c/step-00-conversion.md +263 -263
- package/src/bmb/workflows/workflow/steps-c/step-01-discovery.md +194 -194
- package/src/bmb/workflows/workflow/steps-c/step-01b-continuation.md +3 -3
- package/src/bmb/workflows/workflow/steps-c/step-02-classification.md +270 -270
- package/src/bmb/workflows/workflow/steps-c/step-03-requirements.md +283 -283
- package/src/bmb/workflows/workflow/steps-c/step-04-tools.md +282 -282
- package/src/bmb/workflows/workflow/steps-c/step-05-plan-review.md +243 -243
- package/src/bmb/workflows/workflow/steps-c/step-06-design.md +330 -330
- package/src/bmb/workflows/workflow/steps-c/step-07-foundation.md +239 -239
- package/src/bmb/workflows/workflow/steps-c/step-08-build-step-01.md +379 -379
- package/src/bmb/workflows/workflow/steps-c/step-09-build-next-step.md +350 -350
- package/src/bmb/workflows/workflow/steps-c/step-10-confirmation.md +322 -322
- package/src/bmb/workflows/workflow/steps-c/step-11-completion.md +191 -191
- package/src/bmb/workflows/workflow/steps-e/step-e-01-assess-workflow.md +237 -237
- package/src/bmb/workflows/workflow/steps-e/step-e-02-discover-edits.md +251 -251
- package/src/bmb/workflows/workflow/steps-e/step-e-03-fix-validation.md +254 -254
- package/src/bmb/workflows/workflow/steps-e/step-e-04-direct-edit.md +277 -277
- package/src/bmb/workflows/workflow/steps-e/step-e-05-apply-edit.md +154 -154
- package/src/bmb/workflows/workflow/steps-e/step-e-06-validate-after.md +190 -190
- package/src/bmb/workflows/workflow/steps-e/step-e-07-complete.md +206 -206
- package/src/bmb/workflows/workflow/steps-v/step-01-validate-max-mode.md +109 -109
- package/src/bmb/workflows/workflow/steps-v/step-01-validate.md +221 -221
- package/src/bmb/workflows/workflow/steps-v/step-01b-structure.md +152 -152
- package/src/bmb/workflows/workflow/steps-v/step-02-frontmatter-validation.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-02b-path-violations.md +265 -265
- package/src/bmb/workflows/workflow/steps-v/step-03-menu-validation.md +164 -164
- package/src/bmb/workflows/workflow/steps-v/step-04-step-type-validation.md +211 -211
- package/src/bmb/workflows/workflow/steps-v/step-05-output-format-validation.md +200 -200
- package/src/bmb/workflows/workflow/steps-v/step-06-validation-design-check.md +195 -195
- package/src/bmb/workflows/workflow/steps-v/step-07-instruction-style-check.md +209 -209
- package/src/bmb/workflows/workflow/steps-v/step-08-collaborative-experience-check.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-08b-subprocess-optimization.md +179 -179
- package/src/bmb/workflows/workflow/steps-v/step-09-cohesive-review.md +186 -186
- package/src/bmb/workflows/workflow/steps-v/step-10-report-complete.md +154 -154
- package/src/bmb/workflows/workflow/steps-v/step-11-plan-validation.md +237 -237
- package/src/bmb/workflows/workflow/templates/minimal-output-template.md +11 -11
- package/src/bmb/workflows/workflow/templates/step-01-init-continuable-template.md +241 -241
- package/src/bmb/workflows/workflow/templates/step-1b-template.md +224 -224
- package/src/bmb/workflows/workflow/templates/step-template.md +294 -294
- package/src/bmb/workflows/workflow/templates/workflow-template.md +102 -102
- package/src/bmb/workflows/workflow/workflow-create-workflow.md +79 -79
- package/src/bmb/workflows/workflow/workflow-edit-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-rework-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-validate-max-parallel-workflow.md +66 -66
- package/src/bmb/workflows/workflow/workflow-validate-workflow.md +65 -65
- package/src/bmm/agents/analyst.md +104 -104
- package/src/bmm/agents/dev.md +100 -100
- package/src/bmm/agents/qa.md +100 -90
- package/src/bmm/agents/tech-writer/tech-writer.md +94 -94
- package/src/bmm/module-help.csv +31 -31
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +115 -115
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +107 -107
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +141 -141
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +144 -144
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +147 -147
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +161 -161
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +99 -99
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -57
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +156 -156
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +165 -165
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +140 -140
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +152 -152
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +345 -345
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +92 -92
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +164 -164
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +174 -174
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +184 -184
- package/src/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +105 -105
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +360 -360
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +165 -165
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +174 -174
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +141 -141
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +159 -159
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +387 -387
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -54
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +100 -100
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +160 -160
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +88 -88
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +99 -99
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +169 -169
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +156 -156
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +176 -176
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +184 -184
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +174 -174
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +175 -175
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +189 -189
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +162 -162
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +79 -79
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +183 -183
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +149 -149
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +187 -187
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +108 -108
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +166 -166
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +131 -131
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +150 -150
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +155 -155
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +170 -170
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +158 -158
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +147 -147
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +182 -182
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +202 -202
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +148 -148
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +201 -201
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +179 -179
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +164 -164
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +106 -106
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +111 -111
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +115 -115
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +127 -127
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +167 -167
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +143 -143
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +154 -154
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +165 -165
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +135 -135
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +101 -101
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +45 -45
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +185 -185
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +130 -130
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +93 -93
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +196 -196
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -54
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +82 -82
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +106 -106
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +138 -138
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +129 -129
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +166 -166
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +186 -186
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +163 -163
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +38 -38
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -49
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +124 -124
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +122 -122
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +84 -84
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -58
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +43 -43
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +53 -53
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +159 -159
- package/src/bmm/workflows/4-implementation/create-story/template.md +79 -79
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +20 -20
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -25
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +158 -158
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +122 -122
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +87 -87
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -146
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -50
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +152 -152
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +123 -123
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +201 -201
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -79
- package/src/bmm/workflows/document-project/workflow.yaml +22 -22
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -184
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +322 -322
- package/src/bmm/workflows/generate-project-context/steps/step-03-complete.md +235 -235
- package/src/bmm/workflows/generate-project-context/workflow.md +49 -49
- package/src/bmm/workflows/qa/automate/workflow.yaml +233 -233
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +42 -42
- package/src/core/config.yaml +9 -9
- package/src/core/module-help.csv +10 -10
- package/src/core/scripts/generate-loop-report.py +72 -72
- package/src/core/tasks/editorial-review-prose.xml +101 -101
- package/src/core/tasks/editorial-review-structure.xml +207 -207
- package/src/core/tasks/help.md +86 -86
- package/src/core/tasks/index-docs.xml +64 -64
- package/src/core/tasks/review-adversarial-general.xml +66 -66
- package/src/core/tasks/review-adversarial-loop.xml +46 -46
- package/src/core/tasks/review-edge-case-hunter.xml +63 -63
- package/src/core/tasks/review-party-loop.xml +46 -46
- package/src/core/tasks/shard-doc.xml +107 -107
- package/src/core/tasks/workflow.xml +235 -235
- package/src/core/templates/review-loop-report.html +88 -88
- package/src/core/templates/review-loop-report.md +5 -5
- package/src/core/workflows/advanced-elicitation/workflow.xml +117 -117
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +212 -212
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -122
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -225
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -237
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -209
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -264
- package/src/core/workflows/brainstorming/steps/step-02e-deep-dive.md +68 -68
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +403 -403
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -303
- package/src/core/workflows/brainstorming/workflow.md +60 -60
- package/src/core/workflows/extract-trackers/workflow.md +45 -45
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +142 -142
- package/src/core/workflows/party-mode/workflow.md +194 -194
- package/src/docs/dev/tmux/actions_popup.py +291 -291
- package/src/docs/dev/tmux/tmux-setup.md +62 -1
|
@@ -1,505 +1,505 @@
|
|
|
1
|
-
# Swift Patterns Extended Reference
|
|
2
|
-
|
|
3
|
-
Additional patterns and examples that extend the core SKILL.md. Refer to this file for deeper Codable patterns, advanced result builder techniques, and supplementary collection/formatting recipes.
|
|
4
|
-
|
|
5
|
-
## Contents
|
|
6
|
-
|
|
7
|
-
- [Codable: Enums with Associated Values](#codable-enums-with-associated-values)
|
|
8
|
-
- [Codable: Date Decoding Strategies](#codable-date-decoding-strategies)
|
|
9
|
-
- [Codable: Unkeyed Containers (Arrays)](#codable-unkeyed-containers-arrays)
|
|
10
|
-
- [Codable: Wrapper for Lossy Array Decoding](#codable-wrapper-for-lossy-array-decoding)
|
|
11
|
-
- [Codable: @dynamicMemberLookup Wrapper](#codable-dynamicmemberlookup-wrapper)
|
|
12
|
-
- [Result Builder: HTML Builder](#result-builder-html-builder)
|
|
13
|
-
- [Result Builder: buildFinalResult](#result-builder-buildfinalresult)
|
|
14
|
-
- [Property Wrapper: UserDefaults-Backed](#property-wrapper-userdefaults-backed)
|
|
15
|
-
- [Property Wrapper: Validated](#property-wrapper-validated)
|
|
16
|
-
- [Advanced Regex Builder Patterns](#advanced-regex-builder-patterns)
|
|
17
|
-
- [FormatStyle: Custom FormatStyle](#formatstyle-custom-formatstyle)
|
|
18
|
-
- [Collection Patterns: Chunking and Windows](#collection-patterns-chunking-and-windows)
|
|
19
|
-
- [Guard: Complex Pattern Matching](#guard-complex-pattern-matching)
|
|
20
|
-
- [Typed Throws: Protocol with Typed Errors](#typed-throws-protocol-with-typed-errors)
|
|
21
|
-
- [String Interpolation: Custom appendInterpolation](#string-interpolation-custom-appendinterpolation)
|
|
22
|
-
- [Never: Advanced Usage](#never-advanced-usage)
|
|
23
|
-
|
|
24
|
-
## Codable: Enums with Associated Values
|
|
25
|
-
|
|
26
|
-
```swift
|
|
27
|
-
enum Shape: Codable {
|
|
28
|
-
case circle(radius: Double)
|
|
29
|
-
case rectangle(width: Double, height: Double)
|
|
30
|
-
|
|
31
|
-
enum CodingKeys: String, CodingKey {
|
|
32
|
-
case type, radius, width, height
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
func encode(to encoder: Encoder) throws {
|
|
36
|
-
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
37
|
-
switch self {
|
|
38
|
-
case .circle(let radius):
|
|
39
|
-
try container.encode("circle", forKey: .type)
|
|
40
|
-
try container.encode(radius, forKey: .radius)
|
|
41
|
-
case .rectangle(let width, let height):
|
|
42
|
-
try container.encode("rectangle", forKey: .type)
|
|
43
|
-
try container.encode(width, forKey: .width)
|
|
44
|
-
try container.encode(height, forKey: .height)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
init(from decoder: Decoder) throws {
|
|
49
|
-
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
50
|
-
let type = try container.decode(String.self, forKey: .type)
|
|
51
|
-
switch type {
|
|
52
|
-
case "circle":
|
|
53
|
-
let radius = try container.decode(Double.self, forKey: .radius)
|
|
54
|
-
self = .circle(radius: radius)
|
|
55
|
-
case "rectangle":
|
|
56
|
-
let width = try container.decode(Double.self, forKey: .width)
|
|
57
|
-
let height = try container.decode(Double.self, forKey: .height)
|
|
58
|
-
self = .rectangle(width: width, height: height)
|
|
59
|
-
default:
|
|
60
|
-
throw DecodingError.dataCorruptedError(
|
|
61
|
-
forKey: .type, in: container,
|
|
62
|
-
debugDescription: "Unknown shape type: \(type)")
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Codable: Date Decoding Strategies
|
|
69
|
-
|
|
70
|
-
```swift
|
|
71
|
-
// Configure decoder for specific date formats
|
|
72
|
-
let decoder = JSONDecoder()
|
|
73
|
-
|
|
74
|
-
// ISO 8601 (most common for APIs)
|
|
75
|
-
decoder.dateDecodingStrategy = .iso8601
|
|
76
|
-
|
|
77
|
-
// Unix timestamp (seconds since epoch)
|
|
78
|
-
decoder.dateDecodingStrategy = .secondsSince1970
|
|
79
|
-
|
|
80
|
-
// Custom format
|
|
81
|
-
let formatter = DateFormatter()
|
|
82
|
-
formatter.dateFormat = "yyyy-MM-dd"
|
|
83
|
-
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
84
|
-
decoder.dateDecodingStrategy = .formatted(formatter)
|
|
85
|
-
|
|
86
|
-
// Multiple formats in one payload
|
|
87
|
-
decoder.dateDecodingStrategy = .custom { decoder in
|
|
88
|
-
let container = try decoder.singleValueContainer()
|
|
89
|
-
let string = try container.decode(String.self)
|
|
90
|
-
|
|
91
|
-
let iso = ISO8601DateFormatter()
|
|
92
|
-
if let date = iso.date(from: string) { return date }
|
|
93
|
-
|
|
94
|
-
let fallback = DateFormatter()
|
|
95
|
-
fallback.dateFormat = "yyyy-MM-dd"
|
|
96
|
-
fallback.locale = Locale(identifier: "en_US_POSIX")
|
|
97
|
-
if let date = fallback.date(from: string) { return date }
|
|
98
|
-
|
|
99
|
-
throw DecodingError.dataCorruptedError(
|
|
100
|
-
in: container, debugDescription: "Cannot decode date: \(string)")
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Codable: Unkeyed Containers (Arrays)
|
|
105
|
-
|
|
106
|
-
```swift
|
|
107
|
-
// JSON: { "coordinates": [37.7749, -122.4194] }
|
|
108
|
-
struct Location: Decodable {
|
|
109
|
-
let latitude: Double
|
|
110
|
-
let longitude: Double
|
|
111
|
-
|
|
112
|
-
enum CodingKeys: String, CodingKey {
|
|
113
|
-
case coordinates
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
init(from decoder: Decoder) throws {
|
|
117
|
-
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
118
|
-
var coords = try container.nestedUnkeyedContainer(forKey: .coordinates)
|
|
119
|
-
latitude = try coords.decode(Double.self)
|
|
120
|
-
longitude = try coords.decode(Double.self)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Codable: Wrapper for Lossy Array Decoding
|
|
126
|
-
|
|
127
|
-
Skip invalid elements instead of failing the entire array:
|
|
128
|
-
|
|
129
|
-
```swift
|
|
130
|
-
struct LossyArray<Element: Decodable>: Decodable {
|
|
131
|
-
let elements: [Element]
|
|
132
|
-
|
|
133
|
-
init(from decoder: Decoder) throws {
|
|
134
|
-
var container = try decoder.unkeyedContainer()
|
|
135
|
-
var result: [Element] = []
|
|
136
|
-
while !container.isAtEnd {
|
|
137
|
-
if let element = try? container.decode(Element.self) {
|
|
138
|
-
result.append(element)
|
|
139
|
-
} else {
|
|
140
|
-
_ = try? container.decode(AnyCodable.self) // skip invalid
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
elements = result
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private struct AnyCodable: Decodable {}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Codable: @dynamicMemberLookup Wrapper
|
|
151
|
-
|
|
152
|
-
Type-safe access to arbitrary JSON:
|
|
153
|
-
|
|
154
|
-
```swift
|
|
155
|
-
@dynamicMemberLookup
|
|
156
|
-
struct JSONValue: Decodable {
|
|
157
|
-
private let storage: [String: Any]
|
|
158
|
-
|
|
159
|
-
subscript(dynamicMember key: String) -> JSONValue? {
|
|
160
|
-
guard let value = storage[key] as? [String: Any] else { return nil }
|
|
161
|
-
return JSONValue(storage: value)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
func string(for key: String) -> String? {
|
|
165
|
-
storage[key] as? String
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
func int(for key: String) -> Int? {
|
|
169
|
-
storage[key] as? Int
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
init(from decoder: Decoder) throws {
|
|
173
|
-
let container = try decoder.singleValueContainer()
|
|
174
|
-
guard let dict = try container.decode([String: AnyCodableValue].self)
|
|
175
|
-
.mapValues({ $0.value }) as? [String: Any] else {
|
|
176
|
-
throw DecodingError.typeMismatch(
|
|
177
|
-
[String: Any].self,
|
|
178
|
-
.init(codingPath: decoder.codingPath,
|
|
179
|
-
debugDescription: "Expected dictionary"))
|
|
180
|
-
}
|
|
181
|
-
storage = dict
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
## Result Builder: HTML Builder
|
|
187
|
-
|
|
188
|
-
A practical example of a custom result builder:
|
|
189
|
-
|
|
190
|
-
```swift
|
|
191
|
-
@resultBuilder
|
|
192
|
-
struct HTMLBuilder {
|
|
193
|
-
static func buildBlock(_ components: String...) -> String {
|
|
194
|
-
components.joined(separator: "\n")
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
static func buildOptional(_ component: String?) -> String {
|
|
198
|
-
component ?? ""
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
static func buildEither(first component: String) -> String {
|
|
202
|
-
component
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
static func buildEither(second component: String) -> String {
|
|
206
|
-
component
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
static func buildArray(_ components: [String]) -> String {
|
|
210
|
-
components.joined(separator: "\n")
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
func div(@HTMLBuilder content: () -> String) -> String {
|
|
215
|
-
"<div>\n\(content())\n</div>"
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
func p(_ text: String) -> String { "<p>\(text)</p>" }
|
|
219
|
-
func h1(_ text: String) -> String { "<h1>\(text)</h1>" }
|
|
220
|
-
|
|
221
|
-
let html = div {
|
|
222
|
-
h1("Welcome")
|
|
223
|
-
p("Hello, world!")
|
|
224
|
-
if showDetails {
|
|
225
|
-
p("Details here")
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Result Builder: buildFinalResult
|
|
231
|
-
|
|
232
|
-
Transform the accumulated result at the end:
|
|
233
|
-
|
|
234
|
-
```swift
|
|
235
|
-
@resultBuilder
|
|
236
|
-
struct AttributedStringBuilder {
|
|
237
|
-
static func buildBlock(_ components: AttributedString...) -> AttributedString {
|
|
238
|
-
components.reduce(into: AttributedString()) { $0.append($1) }
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
static func buildFinalResult(_ component: AttributedString) -> Text {
|
|
242
|
-
Text(component)
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Property Wrapper: UserDefaults-Backed
|
|
248
|
-
|
|
249
|
-
```swift
|
|
250
|
-
@propertyWrapper
|
|
251
|
-
struct AppStorage<Value> {
|
|
252
|
-
let key: String
|
|
253
|
-
let defaultValue: Value
|
|
254
|
-
let store: UserDefaults
|
|
255
|
-
|
|
256
|
-
var wrappedValue: Value {
|
|
257
|
-
get { store.object(forKey: key) as? Value ?? defaultValue }
|
|
258
|
-
set { store.set(newValue, forKey: key) }
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
init(wrappedValue: Value, _ key: String, store: UserDefaults = .standard) {
|
|
262
|
-
self.key = key
|
|
263
|
-
self.defaultValue = wrappedValue
|
|
264
|
-
self.store = store
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Usage
|
|
269
|
-
struct Settings {
|
|
270
|
-
@AppStorage("onboarding_complete") var onboardingComplete = false
|
|
271
|
-
@AppStorage("preferred_theme") var theme = "system"
|
|
272
|
-
}
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## Property Wrapper: Validated
|
|
276
|
-
|
|
277
|
-
```swift
|
|
278
|
-
@propertyWrapper
|
|
279
|
-
struct Validated<Value> {
|
|
280
|
-
private var value: Value
|
|
281
|
-
private let validator: (Value) -> Bool
|
|
282
|
-
private(set) var isValid: Bool
|
|
283
|
-
|
|
284
|
-
var wrappedValue: Value {
|
|
285
|
-
get { value }
|
|
286
|
-
set {
|
|
287
|
-
value = newValue
|
|
288
|
-
isValid = validator(newValue)
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
var projectedValue: Bool { isValid }
|
|
293
|
-
|
|
294
|
-
init(wrappedValue: Value, _ validator: @escaping (Value) -> Bool) {
|
|
295
|
-
self.value = wrappedValue
|
|
296
|
-
self.validator = validator
|
|
297
|
-
self.isValid = validator(wrappedValue)
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Usage
|
|
302
|
-
struct SignUpForm {
|
|
303
|
-
@Validated({ $0.count >= 3 }) var username = ""
|
|
304
|
-
@Validated({ $0.contains("@") && $0.contains(".") }) var email = ""
|
|
305
|
-
|
|
306
|
-
var canSubmit: Bool { $username && $email }
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
## Advanced Regex Builder Patterns
|
|
311
|
-
|
|
312
|
-
### Named captures with strong typing
|
|
313
|
-
|
|
314
|
-
```swift
|
|
315
|
-
import RegexBuilder
|
|
316
|
-
|
|
317
|
-
struct LogEntry {
|
|
318
|
-
let timestamp: String
|
|
319
|
-
let level: String
|
|
320
|
-
let message: String
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
let logRegex = Regex {
|
|
324
|
-
Capture(as: Reference<Substring>(\.self)) { /\[.+?\]/ }
|
|
325
|
-
" "
|
|
326
|
-
Capture(as: Reference<Substring>(\.self)) {
|
|
327
|
-
ChoiceOf { "INFO"; "WARN"; "ERROR"; "DEBUG" }
|
|
328
|
-
}
|
|
329
|
-
": "
|
|
330
|
-
Capture(as: Reference<Substring>(\.self)) { OneOrMore(.any) }
|
|
331
|
-
}
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Reusing regex components
|
|
335
|
-
|
|
336
|
-
```swift
|
|
337
|
-
let ipOctet = Regex {
|
|
338
|
-
ChoiceOf {
|
|
339
|
-
Regex { "25"; ("0"..."5") }
|
|
340
|
-
Regex { "2"; ("0"..."4"); .digit }
|
|
341
|
-
Regex { Optionally { ("0"..."1") }; .digit; Optionally { .digit } }
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
let ipAddress = Regex {
|
|
346
|
-
ipOctet; "."; ipOctet; "."; ipOctet; "."; ipOctet
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
## FormatStyle: Custom FormatStyle
|
|
351
|
-
|
|
352
|
-
Create reusable format styles for domain types:
|
|
353
|
-
|
|
354
|
-
```swift
|
|
355
|
-
struct FileSize {
|
|
356
|
-
let bytes: Int64
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
struct FileSizeFormatStyle: FormatStyle {
|
|
360
|
-
typealias FormatInput = FileSize
|
|
361
|
-
typealias FormatOutput = String
|
|
362
|
-
|
|
363
|
-
func format(_ value: FileSize) -> String {
|
|
364
|
-
ByteCountFormatter.string(fromByteCount: value.bytes, countStyle: .file)
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
extension FormatStyle where Self == FileSizeFormatStyle {
|
|
369
|
-
static var fileSize: FileSizeFormatStyle { .init() }
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Usage
|
|
373
|
-
let size = FileSize(bytes: 1_500_000)
|
|
374
|
-
size.formatted(.fileSize) // "1.5 MB"
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
## Collection Patterns: Chunking and Windows
|
|
378
|
-
|
|
379
|
-
```swift
|
|
380
|
-
// chunks(ofCount:) -- Swift Algorithms package
|
|
381
|
-
import Algorithms
|
|
382
|
-
|
|
383
|
-
let batches = items.chunks(ofCount: 10)
|
|
384
|
-
for batch in batches {
|
|
385
|
-
try await upload(batch)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// windows(ofCount:) -- sliding window
|
|
389
|
-
let movingAverages = values.windows(ofCount: 3).map { window in
|
|
390
|
-
window.reduce(0, +) / Double(window.count)
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// adjacentPairs() -- process consecutive elements
|
|
394
|
-
for (previous, current) in values.adjacentPairs() {
|
|
395
|
-
if current > previous * 2 {
|
|
396
|
-
print("Spike detected")
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
## Guard: Complex Pattern Matching
|
|
402
|
-
|
|
403
|
-
```swift
|
|
404
|
-
func processResponse(_ data: Data) throws -> User {
|
|
405
|
-
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
406
|
-
let userData = json["user"] as? [String: Any],
|
|
407
|
-
let name = userData["name"] as? String,
|
|
408
|
-
let id = userData["id"] as? Int
|
|
409
|
-
else {
|
|
410
|
-
throw ParseError.invalidFormat
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Use Codable instead when practical -- this is for mixed/dynamic JSON
|
|
414
|
-
return User(id: id, name: name)
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Guard with where clause
|
|
418
|
-
func processItems(_ items: [Item]) {
|
|
419
|
-
for item in items {
|
|
420
|
-
guard case .active(let config) = item.status,
|
|
421
|
-
config.isEnabled,
|
|
422
|
-
!config.isExpired
|
|
423
|
-
else { continue }
|
|
424
|
-
|
|
425
|
-
activate(item, with: config)
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
## Typed Throws: Protocol with Typed Errors
|
|
431
|
-
|
|
432
|
-
```swift
|
|
433
|
-
protocol DataStore {
|
|
434
|
-
associatedtype StoreError: Error
|
|
435
|
-
func save(_ data: Data) throws(StoreError)
|
|
436
|
-
func load(id: String) throws(StoreError) -> Data
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
struct FileStore: DataStore {
|
|
440
|
-
enum StoreError: Error {
|
|
441
|
-
case notFound, permissionDenied, diskFull
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
func save(_ data: Data) throws(StoreError) {
|
|
445
|
-
// ...
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
func load(id: String) throws(StoreError) -> Data {
|
|
449
|
-
guard fileExists(id) else { throw .notFound }
|
|
450
|
-
// ...
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
## String Interpolation: Custom appendInterpolation
|
|
456
|
-
|
|
457
|
-
Apple documents `DefaultStringInterpolation` as the type used while building interpolated strings, and supports extending it with custom `appendInterpolation(...)` overloads.
|
|
458
|
-
|
|
459
|
-
```swift
|
|
460
|
-
extension DefaultStringInterpolation {
|
|
461
|
-
mutating func appendInterpolation(json value: some Encodable) {
|
|
462
|
-
let encoder = JSONEncoder()
|
|
463
|
-
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
|
|
464
|
-
if let data = try? encoder.encode(value),
|
|
465
|
-
let string = String(data: data, encoding: .utf8) {
|
|
466
|
-
appendLiteral(string)
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
mutating func appendInterpolation(ordinal value: Int) {
|
|
471
|
-
let formatter = NumberFormatter()
|
|
472
|
-
formatter.numberStyle = .ordinal
|
|
473
|
-
if let result = formatter.string(from: value as NSNumber) {
|
|
474
|
-
appendLiteral(result)
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
print("Config: \(json: settings)")
|
|
480
|
-
print("You placed \(ordinal: 3)")
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Never: Advanced Usage
|
|
484
|
-
|
|
485
|
-
```swift
|
|
486
|
-
// Publisher that never fails
|
|
487
|
-
let publisher: AnyPublisher<String, Never> = Just("hello").eraseToAnyPublisher()
|
|
488
|
-
|
|
489
|
-
// Phantom type preventing construction
|
|
490
|
-
enum Locked {}
|
|
491
|
-
enum Unlocked {}
|
|
492
|
-
|
|
493
|
-
struct Door<State> {
|
|
494
|
-
private init() {}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
extension Door where State == Unlocked {
|
|
498
|
-
func open() { /* ... */ }
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Generic constraint meaning "this case cannot happen"
|
|
502
|
-
func absurd<T>(_ never: Never) -> T {
|
|
503
|
-
// No body needed -- Never has no values, so this is never called
|
|
504
|
-
}
|
|
505
|
-
```
|
|
1
|
+
# Swift Patterns Extended Reference
|
|
2
|
+
|
|
3
|
+
Additional patterns and examples that extend the core SKILL.md. Refer to this file for deeper Codable patterns, advanced result builder techniques, and supplementary collection/formatting recipes.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Codable: Enums with Associated Values](#codable-enums-with-associated-values)
|
|
8
|
+
- [Codable: Date Decoding Strategies](#codable-date-decoding-strategies)
|
|
9
|
+
- [Codable: Unkeyed Containers (Arrays)](#codable-unkeyed-containers-arrays)
|
|
10
|
+
- [Codable: Wrapper for Lossy Array Decoding](#codable-wrapper-for-lossy-array-decoding)
|
|
11
|
+
- [Codable: @dynamicMemberLookup Wrapper](#codable-dynamicmemberlookup-wrapper)
|
|
12
|
+
- [Result Builder: HTML Builder](#result-builder-html-builder)
|
|
13
|
+
- [Result Builder: buildFinalResult](#result-builder-buildfinalresult)
|
|
14
|
+
- [Property Wrapper: UserDefaults-Backed](#property-wrapper-userdefaults-backed)
|
|
15
|
+
- [Property Wrapper: Validated](#property-wrapper-validated)
|
|
16
|
+
- [Advanced Regex Builder Patterns](#advanced-regex-builder-patterns)
|
|
17
|
+
- [FormatStyle: Custom FormatStyle](#formatstyle-custom-formatstyle)
|
|
18
|
+
- [Collection Patterns: Chunking and Windows](#collection-patterns-chunking-and-windows)
|
|
19
|
+
- [Guard: Complex Pattern Matching](#guard-complex-pattern-matching)
|
|
20
|
+
- [Typed Throws: Protocol with Typed Errors](#typed-throws-protocol-with-typed-errors)
|
|
21
|
+
- [String Interpolation: Custom appendInterpolation](#string-interpolation-custom-appendinterpolation)
|
|
22
|
+
- [Never: Advanced Usage](#never-advanced-usage)
|
|
23
|
+
|
|
24
|
+
## Codable: Enums with Associated Values
|
|
25
|
+
|
|
26
|
+
```swift
|
|
27
|
+
enum Shape: Codable {
|
|
28
|
+
case circle(radius: Double)
|
|
29
|
+
case rectangle(width: Double, height: Double)
|
|
30
|
+
|
|
31
|
+
enum CodingKeys: String, CodingKey {
|
|
32
|
+
case type, radius, width, height
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func encode(to encoder: Encoder) throws {
|
|
36
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
37
|
+
switch self {
|
|
38
|
+
case .circle(let radius):
|
|
39
|
+
try container.encode("circle", forKey: .type)
|
|
40
|
+
try container.encode(radius, forKey: .radius)
|
|
41
|
+
case .rectangle(let width, let height):
|
|
42
|
+
try container.encode("rectangle", forKey: .type)
|
|
43
|
+
try container.encode(width, forKey: .width)
|
|
44
|
+
try container.encode(height, forKey: .height)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
init(from decoder: Decoder) throws {
|
|
49
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
50
|
+
let type = try container.decode(String.self, forKey: .type)
|
|
51
|
+
switch type {
|
|
52
|
+
case "circle":
|
|
53
|
+
let radius = try container.decode(Double.self, forKey: .radius)
|
|
54
|
+
self = .circle(radius: radius)
|
|
55
|
+
case "rectangle":
|
|
56
|
+
let width = try container.decode(Double.self, forKey: .width)
|
|
57
|
+
let height = try container.decode(Double.self, forKey: .height)
|
|
58
|
+
self = .rectangle(width: width, height: height)
|
|
59
|
+
default:
|
|
60
|
+
throw DecodingError.dataCorruptedError(
|
|
61
|
+
forKey: .type, in: container,
|
|
62
|
+
debugDescription: "Unknown shape type: \(type)")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Codable: Date Decoding Strategies
|
|
69
|
+
|
|
70
|
+
```swift
|
|
71
|
+
// Configure decoder for specific date formats
|
|
72
|
+
let decoder = JSONDecoder()
|
|
73
|
+
|
|
74
|
+
// ISO 8601 (most common for APIs)
|
|
75
|
+
decoder.dateDecodingStrategy = .iso8601
|
|
76
|
+
|
|
77
|
+
// Unix timestamp (seconds since epoch)
|
|
78
|
+
decoder.dateDecodingStrategy = .secondsSince1970
|
|
79
|
+
|
|
80
|
+
// Custom format
|
|
81
|
+
let formatter = DateFormatter()
|
|
82
|
+
formatter.dateFormat = "yyyy-MM-dd"
|
|
83
|
+
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
84
|
+
decoder.dateDecodingStrategy = .formatted(formatter)
|
|
85
|
+
|
|
86
|
+
// Multiple formats in one payload
|
|
87
|
+
decoder.dateDecodingStrategy = .custom { decoder in
|
|
88
|
+
let container = try decoder.singleValueContainer()
|
|
89
|
+
let string = try container.decode(String.self)
|
|
90
|
+
|
|
91
|
+
let iso = ISO8601DateFormatter()
|
|
92
|
+
if let date = iso.date(from: string) { return date }
|
|
93
|
+
|
|
94
|
+
let fallback = DateFormatter()
|
|
95
|
+
fallback.dateFormat = "yyyy-MM-dd"
|
|
96
|
+
fallback.locale = Locale(identifier: "en_US_POSIX")
|
|
97
|
+
if let date = fallback.date(from: string) { return date }
|
|
98
|
+
|
|
99
|
+
throw DecodingError.dataCorruptedError(
|
|
100
|
+
in: container, debugDescription: "Cannot decode date: \(string)")
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Codable: Unkeyed Containers (Arrays)
|
|
105
|
+
|
|
106
|
+
```swift
|
|
107
|
+
// JSON: { "coordinates": [37.7749, -122.4194] }
|
|
108
|
+
struct Location: Decodable {
|
|
109
|
+
let latitude: Double
|
|
110
|
+
let longitude: Double
|
|
111
|
+
|
|
112
|
+
enum CodingKeys: String, CodingKey {
|
|
113
|
+
case coordinates
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
init(from decoder: Decoder) throws {
|
|
117
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
118
|
+
var coords = try container.nestedUnkeyedContainer(forKey: .coordinates)
|
|
119
|
+
latitude = try coords.decode(Double.self)
|
|
120
|
+
longitude = try coords.decode(Double.self)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Codable: Wrapper for Lossy Array Decoding
|
|
126
|
+
|
|
127
|
+
Skip invalid elements instead of failing the entire array:
|
|
128
|
+
|
|
129
|
+
```swift
|
|
130
|
+
struct LossyArray<Element: Decodable>: Decodable {
|
|
131
|
+
let elements: [Element]
|
|
132
|
+
|
|
133
|
+
init(from decoder: Decoder) throws {
|
|
134
|
+
var container = try decoder.unkeyedContainer()
|
|
135
|
+
var result: [Element] = []
|
|
136
|
+
while !container.isAtEnd {
|
|
137
|
+
if let element = try? container.decode(Element.self) {
|
|
138
|
+
result.append(element)
|
|
139
|
+
} else {
|
|
140
|
+
_ = try? container.decode(AnyCodable.self) // skip invalid
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
elements = result
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private struct AnyCodable: Decodable {}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Codable: @dynamicMemberLookup Wrapper
|
|
151
|
+
|
|
152
|
+
Type-safe access to arbitrary JSON:
|
|
153
|
+
|
|
154
|
+
```swift
|
|
155
|
+
@dynamicMemberLookup
|
|
156
|
+
struct JSONValue: Decodable {
|
|
157
|
+
private let storage: [String: Any]
|
|
158
|
+
|
|
159
|
+
subscript(dynamicMember key: String) -> JSONValue? {
|
|
160
|
+
guard let value = storage[key] as? [String: Any] else { return nil }
|
|
161
|
+
return JSONValue(storage: value)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
func string(for key: String) -> String? {
|
|
165
|
+
storage[key] as? String
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
func int(for key: String) -> Int? {
|
|
169
|
+
storage[key] as? Int
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
init(from decoder: Decoder) throws {
|
|
173
|
+
let container = try decoder.singleValueContainer()
|
|
174
|
+
guard let dict = try container.decode([String: AnyCodableValue].self)
|
|
175
|
+
.mapValues({ $0.value }) as? [String: Any] else {
|
|
176
|
+
throw DecodingError.typeMismatch(
|
|
177
|
+
[String: Any].self,
|
|
178
|
+
.init(codingPath: decoder.codingPath,
|
|
179
|
+
debugDescription: "Expected dictionary"))
|
|
180
|
+
}
|
|
181
|
+
storage = dict
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Result Builder: HTML Builder
|
|
187
|
+
|
|
188
|
+
A practical example of a custom result builder:
|
|
189
|
+
|
|
190
|
+
```swift
|
|
191
|
+
@resultBuilder
|
|
192
|
+
struct HTMLBuilder {
|
|
193
|
+
static func buildBlock(_ components: String...) -> String {
|
|
194
|
+
components.joined(separator: "\n")
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static func buildOptional(_ component: String?) -> String {
|
|
198
|
+
component ?? ""
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static func buildEither(first component: String) -> String {
|
|
202
|
+
component
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
static func buildEither(second component: String) -> String {
|
|
206
|
+
component
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static func buildArray(_ components: [String]) -> String {
|
|
210
|
+
components.joined(separator: "\n")
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
func div(@HTMLBuilder content: () -> String) -> String {
|
|
215
|
+
"<div>\n\(content())\n</div>"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
func p(_ text: String) -> String { "<p>\(text)</p>" }
|
|
219
|
+
func h1(_ text: String) -> String { "<h1>\(text)</h1>" }
|
|
220
|
+
|
|
221
|
+
let html = div {
|
|
222
|
+
h1("Welcome")
|
|
223
|
+
p("Hello, world!")
|
|
224
|
+
if showDetails {
|
|
225
|
+
p("Details here")
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Result Builder: buildFinalResult
|
|
231
|
+
|
|
232
|
+
Transform the accumulated result at the end:
|
|
233
|
+
|
|
234
|
+
```swift
|
|
235
|
+
@resultBuilder
|
|
236
|
+
struct AttributedStringBuilder {
|
|
237
|
+
static func buildBlock(_ components: AttributedString...) -> AttributedString {
|
|
238
|
+
components.reduce(into: AttributedString()) { $0.append($1) }
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static func buildFinalResult(_ component: AttributedString) -> Text {
|
|
242
|
+
Text(component)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Property Wrapper: UserDefaults-Backed
|
|
248
|
+
|
|
249
|
+
```swift
|
|
250
|
+
@propertyWrapper
|
|
251
|
+
struct AppStorage<Value> {
|
|
252
|
+
let key: String
|
|
253
|
+
let defaultValue: Value
|
|
254
|
+
let store: UserDefaults
|
|
255
|
+
|
|
256
|
+
var wrappedValue: Value {
|
|
257
|
+
get { store.object(forKey: key) as? Value ?? defaultValue }
|
|
258
|
+
set { store.set(newValue, forKey: key) }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
init(wrappedValue: Value, _ key: String, store: UserDefaults = .standard) {
|
|
262
|
+
self.key = key
|
|
263
|
+
self.defaultValue = wrappedValue
|
|
264
|
+
self.store = store
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Usage
|
|
269
|
+
struct Settings {
|
|
270
|
+
@AppStorage("onboarding_complete") var onboardingComplete = false
|
|
271
|
+
@AppStorage("preferred_theme") var theme = "system"
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Property Wrapper: Validated
|
|
276
|
+
|
|
277
|
+
```swift
|
|
278
|
+
@propertyWrapper
|
|
279
|
+
struct Validated<Value> {
|
|
280
|
+
private var value: Value
|
|
281
|
+
private let validator: (Value) -> Bool
|
|
282
|
+
private(set) var isValid: Bool
|
|
283
|
+
|
|
284
|
+
var wrappedValue: Value {
|
|
285
|
+
get { value }
|
|
286
|
+
set {
|
|
287
|
+
value = newValue
|
|
288
|
+
isValid = validator(newValue)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
var projectedValue: Bool { isValid }
|
|
293
|
+
|
|
294
|
+
init(wrappedValue: Value, _ validator: @escaping (Value) -> Bool) {
|
|
295
|
+
self.value = wrappedValue
|
|
296
|
+
self.validator = validator
|
|
297
|
+
self.isValid = validator(wrappedValue)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Usage
|
|
302
|
+
struct SignUpForm {
|
|
303
|
+
@Validated({ $0.count >= 3 }) var username = ""
|
|
304
|
+
@Validated({ $0.contains("@") && $0.contains(".") }) var email = ""
|
|
305
|
+
|
|
306
|
+
var canSubmit: Bool { $username && $email }
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Advanced Regex Builder Patterns
|
|
311
|
+
|
|
312
|
+
### Named captures with strong typing
|
|
313
|
+
|
|
314
|
+
```swift
|
|
315
|
+
import RegexBuilder
|
|
316
|
+
|
|
317
|
+
struct LogEntry {
|
|
318
|
+
let timestamp: String
|
|
319
|
+
let level: String
|
|
320
|
+
let message: String
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let logRegex = Regex {
|
|
324
|
+
Capture(as: Reference<Substring>(\.self)) { /\[.+?\]/ }
|
|
325
|
+
" "
|
|
326
|
+
Capture(as: Reference<Substring>(\.self)) {
|
|
327
|
+
ChoiceOf { "INFO"; "WARN"; "ERROR"; "DEBUG" }
|
|
328
|
+
}
|
|
329
|
+
": "
|
|
330
|
+
Capture(as: Reference<Substring>(\.self)) { OneOrMore(.any) }
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Reusing regex components
|
|
335
|
+
|
|
336
|
+
```swift
|
|
337
|
+
let ipOctet = Regex {
|
|
338
|
+
ChoiceOf {
|
|
339
|
+
Regex { "25"; ("0"..."5") }
|
|
340
|
+
Regex { "2"; ("0"..."4"); .digit }
|
|
341
|
+
Regex { Optionally { ("0"..."1") }; .digit; Optionally { .digit } }
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let ipAddress = Regex {
|
|
346
|
+
ipOctet; "."; ipOctet; "."; ipOctet; "."; ipOctet
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## FormatStyle: Custom FormatStyle
|
|
351
|
+
|
|
352
|
+
Create reusable format styles for domain types:
|
|
353
|
+
|
|
354
|
+
```swift
|
|
355
|
+
struct FileSize {
|
|
356
|
+
let bytes: Int64
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
struct FileSizeFormatStyle: FormatStyle {
|
|
360
|
+
typealias FormatInput = FileSize
|
|
361
|
+
typealias FormatOutput = String
|
|
362
|
+
|
|
363
|
+
func format(_ value: FileSize) -> String {
|
|
364
|
+
ByteCountFormatter.string(fromByteCount: value.bytes, countStyle: .file)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
extension FormatStyle where Self == FileSizeFormatStyle {
|
|
369
|
+
static var fileSize: FileSizeFormatStyle { .init() }
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Usage
|
|
373
|
+
let size = FileSize(bytes: 1_500_000)
|
|
374
|
+
size.formatted(.fileSize) // "1.5 MB"
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Collection Patterns: Chunking and Windows
|
|
378
|
+
|
|
379
|
+
```swift
|
|
380
|
+
// chunks(ofCount:) -- Swift Algorithms package
|
|
381
|
+
import Algorithms
|
|
382
|
+
|
|
383
|
+
let batches = items.chunks(ofCount: 10)
|
|
384
|
+
for batch in batches {
|
|
385
|
+
try await upload(batch)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// windows(ofCount:) -- sliding window
|
|
389
|
+
let movingAverages = values.windows(ofCount: 3).map { window in
|
|
390
|
+
window.reduce(0, +) / Double(window.count)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// adjacentPairs() -- process consecutive elements
|
|
394
|
+
for (previous, current) in values.adjacentPairs() {
|
|
395
|
+
if current > previous * 2 {
|
|
396
|
+
print("Spike detected")
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Guard: Complex Pattern Matching
|
|
402
|
+
|
|
403
|
+
```swift
|
|
404
|
+
func processResponse(_ data: Data) throws -> User {
|
|
405
|
+
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
406
|
+
let userData = json["user"] as? [String: Any],
|
|
407
|
+
let name = userData["name"] as? String,
|
|
408
|
+
let id = userData["id"] as? Int
|
|
409
|
+
else {
|
|
410
|
+
throw ParseError.invalidFormat
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Use Codable instead when practical -- this is for mixed/dynamic JSON
|
|
414
|
+
return User(id: id, name: name)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Guard with where clause
|
|
418
|
+
func processItems(_ items: [Item]) {
|
|
419
|
+
for item in items {
|
|
420
|
+
guard case .active(let config) = item.status,
|
|
421
|
+
config.isEnabled,
|
|
422
|
+
!config.isExpired
|
|
423
|
+
else { continue }
|
|
424
|
+
|
|
425
|
+
activate(item, with: config)
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Typed Throws: Protocol with Typed Errors
|
|
431
|
+
|
|
432
|
+
```swift
|
|
433
|
+
protocol DataStore {
|
|
434
|
+
associatedtype StoreError: Error
|
|
435
|
+
func save(_ data: Data) throws(StoreError)
|
|
436
|
+
func load(id: String) throws(StoreError) -> Data
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
struct FileStore: DataStore {
|
|
440
|
+
enum StoreError: Error {
|
|
441
|
+
case notFound, permissionDenied, diskFull
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
func save(_ data: Data) throws(StoreError) {
|
|
445
|
+
// ...
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
func load(id: String) throws(StoreError) -> Data {
|
|
449
|
+
guard fileExists(id) else { throw .notFound }
|
|
450
|
+
// ...
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## String Interpolation: Custom appendInterpolation
|
|
456
|
+
|
|
457
|
+
Apple documents `DefaultStringInterpolation` as the type used while building interpolated strings, and supports extending it with custom `appendInterpolation(...)` overloads.
|
|
458
|
+
|
|
459
|
+
```swift
|
|
460
|
+
extension DefaultStringInterpolation {
|
|
461
|
+
mutating func appendInterpolation(json value: some Encodable) {
|
|
462
|
+
let encoder = JSONEncoder()
|
|
463
|
+
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
|
|
464
|
+
if let data = try? encoder.encode(value),
|
|
465
|
+
let string = String(data: data, encoding: .utf8) {
|
|
466
|
+
appendLiteral(string)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
mutating func appendInterpolation(ordinal value: Int) {
|
|
471
|
+
let formatter = NumberFormatter()
|
|
472
|
+
formatter.numberStyle = .ordinal
|
|
473
|
+
if let result = formatter.string(from: value as NSNumber) {
|
|
474
|
+
appendLiteral(result)
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
print("Config: \(json: settings)")
|
|
480
|
+
print("You placed \(ordinal: 3)")
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Never: Advanced Usage
|
|
484
|
+
|
|
485
|
+
```swift
|
|
486
|
+
// Publisher that never fails
|
|
487
|
+
let publisher: AnyPublisher<String, Never> = Just("hello").eraseToAnyPublisher()
|
|
488
|
+
|
|
489
|
+
// Phantom type preventing construction
|
|
490
|
+
enum Locked {}
|
|
491
|
+
enum Unlocked {}
|
|
492
|
+
|
|
493
|
+
struct Door<State> {
|
|
494
|
+
private init() {}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
extension Door where State == Unlocked {
|
|
498
|
+
func open() { /* ... */ }
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Generic constraint meaning "this case cannot happen"
|
|
502
|
+
func absurd<T>(_ never: Never) -> T {
|
|
503
|
+
// No body needed -- Never has no values, so this is never called
|
|
504
|
+
}
|
|
505
|
+
```
|