@xgent-ai/skills 0.1.0 → 0.3.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/README.md +38 -2
- package/bin/xgent-skills.js +515 -4
- package/package.json +7 -3
- package/skills/dev-plan/SKILL.md +113 -93
- package/skills/dev-plan/references/architecture-quality.md +141 -0
- package/skills/dev-plan/references/execution-workflow.md +78 -0
- package/skills/dev-plan/references/plan-skeleton.md +238 -78
- package/skills/dev-plan/scripts/check_progress.sh +158 -0
- package/skills/elintp/SKILL.md +129 -0
- package/skills/grafton-view-dev/SKILL.md +195 -0
- package/skills/grafton-view-dev/references/bindings.md +120 -0
- package/skills/grafton-view-dev/references/components.md +168 -0
- package/skills/grafton-view-dev/references/recipes.md +208 -0
- package/skills/grafton-view-dev/references/schema.md +86 -0
- package/skills/grafton-view-dev/references/stores.md +310 -0
- package/skills/pardon/SKILL.md +30 -0
- package/skills/portal-app-exchange/SKILL.md +106 -0
- package/skills/portal-backend-app/SKILL.md +56 -0
- package/skills/portal-backend-app/references/gate-and-tokens.md +93 -0
- package/skills/portal-backend-app/references/wiring-and-conventions.md +71 -0
- package/skills/portal-dev-setup/SKILL.md +519 -0
- package/skills/portal-dev-setup/puller.env.example +74 -0
- package/skills/portal-dev-setup/references/troubleshooting.md +167 -0
- package/skills/portal-dev-setup/scripts/onebox.sh +966 -0
- package/skills/portal-external-app/SKILL.md +273 -0
- package/skills/portal-external-app/references/contract-doc-template.md +96 -0
- package/skills/portal-external-app/references/health-contract.md +80 -0
- package/skills/portal-external-app/references/integration-contract.md +130 -0
- package/skills/portal-external-app/references/quota-and-seats.md +213 -0
- package/skills/portal-external-app/references/registration-and-onebox.md +259 -0
- package/skills/portal-external-app/scripts/health-verdict.ts +22 -0
- package/skills/portal-external-app/scripts/verify-health.ts +27 -0
- package/skills/portal-logging/SKILL.md +139 -0
- package/skills/portal-logging/references/collectors.md +285 -0
- package/skills/portal-logging/references/contract.md +95 -0
- package/skills/portal-logging/scripts/smoke-ingest.sh +72 -0
- package/skills/portal-micro-app/SKILL.md +83 -0
- package/skills/portal-micro-app/references/manifest-and-acl.md +79 -0
- package/skills/portal-micro-app/references/open-api-and-extensions.md +86 -0
- package/skills/portal-micro-app/references/sdk-reference.md +208 -0
- package/skills/prd/SKILL.md +212 -0
- package/skills/prd/references/prd-skeleton.md +244 -0
- package/skills/prd/references/spms-mapping.md +148 -0
- package/skills/react/SKILL.md +103 -0
- package/skills/react/references/component-patterns.md +275 -0
- package/skills/react/references/data-fetching.md +255 -0
- package/skills/react/references/effect-patterns.md +407 -0
- package/skills/react/references/js-performance.md +432 -0
- package/skills/react/references/rendering-performance.md +351 -0
- package/skills/react/references/rerender-optimization.md +578 -0
- package/skills/rust/SKILL.md +103 -0
- package/skills/rust/references/chapter_01.md +564 -0
- package/skills/rust/references/chapter_02.md +117 -0
- package/skills/rust/references/chapter_03.md +209 -0
- package/skills/rust/references/chapter_04.md +183 -0
- package/skills/rust/references/chapter_05.md +390 -0
- package/skills/rust/references/chapter_06.md +142 -0
- package/skills/rust/references/chapter_07.md +226 -0
- package/skills/rust/references/chapter_08.md +257 -0
- package/skills/rust/references/chapter_09.md +261 -0
- package/skills/rust/references/chapter_10.md +554 -0
- package/skills/story-points/SKILL.md +219 -0
- package/skills/story-points/references/factors.md +367 -0
- package/skills/summarize/SKILL.md +79 -0
- package/skills/swarm/SKILL.md +263 -0
- package/skills/swarm/evals/evals.json +55 -0
- package/skills/swarm/references/agent-types.md +260 -0
- package/skills/swarm/references/teams/code-audit.md +81 -0
- package/skills/swarm/references/teams/debug-race.md +70 -0
- package/skills/swarm/references/teams/feature-dev.md +71 -0
- package/skills/swarm/references/teams/product.md +114 -0
- package/skills/swarm/references/teams/refactor-migration.md +73 -0
- package/skills/swarm/references/teams/research-debate.md +73 -0
- package/skills/test-plan/SKILL.md +136 -0
- package/skills/test-plan/references/case-taxonomy.md +141 -0
- package/skills/working-with-mbx/SKILL.md +343 -0
- package/skills/working-with-mbx/references/acknowledgements.md +37 -0
- package/skills/working-with-mbx/references/benchmarks.md +140 -0
- package/skills/working-with-mbx/references/cache-results.md +153 -0
- package/skills/working-with-mbx/references/cache-server.md +151 -0
- package/skills/working-with-mbx/references/cli/adopt.md +29 -0
- package/skills/working-with-mbx/references/cli/cache/dir.md +24 -0
- package/skills/working-with-mbx/references/cli/cache/export.md +31 -0
- package/skills/working-with-mbx/references/cli/cache/import.md +27 -0
- package/skills/working-with-mbx/references/cli/cache/largest.md +26 -0
- package/skills/working-with-mbx/references/cli/cache/projects.md +23 -0
- package/skills/working-with-mbx/references/cli/cache/remove.md +30 -0
- package/skills/working-with-mbx/references/cli/cache/stats.md +24 -0
- package/skills/working-with-mbx/references/cli/cache/trace.md +27 -0
- package/skills/working-with-mbx/references/cli/cache/verify.md +23 -0
- package/skills/working-with-mbx/references/cli/cache.md +35 -0
- package/skills/working-with-mbx/references/cli/clean.md +27 -0
- package/skills/working-with-mbx/references/cli/completion.md +27 -0
- package/skills/working-with-mbx/references/cli/doctor.md +24 -0
- package/skills/working-with-mbx/references/cli/exec.md +28 -0
- package/skills/working-with-mbx/references/cli/explain.md +29 -0
- package/skills/working-with-mbx/references/cli/gc.md +28 -0
- package/skills/working-with-mbx/references/cli/prefetch.md +27 -0
- package/skills/working-with-mbx/references/cli/setup.md +28 -0
- package/skills/working-with-mbx/references/cli/stats.md +24 -0
- package/skills/working-with-mbx/references/cli/tui.md +24 -0
- package/skills/working-with-mbx/references/cli.md +58 -0
- package/skills/working-with-mbx/references/compared.md +67 -0
- package/skills/working-with-mbx/references/configuration.md +724 -0
- package/skills/working-with-mbx/references/cookbook/fork-prs.md +82 -0
- package/skills/working-with-mbx/references/cookbook/local-development.md +127 -0
- package/skills/working-with-mbx/references/cookbook/migrate.md +67 -0
- package/skills/working-with-mbx/references/dashboard.md +89 -0
- package/skills/working-with-mbx/references/faq.md +75 -0
- package/skills/working-with-mbx/references/getting-started.md +147 -0
- package/skills/working-with-mbx/references/github-action.md +254 -0
- package/skills/working-with-mbx/references/guide.md +59 -0
- package/skills/working-with-mbx/references/how-it-works.md +86 -0
- package/skills/working-with-mbx/references/incremental.md +78 -0
- package/skills/working-with-mbx/references/index.md +57 -0
- package/skills/working-with-mbx/references/installation.md +101 -0
- package/skills/working-with-mbx/references/limits.md +182 -0
- package/skills/working-with-mbx/references/linkers.md +75 -0
- package/skills/working-with-mbx/references/managed-targets.md +197 -0
- package/skills/working-with-mbx/references/protocol-compatibility.md +103 -0
- package/skills/working-with-mbx/references/remote-cache.md +190 -0
- package/skills/working-with-mbx/references/scheduling.md +65 -0
- package/skills/working-with-mbx/references/setup.md +157 -0
- package/skills/working-with-mbx/references/stability.md +43 -0
- package/skills/working-with-mbx/references/standalone-builds.md +102 -0
- package/skills/working-with-mbx/references/stats.md +49 -0
- package/skills/working-with-mbx/references/troubleshooting.md +136 -0
- package/skills/working-with-mbx/references/tui.md +163 -0
- package/skills/working-with-mbx/update-docs.sh +49 -0
- package/skills/working-with-mise/SKILL.md +297 -0
- package/skills/working-with-mise/references/cli/activate-html.md +90 -0
- package/skills/working-with-mise/references/cli/alias-html.md +30 -0
- package/skills/working-with-mise/references/cli/backends-html.md +40 -0
- package/skills/working-with-mise/references/cli/bin-paths-html.md +37 -0
- package/skills/working-with-mise/references/cli/bootstrap-html.md +109 -0
- package/skills/working-with-mise/references/cli/cache-html.md +40 -0
- package/skills/working-with-mise/references/cli/completion-html.md +76 -0
- package/skills/working-with-mise/references/cli/config-html.md +44 -0
- package/skills/working-with-mise/references/cli/daemons-html.md +48 -0
- package/skills/working-with-mise/references/cli/deactivate-html.md +47 -0
- package/skills/working-with-mise/references/cli/deps-html.md +89 -0
- package/skills/working-with-mise/references/cli/doctor-html.md +46 -0
- package/skills/working-with-mise/references/cli/dotfiles-html.md +57 -0
- package/skills/working-with-mise/references/cli/edit-html.md +48 -0
- package/skills/working-with-mise/references/cli/en-html.md +62 -0
- package/skills/working-with-mise/references/cli/env-html.md +57 -0
- package/skills/working-with-mise/references/cli/exec-html.md +79 -0
- package/skills/working-with-mise/references/cli/exec.md +79 -0
- package/skills/working-with-mise/references/cli/fmt-html.md +44 -0
- package/skills/working-with-mise/references/cli/generate-html.md +43 -0
- package/skills/working-with-mise/references/cli/implode-html.md +35 -0
- package/skills/working-with-mise/references/cli/install-html.md +83 -0
- package/skills/working-with-mise/references/cli/install-into-html.md +47 -0
- package/skills/working-with-mise/references/cli/latest-html.md +62 -0
- package/skills/working-with-mise/references/cli/link-html.md +57 -0
- package/skills/working-with-mise/references/cli/lock-html.md +114 -0
- package/skills/working-with-mise/references/cli/ls-html.md +95 -0
- package/skills/working-with-mise/references/cli/ls-remote-html.md +61 -0
- package/skills/working-with-mise/references/cli/mcp-html.md +57 -0
- package/skills/working-with-mise/references/cli/oci-html.md +41 -0
- package/skills/working-with-mise/references/cli/outdated-html.md +79 -0
- package/skills/working-with-mise/references/cli/packslip-html.md +38 -0
- package/skills/working-with-mise/references/cli/patrons-html.md +45 -0
- package/skills/working-with-mise/references/cli/plugins-html.md +46 -0
- package/skills/working-with-mise/references/cli/prune-html.md +56 -0
- package/skills/working-with-mise/references/cli/registry-html.md +59 -0
- package/skills/working-with-mise/references/cli/reshim-html.md +46 -0
- package/skills/working-with-mise/references/cli/run-html.md +152 -0
- package/skills/working-with-mise/references/cli/search-html.md +69 -0
- package/skills/working-with-mise/references/cli/self-update-html.md +42 -0
- package/skills/working-with-mise/references/cli/set-html.md +116 -0
- package/skills/working-with-mise/references/cli/settings-html.md +78 -0
- package/skills/working-with-mise/references/cli/shell-alias-html.md +39 -0
- package/skills/working-with-mise/references/cli/shell-html.md +53 -0
- package/skills/working-with-mise/references/cli/skills-html.md +39 -0
- package/skills/working-with-mise/references/cli/sponsors-html.md +31 -0
- package/skills/working-with-mise/references/cli/ssh-html.md +45 -0
- package/skills/working-with-mise/references/cli/sync-html.md +37 -0
- package/skills/working-with-mise/references/cli/tasks-html.md +61 -0
- package/skills/working-with-mise/references/cli/test-tool-html.md +49 -0
- package/skills/working-with-mise/references/cli/token-html.md +37 -0
- package/skills/working-with-mise/references/cli/tool-alias-html.md +41 -0
- package/skills/working-with-mise/references/cli/tool-html.md +55 -0
- package/skills/working-with-mise/references/cli/tool-stub-html.md +60 -0
- package/skills/working-with-mise/references/cli/trust-html.md +63 -0
- package/skills/working-with-mise/references/cli/uninstall-html.md +62 -0
- package/skills/working-with-mise/references/cli/unset-html.md +59 -0
- package/skills/working-with-mise/references/cli/untrust-html.md +35 -0
- package/skills/working-with-mise/references/cli/unuse-html.md +74 -0
- package/skills/working-with-mise/references/cli/upgrade-html.md +133 -0
- package/skills/working-with-mise/references/cli/use-html.md +130 -0
- package/skills/working-with-mise/references/cli/use.md +130 -0
- package/skills/working-with-mise/references/cli/version-html.md +46 -0
- package/skills/working-with-mise/references/cli/watch-html.md +465 -0
- package/skills/working-with-mise/references/cli/where-html.md +53 -0
- package/skills/working-with-mise/references/cli/which-html.md +55 -0
- package/skills/working-with-mise/references/configuration/environments-html.md +171 -0
- package/skills/working-with-mise/references/configuration/project-diagnostics-html.md +93 -0
- package/skills/working-with-mise/references/configuration/settings-html.md +3062 -0
- package/skills/working-with-mise/references/configuration/vars-html.md +167 -0
- package/skills/working-with-mise/references/dev-tools/aliases-html.md +97 -0
- package/skills/working-with-mise/references/dev-tools/backend_architecture-html.md +198 -0
- package/skills/working-with-mise/references/dev-tools/backends/aqua-html.md +274 -0
- package/skills/working-with-mise/references/dev-tools/backends/aqua.md +274 -0
- package/skills/working-with-mise/references/dev-tools/backends/asdf-html.md +98 -0
- package/skills/working-with-mise/references/dev-tools/backends/asdf.md +98 -0
- package/skills/working-with-mise/references/dev-tools/backends/cargo-html.md +240 -0
- package/skills/working-with-mise/references/dev-tools/backends/cargo.md +240 -0
- package/skills/working-with-mise/references/dev-tools/backends/conda-html.md +125 -0
- package/skills/working-with-mise/references/dev-tools/backends/dotnet-html.md +142 -0
- package/skills/working-with-mise/references/dev-tools/backends/forgejo-html.md +533 -0
- package/skills/working-with-mise/references/dev-tools/backends/gem-html.md +77 -0
- package/skills/working-with-mise/references/dev-tools/backends/gem.md +77 -0
- package/skills/working-with-mise/references/dev-tools/backends/github-html.md +622 -0
- package/skills/working-with-mise/references/dev-tools/backends/github.md +622 -0
- package/skills/working-with-mise/references/dev-tools/backends/gitlab-html.md +546 -0
- package/skills/working-with-mise/references/dev-tools/backends/go-html.md +115 -0
- package/skills/working-with-mise/references/dev-tools/backends/go.md +115 -0
- package/skills/working-with-mise/references/dev-tools/backends/http-html.md +644 -0
- package/skills/working-with-mise/references/dev-tools/backends/http.md +644 -0
- package/skills/working-with-mise/references/dev-tools/backends/npm-html.md +436 -0
- package/skills/working-with-mise/references/dev-tools/backends/npm.md +436 -0
- package/skills/working-with-mise/references/dev-tools/backends/packslip-html.md +310 -0
- package/skills/working-with-mise/references/dev-tools/backends/pipx-html.md +329 -0
- package/skills/working-with-mise/references/dev-tools/backends/pipx.md +329 -0
- package/skills/working-with-mise/references/dev-tools/backends/pkgx-html.md +73 -0
- package/skills/working-with-mise/references/dev-tools/backends/pypi-html.md +331 -0
- package/skills/working-with-mise/references/dev-tools/backends/s3-html.md +346 -0
- package/skills/working-with-mise/references/dev-tools/backends/spm-html.md +201 -0
- package/skills/working-with-mise/references/dev-tools/backends/ubi-html.md +232 -0
- package/skills/working-with-mise/references/dev-tools/backends/vfox-html.md +173 -0
- package/skills/working-with-mise/references/dev-tools/backends/vfox.md +173 -0
- package/skills/working-with-mise/references/dev-tools/backends.md +32 -0
- package/skills/working-with-mise/references/dev-tools/comparison-to-asdf-html.md +112 -0
- package/skills/working-with-mise/references/dev-tools/deps-html.md +390 -0
- package/skills/working-with-mise/references/dev-tools/github-tokens-html.md +390 -0
- package/skills/working-with-mise/references/dev-tools/index-html.md +420 -0
- package/skills/working-with-mise/references/dev-tools/mise-lock-html.md +660 -0
- package/skills/working-with-mise/references/dev-tools/mise-oci-html.md +418 -0
- package/skills/working-with-mise/references/dev-tools/packslip-resources-html.md +203 -0
- package/skills/working-with-mise/references/dev-tools/packslip-verification-html.md +178 -0
- package/skills/working-with-mise/references/dev-tools/shims-html.md +397 -0
- package/skills/working-with-mise/references/dev-tools/tool-stubs-html.md +416 -0
- package/skills/working-with-mise/references/guides/getting-started.md +268 -0
- package/skills/working-with-mise/references/index.md +37 -0
- package/skills/working-with-mise/update-docs.sh +111 -0
- package/skills/xgent-app-release/SKILL.md +438 -0
- package/skills/xgent-app-release/references/build-and-package.md +65 -0
- package/skills/xgent-app-release/references/publish-api.md +315 -0
- package/skills/xgent-app-release/references/troubleshooting.md +108 -0
- package/skills/xgent-app-release/scripts/npm-token.mjs +94 -0
- package/skills/xgent-app-release/scripts/preflight.mjs +340 -0
- package/skills/xgent-app-release/scripts/registry-config.mjs +88 -0
- package/skills/xgent-image-push/SKILL.md +239 -0
- package/skills/xgent-image-push/registry.env.example +51 -0
- package/skills/xgent-image-push/scripts/push-image.sh +576 -0
- package/skills/xgent-init/SKILL.md +96 -0
- package/skills/xgent-init/references/external-app-CLAUDE.template.md +249 -0
- package/skills/xgent-init/references/external-app-DESIGN.template.md +317 -0
- package/skills/xgent-init/references/external-app-PRODUCT.template.md +87 -0
- package/skills/xgent-init/references/fill-guide.md +78 -0
- package/skills/xgent-init/scripts/check-docs.mjs +304 -0
- package/vendor/impeccable/LICENSE +191 -0
- package/vendor/impeccable/NOTICE.md +11 -0
- package/vendor/impeccable/VERSION.json +28 -0
- package/vendor/impeccable/bundle/blobs/00023f9e7f2e27604fde978b56510a8f837b76eeadd93221d11adcf4c98f1a10 +88 -0
- package/vendor/impeccable/bundle/blobs/00f053b877a92a9847d69eec2403e40c757152f30a5ca807c5033c58d7c297f1 +33 -0
- package/vendor/impeccable/bundle/blobs/012f548547fae48ebdd22a3c3af8a01032641fddd530e3783bd73b7358ab2c49 +80 -0
- package/vendor/impeccable/bundle/blobs/015725eeca94f52bffd2132d4cb49bc3eb1ee76e6ac7378c065e629d59f56613 +84 -0
- package/vendor/impeccable/bundle/blobs/03b30331c176a248a3b3bd17abdff1a1fd658f09ffb2a412b36ae9627dd3f33b +105 -0
- package/vendor/impeccable/bundle/blobs/041535231366047a0beeb5daa64ea9c23d5a566580f7dafdb8c0623cb4a7e76b +24 -0
- package/vendor/impeccable/bundle/blobs/04af9f2d6883fe76f9539d310d9c369052822a24886d2c330ab1e3fe5981c8a1 +24 -0
- package/vendor/impeccable/bundle/blobs/058f81f256134841875fd3183e06b37a023de0c877fd2b9eecd97011640791fe +46 -0
- package/vendor/impeccable/bundle/blobs/05aa836a190f4ff62e5d4619738bdb891d83d85e35d81c2e6e322d1dc084d802 +80 -0
- package/vendor/impeccable/bundle/blobs/05e86f37d7fa381c5e8a04b6212490a27904d3be3e9384862a0764d3daba6d78 +54 -0
- package/vendor/impeccable/bundle/blobs/0617b37a905f0486c1ab4e91a287c8ef8292e253095c340f452d591206272f73 +104 -0
- package/vendor/impeccable/bundle/blobs/074575671f24cf4298d06f0019f76e94f62e9a6ed205fce05b8e507341e64266 +111 -0
- package/vendor/impeccable/bundle/blobs/076a31941acbaa81013c8c511e146ed4138128eb5e9895dae3e9a27a25ac4f04 +13 -0
- package/vendor/impeccable/bundle/blobs/08812a8618de7bd2f63a51298e9c2558031237e8efba280062ccb636101e25e1 +80 -0
- package/vendor/impeccable/bundle/blobs/08a2980eae0bfea1f00229899defc28ec92c7ecb875bf5fb02e4ba80dad6c394 +806 -0
- package/vendor/impeccable/bundle/blobs/08d78eb31c561256f83baa0afa742a660f1467aa2c81be2f60c2b7f9c770d66e +54 -0
- package/vendor/impeccable/bundle/blobs/098a891028ce59c212b747d3c70468dd750aff7053a703d1336045ed31e0da7c +70 -0
- package/vendor/impeccable/bundle/blobs/0a151a54959a15eb32fa338890d5d64ac48a9d54d2d5442c3c7708a4c27c1858 +104 -0
- package/vendor/impeccable/bundle/blobs/0bb4085f6dda702846e0e56bd4f797aa1b046ab48eca02644448e368f3820f88 +104 -0
- package/vendor/impeccable/bundle/blobs/0bc7d7971b3edf2acd0580e847458dc6d84129d90715b452799ace3bed815c7c +84 -0
- package/vendor/impeccable/bundle/blobs/0bf6f08bf34d24cd88a78d544add9e4d71478bcf939926cde32f4e164882c775 +105 -0
- package/vendor/impeccable/bundle/blobs/0dbbef70048cc3ae44e6710ff09992ce14ad049ce8ed519b0ff8a1ddb4633f4e +111 -0
- package/vendor/impeccable/bundle/blobs/0e081d496eba4bd77aca81723d59120c10177a71c9551a60ab923c356fb3cf38 +104 -0
- package/vendor/impeccable/bundle/blobs/0e1819750e5448311a051d35ab6d0be0830418f78ca872ef10469fafebb27d4f +46 -0
- package/vendor/impeccable/bundle/blobs/0e18ac33b7e6a247b658fcaf926d9eac028399597dbaba366f1d2f2b884a383b +325 -0
- package/vendor/impeccable/bundle/blobs/0f83648f6b425225290305bced51eacebacf9bf9bc05e21cdbad46863fbc89ce +24 -0
- package/vendor/impeccable/bundle/blobs/115e1c3f1b58b5129910ed925dbf65d61d5ac4c2036618847555ce40098aae97 +145 -0
- package/vendor/impeccable/bundle/blobs/11f75834c26ecd8a5b0afdf696e838953b235dc4835b7293bbc6b1bc27dd3106 +84 -0
- package/vendor/impeccable/bundle/blobs/12c1afcd15e86d840b89a78c6d17ce6d1b5609bac713d59271c6ab5932975dac +111 -0
- package/vendor/impeccable/bundle/blobs/12d2a8043ae8668ad29c32bfa92995849fc49cb016e6ebd4f7e59539d96e7b03 +46 -0
- package/vendor/impeccable/bundle/blobs/12fefe52d80d25014e5f7e2f9b278275a675653d3d99ae8f0ecf344cdb9abbe6 +111 -0
- package/vendor/impeccable/bundle/blobs/13bd27aa8573e6d45d8bbf9f3fc991e4719d28a7e8f709009a4a5a49a227fff3 +37 -0
- package/vendor/impeccable/bundle/blobs/1484a7ae206ab4f0e6262b21afe0f6307a629ed27d28fb7de69536a6800a4883 +37 -0
- package/vendor/impeccable/bundle/blobs/15b4837dccb27d7382e2f134ef050b244c4488b1906e0308f288112183cc09ac +145 -0
- package/vendor/impeccable/bundle/blobs/1640c70b984a43e729d72d046109f87243ae84ecd64d2600a007d140558123cc +80 -0
- package/vendor/impeccable/bundle/blobs/1652d639d91889a08bda7f351456c43ee30e5677aa4866a90f375e1e4be15deb +80 -0
- package/vendor/impeccable/bundle/blobs/16d99e9fe8e75d69042bc4fda12e93daa7e10f9fa6c00b12b0f0580b119a4cfd +105 -0
- package/vendor/impeccable/bundle/blobs/171777f8a8596d2ffdb43f4b935a7c6c12859ace233967f868a566390a59708e +325 -0
- package/vendor/impeccable/bundle/blobs/173dd66abe65633910dcb04a51f40d6ff2a793f87088f022a02fc4cad24dd133 +94 -0
- package/vendor/impeccable/bundle/blobs/17c583cf8ad41266ea1e787b666b9d91fe13469d3d0f6af57c08e0146f9b17ac +58 -0
- package/vendor/impeccable/bundle/blobs/181e814c1b9317098b2300c1b02ad0d137b6d82bd1e7e8cc64de4d00b4c50c25 +111 -0
- package/vendor/impeccable/bundle/blobs/190a4e642ca362d7499f3c3ab123e21f18f75457d11f072b545a183f296e6495 +99 -0
- package/vendor/impeccable/bundle/blobs/1971edc3784273bd8da7b1980779c6159471e857992faa6637178109cb130503 +806 -0
- package/vendor/impeccable/bundle/blobs/199d5d3db1197e053a2eb9c3cb927d44cbaaaeb57745c1ada3fd775ba50d9291 +104 -0
- package/vendor/impeccable/bundle/blobs/19c5bfce570a0e2bddd4d9c788936ff9070c90299363c4853ba77bfd37306e20 +416 -0
- package/vendor/impeccable/bundle/blobs/1a9180cec754f8afd354e7cb759750247e97c5bd26d3242ad4c45e315069e8c0 +37 -0
- package/vendor/impeccable/bundle/blobs/1c804990fd8ac23a4b19c42972b5ae591d17f620d0006f0f32927c8db5d5bf50 +145 -0
- package/vendor/impeccable/bundle/blobs/1d72b494f46a60e6c9c06e89bab79789dd85e11f62fb4286a03abf26d352dc1f +80 -0
- package/vendor/impeccable/bundle/blobs/21bc91f6e07691e82b7bba99f9e1d956f9d7a6810dcdc18d231fe73b53a13b23 +37 -0
- package/vendor/impeccable/bundle/blobs/238e1967d933ca5739db708f7ad9f72ca8b34bc4c9b9e1c07b0a06dcf9d00681 +806 -0
- package/vendor/impeccable/bundle/blobs/244e5b7bca6d22a51b4e22104a52a36e477056b03d257b56d1d4e319cd6167a8 +80 -0
- package/vendor/impeccable/bundle/blobs/249f0437a52ab3eb4bc4d4a9f38e085334c0fbb7795e88dd419e32b5f58c924d +42 -0
- package/vendor/impeccable/bundle/blobs/27c4b6c90ad12a186136f9ece9cb1830d4a6e36b11382ab334efc4543f8082de +145 -0
- package/vendor/impeccable/bundle/blobs/29f741b71e75fd39c65ca6df4b01b5f6c4f3c4c7adf23b47a3220ce2c0251f24 +104 -0
- package/vendor/impeccable/bundle/blobs/2b21f0142ee88a11dbe2593362f5a910718a61062e3a64e7ff936ef1e74fd394 +46 -0
- package/vendor/impeccable/bundle/blobs/2b58041cd82d819d12762b10becb95f8253c661bf6a9de40f61fc01c1204b743 +806 -0
- package/vendor/impeccable/bundle/blobs/2b5b2fbf5f658f34ea1997fb1aeebe01604d05187f75c6a4f1f55a5bc78520a4 +104 -0
- package/vendor/impeccable/bundle/blobs/2c2ed6286bd74adef4f24ef442e2e1bc0780d44bc060aa2a4c03a03988dbafd5 +325 -0
- package/vendor/impeccable/bundle/blobs/2d7086992c07df1fc734cdf9c420c4bd8ad409ab7909e07c8b486c303d420732 +83 -0
- package/vendor/impeccable/bundle/blobs/2e4846117a2fcdc1e4bc9570a5333da839649cb8ccdac6a30a87591ca05b4bb0 +54 -0
- package/vendor/impeccable/bundle/blobs/2f02f96f889e0c8e0e90806af1ef17e0c162a6cc402068f434d3f7608d9deda3 +54 -0
- package/vendor/impeccable/bundle/blobs/2fd096823e4a93f19edd421a69e10f90ebb630a014c673d1802a927c6f47b7d2 +111 -0
- package/vendor/impeccable/bundle/blobs/2feb3768125ba6469c92a50d516727e6d42f44579165ddfd33409948e2a3803d +27 -0
- package/vendor/impeccable/bundle/blobs/30e006fdee873bac23edaeadce0371161625e021e3cf442dff4b05bb82297ba1 +24 -0
- package/vendor/impeccable/bundle/blobs/31b90048c0b540daec46762a10c2b6b6434737a89af005054d8b848d829d003b +69 -0
- package/vendor/impeccable/bundle/blobs/33b6b32c0c3c0c4a2b22bd2275176b1c88a006dd94592a854f629911a0b21cdc +111 -0
- package/vendor/impeccable/bundle/blobs/3565d038a2eeab88a8b18ff52e6630008ab30f867f9df922a38ce8980440b2e3 +80 -0
- package/vendor/impeccable/bundle/blobs/356cfa0ebf61589cf5d52691d101a69d69256062fe1d11d71d95d41a78289cbd +111 -0
- package/vendor/impeccable/bundle/blobs/3673248740bcdd1122ccc610093ba2fe52f3943a61ce0b7170b74dc49e5b6098 +416 -0
- package/vendor/impeccable/bundle/blobs/37080ea5e5b381adb7eae7a427231b0ad0dee0f0916fc1d6b673b7101a5b425b +42 -0
- package/vendor/impeccable/bundle/blobs/3753448bca49da76dd8b12d5a8b4264414673f26e49028d37616faa8beb210b7 +127 -0
- package/vendor/impeccable/bundle/blobs/37565671b09d983ea1ad83a9e9190bc37255d93c68445958c6facecc7e0f7c4f +33 -0
- package/vendor/impeccable/bundle/blobs/37aeddc0f2031fa89d72519ae2e7542c267872f81786fb8288fca0a49118be11 +27 -0
- package/vendor/impeccable/bundle/blobs/37c9a2122efa64dc8789eb47d196150b0bc635e0ba95042fd381ff157002ed50 +111 -0
- package/vendor/impeccable/bundle/blobs/381ff89aa76e82a0d98456ec31cb117555ae045539fba47c45056daa50f611ca +46 -0
- package/vendor/impeccable/bundle/blobs/3895765e9434400dfc1b30e364be002cf499c1718fb2431e65b907c14ae2cb27 +86 -0
- package/vendor/impeccable/bundle/blobs/38c2e839e130008b6da814ab9c16f3fcbbedfdf721a9638eebd31a9e65341a7a +84 -0
- package/vendor/impeccable/bundle/blobs/38d4d404030c6ea935d3223db1eeb22c45d04a94f41f98e02a43cdc5af7ff2e3 +24 -0
- package/vendor/impeccable/bundle/blobs/3970c8e24615610b0246585e49146f6762d5082b3c8fddc08a00940d6e72d394 +80 -0
- package/vendor/impeccable/bundle/blobs/39ac044f2e45a9e7eed8eb68fe91d32938160eb7f8fa93d2afc42fc80a0c3c10 +54 -0
- package/vendor/impeccable/bundle/blobs/39d9600489073e227e4f4d55c451ce4252a6632ed7ae37923efbbcbc91f16d07 +206 -0
- package/vendor/impeccable/bundle/blobs/3aa908c18db91d5f31d6bba6402eab6afc4e0b75137f841a86bd012386e0d8e2 +145 -0
- package/vendor/impeccable/bundle/blobs/3af7c46309f748ff3845f16455a431ec0e9e807e5e3a965e96e9ee75a1198eb8 +95 -0
- package/vendor/impeccable/bundle/blobs/3ba92d4aa840ec1b6c2fda224339489d6dd65eedf43bb45836af02584d1faa88 +42 -0
- package/vendor/impeccable/bundle/blobs/3bcf81b938a0f0309e9ed6616f4bd18d82f07e2801411ee4cce51220d417eb95 +80 -0
- package/vendor/impeccable/bundle/blobs/3bf5d8661351831dbb2195e3b677fea1f128ca319c0589d538b66d9c9d7dddbc +111 -0
- package/vendor/impeccable/bundle/blobs/3dd45e1c32db3d3163a96ef198954905807b25cb9a1d206a7d77986f21d27652 +39 -0
- package/vendor/impeccable/bundle/blobs/3e3b6fdc6afbc2c2a734d08d6a18b393b7139c56f28f91f82e13e5555b98018a +84 -0
- package/vendor/impeccable/bundle/blobs/3f2c351303b74e217907006fb9c55ada2ef596e9710c13d631e20506d17b9ee8 +325 -0
- package/vendor/impeccable/bundle/blobs/402373ef95962ecb81dd3d7cf70ecb3bd3e22a2bd2aabb4c0d76f7f4f9447870 +105 -0
- package/vendor/impeccable/bundle/blobs/402656ca6df17bad1cd55ede0a966a7bb5b187cf4f89c517851f9efe7f14c0fd +87 -0
- package/vendor/impeccable/bundle/blobs/40c87038b5f75147a5952a96237acf312a327bf70c1bcd8e0a5f064625ae9668 +51 -0
- package/vendor/impeccable/bundle/blobs/420d82fe41884b7aa8c28750520146d8160c91396ac332a96b2d82a90b017fb2 +80 -0
- package/vendor/impeccable/bundle/blobs/420e2fdee2b7f555d9a37ce348cf62610ddd98f96b1a0a511796ba600881588c +111 -0
- package/vendor/impeccable/bundle/blobs/424b2e75cb204e2dca7db4a40dfe5a81f78dc0fc58ac4790e8b7bbf2f330bba4 +37 -0
- package/vendor/impeccable/bundle/blobs/424ff273e7ab283d6695d127bb502675627193f5b752d7b43b7524bcfc42f43f +84 -0
- package/vendor/impeccable/bundle/blobs/426c7f5437dd3c23a4cfaef6964dc7f1e038480f92238499b85f3ce7e4472bf4 +111 -0
- package/vendor/impeccable/bundle/blobs/42a71df98075f66e6eb396b69ef3d6b1c3db46d1c1d24b4edc9d15f53d193ecb +111 -0
- package/vendor/impeccable/bundle/blobs/433a79eee3ce4c99e79a7aebe3a6d8ec9ff70216772e0c2ff9dce3a01d672963 +46 -0
- package/vendor/impeccable/bundle/blobs/43852ca5917de66704f73f9019d15482bb1efd92f2eefaeeeae23610b4c0c6a0 +38 -0
- package/vendor/impeccable/bundle/blobs/442749aed338f51c1a3ccfb182c6ade9b74b90590b67984062ac94a5b100e914 +80 -0
- package/vendor/impeccable/bundle/blobs/44a91b3f0810f43829d8584e912812444d15614e4b57ca8070aee7ab899f7c1e +46 -0
- package/vendor/impeccable/bundle/blobs/46250caaec1bd69619a5b28a73cb3c845b319d029b0af9228aaa7001e7e0104a +37 -0
- package/vendor/impeccable/bundle/blobs/464c0c2b33d278375aec66caf95518f5e7ccd0aad1bea3f9dd553ed47815daa1 +325 -0
- package/vendor/impeccable/bundle/blobs/47b3461f6f76db80fdc49fc7542552d65fed24edc8d30d903cb76aefbad0ed05 +84 -0
- package/vendor/impeccable/bundle/blobs/47edbdfaf27073c47033d1ac7dfee881be49e2dcbda7671d1157300481dde6da +1 -0
- package/vendor/impeccable/bundle/blobs/4879f38b23d0a251a63cbb0327e660296194cd2e71eb4da3236c6ebfe5807746 +33 -0
- package/vendor/impeccable/bundle/blobs/48bb7c3b738f57fa4f3f714d7e3e919879036f3e751135a9acc1c5ede1850ea6 +54 -0
- package/vendor/impeccable/bundle/blobs/494d6fcb4701c437597c2ed16a9595af92f3d9ad53c944c96a2fb563bd766af5 +99 -0
- package/vendor/impeccable/bundle/blobs/49a7b37b98fb6e3ef68154174677ff4b9f1715efcffdbf6b30c3535b3e4e302c +54 -0
- package/vendor/impeccable/bundle/blobs/4a7d8695741e2cd354baada215b06798c050aa7a8e1ca6814f0e395e054d1ab1 +145 -0
- package/vendor/impeccable/bundle/blobs/4a8a45a46b79948a64b484edf389aa0b00fc80de855470cbabe3c7c71268f345 +828 -0
- package/vendor/impeccable/bundle/blobs/4acfb9e38f6e09f7484e36fc19704d69eab159436ee9329168be74c493042f22 +111 -0
- package/vendor/impeccable/bundle/blobs/4ad7c5d5821f85c2311ff91746d9b9cf272dbe0a9a5b61687f77681f5a13f812 +69 -0
- package/vendor/impeccable/bundle/blobs/4b0e2eea17f297daa06b17578131775be099ef43addf91007f4b7e295454f64f +105 -0
- package/vendor/impeccable/bundle/blobs/4bceaf3346b6f5100b5a54deaae49a38b975dd134df2836675848f06ff1e7e11 +806 -0
- package/vendor/impeccable/bundle/blobs/4ce929b8cafd37247ea4c148bbe39a9afe15908d1abf4a8248c5122275d16499 +85 -0
- package/vendor/impeccable/bundle/blobs/4df48b7a86d525ad12e7889a1fd16b06ed4b25a9470c359c7193a6d82649262f +54 -0
- package/vendor/impeccable/bundle/blobs/4fb6d2fcc8afaf827a7377ddd604725264fd83be871e2d35062e9d1939144404 +25 -0
- package/vendor/impeccable/bundle/blobs/51e2f8963377f142ebdc9864e0ecc5aa1e5b7d344ed72d0e9d748d2d3d8c71b3 +46 -0
- package/vendor/impeccable/bundle/blobs/521391d55814fdef6cd648ed62154a14d77b324004a0fc2d06c0a4e97857eab2 +806 -0
- package/vendor/impeccable/bundle/blobs/52e861ac390a62c4473ae0cf87ff18dd6d721afa6557910492dd8ed28bd9970d +84 -0
- package/vendor/impeccable/bundle/blobs/532d6387db6f5da1a59dc7d29ce4d8ba6ca044626c367dc16e1cb8b981eb2d9a +104 -0
- package/vendor/impeccable/bundle/blobs/54cb270e8826380caefc8c40642a5d973f27df46bfdb762d822541a0c72a9877 +145 -0
- package/vendor/impeccable/bundle/blobs/54e71283cbd5646021fcd8eaa28d85852ec5288109c306aca9db9e2e4832338e +69 -0
- package/vendor/impeccable/bundle/blobs/5515d5210fbe2ef64e611ef2827a7204b7cea2f9df059f3ea499931f45065d93 +104 -0
- package/vendor/impeccable/bundle/blobs/55e95137b3f9198c1d4dfc425366b82f1ef5f77d602682b2edf91f2ce9296289 +24 -0
- package/vendor/impeccable/bundle/blobs/56500b1f9d2fcec8324d7f448d813048b5831a46d3feeb1055bd3eb17ec3660f +70 -0
- package/vendor/impeccable/bundle/blobs/571526fd5c60a586ff65bdb3f8333f26c36ae227f5f5ece826f4a43b4d4aee0f +325 -0
- package/vendor/impeccable/bundle/blobs/5738bcf9ac21dbb2113fd0c5cc7e4bbfc8174778916ab5843644332b3dbbc36e +46 -0
- package/vendor/impeccable/bundle/blobs/57402ef6fd9d0745f8c60d778f77da83a8b16edf751fa1013598a0f6e5f0f541 +136 -0
- package/vendor/impeccable/bundle/blobs/57e28934208e3eac653ab59c5c6a5e4eace44906d8ac86472988242d777ca5a1 +54 -0
- package/vendor/impeccable/bundle/blobs/581409ace104a81744b7d08f5398a2c207cf76d9e50751f807b4382eaf66454f +46 -0
- package/vendor/impeccable/bundle/blobs/598bfed550954471ba4d257d46b4d608cd82e4cdbf36d07bf93c5f4a563f7727 +89 -0
- package/vendor/impeccable/bundle/blobs/599afc25c1d6d083e4d4e60e1617ab05f6c5ecd52be75473f3788063219aa174 +31 -0
- package/vendor/impeccable/bundle/blobs/5b30a06646ad5e453d6b5ed1b8d446f69fca3cd13b8aeda28f0d0b2cbe8f62d1 +111 -0
- package/vendor/impeccable/bundle/blobs/5b5dcf7029376ee6fbcf13e5975eb828dd1dbf41736c1bd5017dcda8173b1ebc +325 -0
- package/vendor/impeccable/bundle/blobs/5be952da521a2d5fb799c834d14ce5388284374bc23c5efcec737a05aa65d878 +84 -0
- package/vendor/impeccable/bundle/blobs/5c036648951d555e73be63161e5c9edcba146d8e9f64b1604ffdea765cde5d9d +131 -0
- package/vendor/impeccable/bundle/blobs/5c4cd151c97dae824a039211d7ccfba4c572b76d8f079c6186ba1dd5dae7732b +54 -0
- package/vendor/impeccable/bundle/blobs/5ce02fc8f353d7f659535fb80e453963dc047a07c4396adf098fe010b479e7c0 +84 -0
- package/vendor/impeccable/bundle/blobs/5ce0631eacaae6d9fbb23ade26a774a20142cb40d3a8d5608a3fb9dbc4116b60 +806 -0
- package/vendor/impeccable/bundle/blobs/5db17cd013c10dca0012bc18aee7276280941579aa50757682e9ce60c4f7a006 +104 -0
- package/vendor/impeccable/bundle/blobs/5e3616ac45568f239fda3a4764f7d3bf3473b8b5eefd91e402dd9208a4b851d1 +24 -0
- package/vendor/impeccable/bundle/blobs/5f24c5a97b4ffcabc7c432b064cfdd04c7a2ad52f52e765be648dc0aadab8f38 +38 -0
- package/vendor/impeccable/bundle/blobs/5fae7f8a2fc3ddd49ad0a413446dc44daedef5b6b7de5eb935bd2fbfad646d58 +92 -0
- package/vendor/impeccable/bundle/blobs/61c72fdde649bf7f2e0668e48f9d222666c81672100b5f2265940e7aa13c8767 +111 -0
- package/vendor/impeccable/bundle/blobs/633903ba7cb38ed502448a66691fbf655805786a2f06be67043f12294ad08e86 +37 -0
- package/vendor/impeccable/bundle/blobs/64802d14087fc96b38ef3881fef8098b36068d07f3b942031637b18eef3dd2af +84 -0
- package/vendor/impeccable/bundle/blobs/64807d8f43267f4ed879e997834bbf793bd4605ba1dc65f4b545324b660a7063 +80 -0
- package/vendor/impeccable/bundle/blobs/68bc52a604731ca024610051fc763f4d78a53eb2a45d35b40a8c0383043baa63 +86 -0
- package/vendor/impeccable/bundle/blobs/68c5636a7858dd0b5137a9229c15e25fdc2ee40a0f8a4e9d809f78e809256262 +327 -0
- package/vendor/impeccable/bundle/blobs/696c15f96d49a03091b71a408151a3297521f7a8231b98ca9b1103667a0b5f89 +80 -0
- package/vendor/impeccable/bundle/blobs/6989120346e87907d59cc6d4708dd9dee29227ad583fbefee28935395b68ce34 +24 -0
- package/vendor/impeccable/bundle/blobs/69be9bb887f4d8ba4ead24928f9b97d122c796e731652fc0c08f195ab8ec2815 +105 -0
- package/vendor/impeccable/bundle/blobs/6abbf5979db5cb1d7965bf5f91d589e984843069c587f4d1e63aab135bbace0f +37 -0
- package/vendor/impeccable/bundle/blobs/6acc0bf221a4ddc6e5c6438348920b2ca2393b29c4314dbde2cdc23f2b1a9639 +58 -0
- package/vendor/impeccable/bundle/blobs/6bc62a59f6fef0b749927c8d10e9849ab2411199d86d70772a86f8e83ac309f5 +29 -0
- package/vendor/impeccable/bundle/blobs/6bdbc3f745ceee15e10b050f109ce42bbeb53ab3c3b5239257de1d596654dee7 +94 -0
- package/vendor/impeccable/bundle/blobs/6c382f8283756e8a693d832b750f7e4cbff1ca5bdcc3825b2b4ef4da9f21876a +94 -0
- package/vendor/impeccable/bundle/blobs/6c9ce3e27ec4520ead001da3aad2a2ebba481c4e5cd22873db8890259ee579fe +95 -0
- package/vendor/impeccable/bundle/blobs/6d368b679a0ed1815812815de65863b5840d419589dfbda06224c01149240287 +258 -0
- package/vendor/impeccable/bundle/blobs/6d47503587ad6da17ac529f44a96123bbb96a9c91a7a9350b7690fc467561a5d +46 -0
- package/vendor/impeccable/bundle/blobs/6e20041e209e8705d14aa9c4fb8cca3f0d743791de633785e5b46e2dd1ff1a6b +24 -0
- package/vendor/impeccable/bundle/blobs/6e7e3b7c4cf331cdb43f4546c164acd6c45a267ce3289dcfa87e13202d98c747 +104 -0
- package/vendor/impeccable/bundle/blobs/6f1d52863482fa0f6fff877f0cc8f6dd0b4230d28050b0d267e082776e61a332 +37 -0
- package/vendor/impeccable/bundle/blobs/706c68612a7c6b899a0abf0b407eca7cabcd371deae60f830aa38aa86947694e +84 -0
- package/vendor/impeccable/bundle/blobs/713cac92a71ef45e8b700180d881f830096cfe2b0615e79b276ccc4a12c051e0 +80 -0
- package/vendor/impeccable/bundle/blobs/733504a70ed20bcfca9c26c353f7b88f8491d24f3f2fe124dc1e73b28eefa296 +145 -0
- package/vendor/impeccable/bundle/blobs/73549b5536699c915156339976192fb38534bb43158cf9262ff5b89090388c64 +806 -0
- package/vendor/impeccable/bundle/blobs/73bd60faec1d8360753595f1ee9e970b44933448202767d7b0e87c275d399396 +6 -0
- package/vendor/impeccable/bundle/blobs/745b1f74877f6b3445da48af65dc45c66c3daa7738cb9a928aaa900889c2a204 +104 -0
- package/vendor/impeccable/bundle/blobs/74e20b26c29242bbebf79760315f7f0788e001566695618cfc70805484c6f92a +111 -0
- package/vendor/impeccable/bundle/blobs/759bab1d8adc071fdde2efcf6e2157aa4026f3c2b4f3c342a8070bf328011616 +214 -0
- package/vendor/impeccable/bundle/blobs/7848f40e224cf520bd8554943c9816a1ff8c97b1db57af0844e3b1ebb223d91f +416 -0
- package/vendor/impeccable/bundle/blobs/78ac93689928a580c2f90242cbaa96dda3fa4e55ff1f1d00e412b2a62ad85232 +145 -0
- package/vendor/impeccable/bundle/blobs/78c236dadb7e70337dc9dfa67e65fc15b7abed137ad320c16410ddfa7aec34f9 +131 -0
- package/vendor/impeccable/bundle/blobs/79114c6bf78b5a1838fe19bf033f3be85b232560eebf190ff8586aaec34ea170 +105 -0
- package/vendor/impeccable/bundle/blobs/79f85e381d1d6fdc8d39f54e1c8753fccf19b4ba3abb9827b6a7cc61eb376d1f +416 -0
- package/vendor/impeccable/bundle/blobs/7ad26830c7399a118cdbd4465a5426bc1919015aba99fd15959dc6deb8edc8d6 +80 -0
- package/vendor/impeccable/bundle/blobs/7af0a8665057c83b39bca2c8c7427ef2343734f70d4128c377113a6726a1e3b1 +12990 -0
- package/vendor/impeccable/bundle/blobs/7fd1617d5a86b7a1a0bf9d6e291b334ac41a3efce31031eeaef11de7cd7e75b4 +325 -0
- package/vendor/impeccable/bundle/blobs/800cf1c0392b24de7c0a1c6ea6778ecb433dec71c49a150bce96a98477527b2f +1 -0
- package/vendor/impeccable/bundle/blobs/808291e15746c9a64d9ede3ad3f06664b0a72970aa95052e064a96f1bfbed361 +54 -0
- package/vendor/impeccable/bundle/blobs/81666fc7f783b4e3514db6554e713dc0479bd9cdedb06e93d15f8b579aae869a +105 -0
- package/vendor/impeccable/bundle/blobs/824b994782a1fe68a244bbdff7218a2e0854655d90cc0fb5ade7ef9259ba6305 +46 -0
- package/vendor/impeccable/bundle/blobs/82a5e564563333aabb7ab4d2f8c26c785dfe2c2416ac6e9f30cba31440676194 +46 -0
- package/vendor/impeccable/bundle/blobs/835f19a0a3812f3652dd6979a2ce5597f654fd01f26e1b420b92d5f42b997ce4 +121 -0
- package/vendor/impeccable/bundle/blobs/84a06415956986cb215139b3efda7b3c7a5bb6f502a3b3d9300f0744a970e620 +99 -0
- package/vendor/impeccable/bundle/blobs/84df879a0332a56ece4bff1922ecf4f50635951b3c67e67eb46f31bc5d30fa9a +111 -0
- package/vendor/impeccable/bundle/blobs/85b9c2d051de94ee9129c58be111946f73035ca62bbd2a3936f4fa48768fe5cf +145 -0
- package/vendor/impeccable/bundle/blobs/869fa5390b84bfd00d072f5280a9002ea3e3936edf5985241be641a87f03ff7b +41 -0
- package/vendor/impeccable/bundle/blobs/86d10faab62da852aa1f4304157871545c853da708b6fe61c80aefb552c1f300 +84 -0
- package/vendor/impeccable/bundle/blobs/87b3db688c7963898bda8096f7868fed05ec5a0a80d14298e8b906b70cdf9c42 +416 -0
- package/vendor/impeccable/bundle/blobs/88749ebbe9bc87250765a07c2b959508262bd0e276ad60baa53e6e48c3579143 +806 -0
- package/vendor/impeccable/bundle/blobs/896da399bafcffb0623bdd81bb18709d6eab25c9d5917e739c8798f31ff0d076 +46 -0
- package/vendor/impeccable/bundle/blobs/89eb0206a0d9308c6c6a7cc01bc4fd8812d2bd34bb9a831988c5d86fac2c60de +42 -0
- package/vendor/impeccable/bundle/blobs/8a1c872773996dfa1c1eb765ac7ed8e8d41f99d4f12f090b4725b694e85eaa62 +336 -0
- package/vendor/impeccable/bundle/blobs/8a2d316593a631579bbb2f3fcb90d4488f85e97f69698dd2dd4fb50766f537d3 +325 -0
- package/vendor/impeccable/bundle/blobs/8b23562ccc3e41609ce6e67fdad6cc57b6c961964c329eff6975a1b4c5471c0d +111 -0
- package/vendor/impeccable/bundle/blobs/8c06daf096984cf71cf4133ea284dd6eaf503208da828816836ea41dfb69a234 +80 -0
- package/vendor/impeccable/bundle/blobs/8c34f78d71ac02c99303c7e0ca9ef30341aa9ecdeb75804dcba7e36a127914c1 +84 -0
- package/vendor/impeccable/bundle/blobs/8e7bb79db7331b93f99de314dd5599de8587ec0b6c25e26cf1efab25c0777fcb +86 -0
- package/vendor/impeccable/bundle/blobs/8eb39a13e3d3650d4261f8fb06e91d6c0b888ca12ddbd3a5610cd8f0b05ad176 +69 -0
- package/vendor/impeccable/bundle/blobs/8eb466778023fccea641654d662157b123eeb360f4a0875bf6fbe3d93680851c +24 -0
- package/vendor/impeccable/bundle/blobs/8f0867db7c6f6a54348a0d951f198a1bd852cd12505d821e6e1ac6bd42e7fcea +87 -0
- package/vendor/impeccable/bundle/blobs/8f651cb1f8cde0acc5cc511b77fddd98558a527f54974698a1650b0fd7e849a7 +43 -0
- package/vendor/impeccable/bundle/blobs/8ff60b8b5369d364f732f8de10479a39294e65341b3e0b6497b21de5c8e34b2d +806 -0
- package/vendor/impeccable/bundle/blobs/904859c8160b02330b04db23a8eeeb4ef55bcaa10f5208b8d73a1718334633e7 +84 -0
- package/vendor/impeccable/bundle/blobs/910461b1c1f8216155165955c860a884a1e2f557cb38f21ef512ea90ef6503c2 +136 -0
- package/vendor/impeccable/bundle/blobs/9205e222bc6565b37fb504ceec93233c2d2a456802b69d16e6b1c44723907c4c +5 -0
- package/vendor/impeccable/bundle/blobs/93eda27117930692a20f668f1cb0a80b7e14ab865998faba567cd721116081d4 +84 -0
- package/vendor/impeccable/bundle/blobs/943b0d7c9ce4f6802d8440a07b2ad3c61cbd1cc00ab63962bab7eea9ca584d20 +46 -0
- package/vendor/impeccable/bundle/blobs/948326fab89f0d5c07355a06b9b9c30d08bba2e3a673a0151ebbf5a39dff7b9a +40 -0
- package/vendor/impeccable/bundle/blobs/94b4ce6299fea93d9f256b2d25705961a76bc5ea940c56db4145686ebc99df1b +89 -0
- package/vendor/impeccable/bundle/blobs/95b07450ad1ea0b7adc369587b06e52404945bbaa5d87f7491fac7ffd0e6e2ae +11 -0
- package/vendor/impeccable/bundle/blobs/960cb922bc934adbf9192e9428ff6bec1f382038166f02a785939c93b7391067 +139 -0
- package/vendor/impeccable/bundle/blobs/96e2e6bd4fcf9a2c6da65fb029f96d9176308fae2efd9d8653d3b8d838960e07 +44 -0
- package/vendor/impeccable/bundle/blobs/96e508039c719c0815701c36b8418b18baee1967f915fa29b23b84861ae8ea94 +127 -0
- package/vendor/impeccable/bundle/blobs/98afc4c6da252e90c6b783079b6f157bf94a13dd4351392e881edd2a100edf6a +105 -0
- package/vendor/impeccable/bundle/blobs/9a2c08ee2516d2ee87129e7ebe6a0895f9990c9852d1f6fa7e70be9a6a88a659 +234 -0
- package/vendor/impeccable/bundle/blobs/9b2fc50c5062073d097140cde85602bba181e325ec6b9eea1bd3da74582acb9d +46 -0
- package/vendor/impeccable/bundle/blobs/9b85b85443aec09918befb83208c72f475457db8261a8fc5e83ef7eec474c869 +145 -0
- package/vendor/impeccable/bundle/blobs/9deb14303b421b5a9232755b5b9f317716f33e1e211557a98a00a9c409775c4d +145 -0
- package/vendor/impeccable/bundle/blobs/9e161532dc6731581d7a5f35bda5a2865e5248df7aff90e6dfc9221409893e35 +54 -0
- package/vendor/impeccable/bundle/blobs/9eb03b319ce7a2b281bc85ed1b0a437eb05ab2f765fc267354f9f9e6cbfadc25 +806 -0
- package/vendor/impeccable/bundle/blobs/9f1151faffbaadba0ddf5c09a4b2a82c9a12c900a2c1a9dac9863ba9ba0f420e +54 -0
- package/vendor/impeccable/bundle/blobs/a1a56df5fd51be403ca85a2f8054bb6f2bfeee443556c7798c2482e412fb6a09 +54 -0
- package/vendor/impeccable/bundle/blobs/a1dbde501ffabb50f30f28f2de6755b5e91b3d4028292c5a3abd3358106eb457 +37 -0
- package/vendor/impeccable/bundle/blobs/a1e4febca3455787d7c753fe177a150dccde6e742957de400b0307247802d200 +145 -0
- package/vendor/impeccable/bundle/blobs/a423108e7e31a54564e2e0794186394f842625fd9f7d7ce6e6615362511503a2 +93 -0
- package/vendor/impeccable/bundle/blobs/a4cfd2330c8cca94b62986679b3f9e3bb9ada0cb30c2c63c5d19c6039f5a45ae +104 -0
- package/vendor/impeccable/bundle/blobs/a5371492582dbeb69b24a1a2947b256a2da8a4d55917af709bbab6e452d9d23c +145 -0
- package/vendor/impeccable/bundle/blobs/a55f016c046cb6a27c55bd7f346375aeb506a755c4fbca19a5f92dbd42309c23 +59 -0
- package/vendor/impeccable/bundle/blobs/a7045711a1f0dd2cd5bd98e57ff615f638d7e29738bdd618cf15e83fea5993b9 +325 -0
- package/vendor/impeccable/bundle/blobs/a7f036f4217933db8a96cf2f0ba251b15f388839d62bcf95720ce0b7152dd185 +806 -0
- package/vendor/impeccable/bundle/blobs/a8547c8565979894f0c07f92a96ac2a38e681a31fbf155ffeefc7566e185d9c2 +39 -0
- package/vendor/impeccable/bundle/blobs/a8f4056a85706c0c8f80ec48e9b437e198464100aa42786f9252051f4b931c19 +111 -0
- package/vendor/impeccable/bundle/blobs/a9515f6f084d8f51c378eb3cdc6db1f12e06dba2d32fc61b7ee7950fa2586f2e +24 -0
- package/vendor/impeccable/bundle/blobs/a9856cb40da6519b1334bcfc75a4fbe83bef39ca86ee6f3effcb2a96794c627c +127 -0
- package/vendor/impeccable/bundle/blobs/a98b397cedeeaa1da57f3395b3d9b6c1fc477f4247fb9dc13e4da3da588283ff +54 -0
- package/vendor/impeccable/bundle/blobs/a9d2203acd45ca33a13d5c68b02b23ed512425ac15f0e8438318ed124b43729d +61 -0
- package/vendor/impeccable/bundle/blobs/ac695dd89d5f1261004cfa966526f5d5e913c92fa0640d4d71cb42493effad08 +131 -0
- package/vendor/impeccable/bundle/blobs/ad389ab12800738b0e5c97618278b7a824654b25990166ec9f389caa5c3386ca +37 -0
- package/vendor/impeccable/bundle/blobs/add1bee76f897f989166a5b9ad1b38d9173248e29d668d5c885ae9a0eff73861 +105 -0
- package/vendor/impeccable/bundle/blobs/af34b8af89edb10e228c0482754423f48238fce816eceb8703b8781c130da54e +24 -0
- package/vendor/impeccable/bundle/blobs/b0e1a0721a1e47675a8750cfb608138743dd9fa9c047146e5cc8f82b9041be7a +806 -0
- package/vendor/impeccable/bundle/blobs/b14dc725606717be881a058bb691c0af1860cc8ad98d48e5a4789fe1a7de5458 +806 -0
- package/vendor/impeccable/bundle/blobs/b161198874e4e77599bc31691e78790be14bacc2eb03be168c8a7543ece9fbe1 +145 -0
- package/vendor/impeccable/bundle/blobs/b29e10f4506af2277739ad2373bc91c9fff41dbe76c9907f45152b4178cc6b6c +105 -0
- package/vendor/impeccable/bundle/blobs/b2d71ff0df7ed49e06dfc4acfce3d3f7eb48afa68be04763ee8c08354df50a07 +97 -0
- package/vendor/impeccable/bundle/blobs/b2f60e0154bf0e687badc46d8c8420e2118a9a6e21162050722be779dc02cb6d +111 -0
- package/vendor/impeccable/bundle/blobs/b314a0c5bd844f6471ea3031aeb9299674d972fbdd1615d99d16478de437d26d +84 -0
- package/vendor/impeccable/bundle/blobs/b31ff29c7a1ea979c6d039f7e8d17007410697ab49536690dca109f0af3f20f8 +336 -0
- package/vendor/impeccable/bundle/blobs/b3782f2d9215eb0f5df4fe3c0e0bec07cef011e1836d4d0e45ef02bc48d3adde +24 -0
- package/vendor/impeccable/bundle/blobs/b4def5b57733b6ba233570bd5691a536901f8b15479fc0111a2cde56224d0e1a +325 -0
- package/vendor/impeccable/bundle/blobs/b5f4fbb4a044c3f5ec14adc847222488f00fccabbf79ecd0b21084c8d319d616 +105 -0
- package/vendor/impeccable/bundle/blobs/b6022a8c7200e96b0b55c2ff599a01d64123a2f5fe01557d4ca5192a6e0f0b0c +145 -0
- package/vendor/impeccable/bundle/blobs/b6a2ef031313d3848ab2928875298550836f0f9ff7bdf5772e918c5c610ea448 +806 -0
- package/vendor/impeccable/bundle/blobs/b6dfd3df9a371e7d179d365cc1d72c11d4ed91b6507c0e1dbec0843419542f66 +84 -0
- package/vendor/impeccable/bundle/blobs/b7fcd2b03539d1029c8774fa806e6f4c677448e9e97e15f69b066022536c5491 +80 -0
- package/vendor/impeccable/bundle/blobs/b824bb76a657d3edd65e89807dcb21a3679eab39292423066e11368b35afba79 +325 -0
- package/vendor/impeccable/bundle/blobs/b8d49a3cab3428d9f351502e9c2c5802cef187e0d2af626ef3e1cd1837fd06bf +105 -0
- package/vendor/impeccable/bundle/blobs/bad9250670c18d89722563fd747bae4c4bec64d1db0ee09d12d4fea04fe271b8 +84 -0
- package/vendor/impeccable/bundle/blobs/bb069b43c09109d7031b0374e31955749fec657b252d39782f11e8985aca2b51 +131 -0
- package/vendor/impeccable/bundle/blobs/bb36665889124a0b6e15f16045265737449c3bdcf2712cdb08af3cfa01563e2b +14 -0
- package/vendor/impeccable/bundle/blobs/bb59a1f78f3d2aa78e4b024fe203117155f50946a9e4bbe65c1b3b3abdcee356 +104 -0
- package/vendor/impeccable/bundle/blobs/bb9d4bb369216e892eea25adeaefc5a3e09bb4abd31e3475b79e47b3aee2a6af +806 -0
- package/vendor/impeccable/bundle/blobs/bc5f71f1129d0f2c310d913d07c8dc609a1d25644121bd78c308f42d52a0b9e9 +86 -0
- package/vendor/impeccable/bundle/blobs/bc7a5128cfed46148396c08798b6b9429406fbe477e84e331a36ee2840b6b776 +111 -0
- package/vendor/impeccable/bundle/blobs/bcc05ea92faebb5c74037a9d4263a5ce9a56f5ab07c8ab3c59ee704d8cade745 +24 -0
- package/vendor/impeccable/bundle/blobs/bdf9a59beea111ac6f98f5624854feb5a5a1d60b1989edbbfabf3dc6f357a7e6 +105 -0
- package/vendor/impeccable/bundle/blobs/bdfd2a879ca65e437481eac5309f2283da225121630935d89ed902cfdf470c8e +105 -0
- package/vendor/impeccable/bundle/blobs/bea6ebfda78c51b9cf372097a1d77431d0f6bcd96eadec13a2ac95afbb87fb6d +104 -0
- package/vendor/impeccable/bundle/blobs/bead87679caad7c537dd7c04c3bb78be56ac7eec279ad6aad7322f48ff2df2d9 +312 -0
- package/vendor/impeccable/bundle/blobs/bf3b8883f8550744e08754af82a78939ab8b1237e5fad6f38d819e2f17e8a389 +104 -0
- package/vendor/impeccable/bundle/blobs/bf92a4a51b29de9661c5fa82f3d79244718a67d385ef661990f0c4a5b367e843 +104 -0
- package/vendor/impeccable/bundle/blobs/bfc51972fbf387566dc9e29c8b1af479a66ab401fdbce659fae9e6a5a9d85316 +69 -0
- package/vendor/impeccable/bundle/blobs/c02feba25a961a72647ad317aba2d65baeeed53c4cdcc072f25bb37f4d867d43 +84 -0
- package/vendor/impeccable/bundle/blobs/c1cb6877ca99a0c1b38ba0c7d59f32702d3022f6821d8045f7133f7c40b6362f +242 -0
- package/vendor/impeccable/bundle/blobs/c1f3766091019b6f9183bc1d11b1e0fe03d44c168dc05a682c55df32f904dcfd +33 -0
- package/vendor/impeccable/bundle/blobs/c327bf17f2af186f87164dee5fb5468746a9b137f0b604365d531ac9387f3712 +325 -0
- package/vendor/impeccable/bundle/blobs/c36f6aac0ddf52eabbb21df09fd3310540dca6b09e7a4017d18e94c06c469405 +46 -0
- package/vendor/impeccable/bundle/blobs/c3ad2a5fa570876af6645c48d246c664859e19f253d2dc9e0ead34e785d5b40a +84 -0
- package/vendor/impeccable/bundle/blobs/c6a0ec6c28ae55fe539f0f41a507b1638495afd285d6eb15c00245fc8cc7e7fe +42 -0
- package/vendor/impeccable/bundle/blobs/c6f15d20d8d8748c4c475ff70cdb0ee426f2e6c9e7eab6169311f4dffd279ea1 +54 -0
- package/vendor/impeccable/bundle/blobs/c83d6a13fdfb58835c845f61aed3fc6dca17b5569d33387ced840bc13424f354 +84 -0
- package/vendor/impeccable/bundle/blobs/c9284892cb1f21aaeaf93fdf2e9e7a679d05e0baa8ddf309a79a9790d262ad38 +806 -0
- package/vendor/impeccable/bundle/blobs/cb8caddbb3919e5bf7f252143b519fb16db28a244642d937b186cb89962d9201 +828 -0
- package/vendor/impeccable/bundle/blobs/cbd8bd68fa00935dd0f179adb169252629cf7ee443ea9dc7db77e7ef2cf77446 +4 -0
- package/vendor/impeccable/bundle/blobs/cf3ae16765e7b5bc333ef76e24ab37f080e3d62e931c4986158e3cbcda6b9f7a +46 -0
- package/vendor/impeccable/bundle/blobs/d07e3131cdf3e392e59eaa3e2f59fcb0799d9494df4adfee12a21067fb8365ce +37 -0
- package/vendor/impeccable/bundle/blobs/d1366aa4802b364893c2a14b16fe95c3b7fab79f9f69eb272fd1538f7cb1ce2c +105 -0
- package/vendor/impeccable/bundle/blobs/d15a2914d93e07a4956acd5c8b8211af17380f527acd10d8acf4f4920badaaaf +89 -0
- package/vendor/impeccable/bundle/blobs/d1faa55eb956033d28e9f27fd2bc2a9f62c5da0f0abd6534819cc0a04db54d9d +37 -0
- package/vendor/impeccable/bundle/blobs/d1fbd55074abb2251bdaa03749d34acc42c38e46e47549f18f5848df57d43c42 +86 -0
- package/vendor/impeccable/bundle/blobs/d2455359baf5f9e75360c7094e28a16937c8674619e07d58f30d2b5abfd31e53 +105 -0
- package/vendor/impeccable/bundle/blobs/d658c48ffbe0031e8e3b318996cad6ceafe29e40aa50d5bb25e4bf1d6839dc7c +89 -0
- package/vendor/impeccable/bundle/blobs/d6a1fa1689642a6db9027493747d7ed54f9e0cae660472022c0a0a8dfdead3f4 +54 -0
- package/vendor/impeccable/bundle/blobs/d7211a816aa8ca1111701930f7cdab82b4c8caa94c9a37522c1d7945209b01c2 +84 -0
- package/vendor/impeccable/bundle/blobs/d87879329982d608866e4babd31c61438ec34c68483e529761fbf420203eeebd +104 -0
- package/vendor/impeccable/bundle/blobs/daa2a8ecd874f9f940dfd72aaa329318b06bb9be25515be85fea84c871b637a6 +145 -0
- package/vendor/impeccable/bundle/blobs/dcf7340da023e64144af5768b8bf44ecf45b1bfdec12d3b1c9e6618f17f8c60a +131 -0
- package/vendor/impeccable/bundle/blobs/dde1b74aeab3d90320e134f0ed0422bef99917dcab4c1749aa1720a2c94f725f +37 -0
- package/vendor/impeccable/bundle/blobs/de1b7404f4cdfd7b515196afb17b74b1980f0bc88cb8681ae93a76ca48ec7bdb +167 -0
- package/vendor/impeccable/bundle/blobs/df0eb9e9a484fc7b8a0f3e50573a7d7f81e0f17598ac30d9f3fe5a6c6aa5fefa +37 -0
- package/vendor/impeccable/bundle/blobs/df23e9ee5b689a05ed88f42e9a36aaffa2e6e28b1d56e2832acaa1d3603fd363 +105 -0
- package/vendor/impeccable/bundle/blobs/df4f14df1daaad1606b682995f649da19a85debf264092447b3b7ddb8b4bc1ce +147 -0
- package/vendor/impeccable/bundle/blobs/dfd6f341b156bc604e7556b27cba437d5870fbc82d4c673d0127cf18151b2226 +99 -0
- package/vendor/impeccable/bundle/blobs/e02ba7f4417e84b3bd5ec65287c4a14cf163ca3ac6f8ee37d8f709d0c8b0b6d2 +84 -0
- package/vendor/impeccable/bundle/blobs/e21af575fcc0f1df54ae422bea4dfa1e5211422606908919f6a86e19e0d5c20c +89 -0
- package/vendor/impeccable/bundle/blobs/e26ddd48211aae08fe6debf2a7a4308aa081ed224668cde528e451888db0e3e3 +325 -0
- package/vendor/impeccable/bundle/blobs/e2e275495354eeccb7e59af7d74e2ff1f371839bd6aaec1266428760995fb24c +104 -0
- package/vendor/impeccable/bundle/blobs/e2f98c4136d0ab70ec32fcdef58edb20ed8ec4f6cc067e0dae952b22cfd6a471 +24 -0
- package/vendor/impeccable/bundle/blobs/e3c331cc21d9a216e25e08628610ea99c97e150893c3d26e5c0cecc532f26d7b +24 -0
- package/vendor/impeccable/bundle/blobs/e44ca51f24c4736f9aee6024182b0409aa12ec94812b7ec94745e0999ed06a70 +29 -0
- package/vendor/impeccable/bundle/blobs/e49d2b0110c55751da3c965b4ae4d294aa676c961a09f8efbbbf22c1ec7c4fa0 +24 -0
- package/vendor/impeccable/bundle/blobs/e68467ba99684d8c975a8a2725145d29db41d70659c7544ea54cc6632660cea3 +127 -0
- package/vendor/impeccable/bundle/blobs/e71524578eb2bda3b8d2da3d8b8371239a2179c5fa866f9f7e48bcac45a8cd6f +84 -0
- package/vendor/impeccable/bundle/blobs/e71d6b97680084a7ccec01844e658cbd2042aec00da0c91bec62a240ad7dcf6a +145 -0
- package/vendor/impeccable/bundle/blobs/e7dd10af2c3c18c60dc20734d55ff870c323a10dadd337600f7bb980fc6b53c8 +327 -0
- package/vendor/impeccable/bundle/blobs/e802e4f7bdc89050a9c0f2ca506e1d493a2316e6e810c0336c57aa073717ef3e +50 -0
- package/vendor/impeccable/bundle/blobs/e8ee6c08e94b80324173d89d6f4cdc5b4829ea6858b3a11fc186588a490cada4 +46 -0
- package/vendor/impeccable/bundle/blobs/e9da72a13eb3411d6bbb316953022f62abc4434f505e5345907b216eda9f793b +39 -0
- package/vendor/impeccable/bundle/blobs/ea8432c90c30ecb0426662a681ead5c0941113079704e1a766cda09e85b15b4f +111 -0
- package/vendor/impeccable/bundle/blobs/eaa50e8cd95e00a94a257db2bff4eafd820696ba75a08a384a00517c3402924e +325 -0
- package/vendor/impeccable/bundle/blobs/eb3213b9c9f4d6b2f153e7b457f13aa131bcf633695229dad4eac39a920bdf38 +46 -0
- package/vendor/impeccable/bundle/blobs/ec58806f16fc7ba29bccef08f2e158cd00be077ce05d45e943a59bd26dc6dc55 +312 -0
- package/vendor/impeccable/bundle/blobs/ec6338b20047099601e4bac8b2efcd597f800d5e437259f6c15d23090400621b +325 -0
- package/vendor/impeccable/bundle/blobs/edddeb3fad88adec9a055b1bf9d5c75418cbe97a13b1a7f6765e73249e482563 +144 -0
- package/vendor/impeccable/bundle/blobs/ee0a15fcfc244b76b896a2650a17b35e444d4311166b69a3cfa32d11f8f44851 +30 -0
- package/vendor/impeccable/bundle/blobs/ee6d6d127c1c2ab3526d529a8e3698be2185b5e346ac617f37501de2c0698b97 +99 -0
- package/vendor/impeccable/bundle/blobs/ef0b8eca20e1321cf7216fd0bda41ce54b0cca197cfd1b075eb51f3436f59059 +24 -0
- package/vendor/impeccable/bundle/blobs/ef2dde00030580ed2765cbf7be9b2ea4a6f64cb915b804fd6f6abcf38051c7b9 +234 -0
- package/vendor/impeccable/bundle/blobs/f0c4d0615c7d520dfc2536c01cc7f1f3aab9b60ddc399ba01289fe62edb12370 +24 -0
- package/vendor/impeccable/bundle/blobs/f1601095679d7d8cf6fef6845598c70d8734190709c1404fa0026e28fef2faaa +325 -0
- package/vendor/impeccable/bundle/blobs/f173ff03f989f162cee815feb2d8ca72daf00019c48694d89db16d52171a79c0 +24 -0
- package/vendor/impeccable/bundle/blobs/f424dafa190533cd32c0bc3e4131d0c472d58e16bb191eab14f0ae73c2cea917 +37 -0
- package/vendor/impeccable/bundle/blobs/f597742c8e5562263d3bce725cb55e920d8c2c60223f41a632d523ca30cdd12b +111 -0
- package/vendor/impeccable/bundle/blobs/f672ef8251a3ed4051a053d30819664951b17540b2899acd27d20e500c234abc +258 -0
- package/vendor/impeccable/bundle/blobs/f7916d0113da7a19d4e03c113d5563d181457e44f1646ecab9191cfee5ae776d +89 -0
- package/vendor/impeccable/bundle/blobs/f7a9e3f30fe07b0d98351730e9895d50bba96dd42fe91c0d9b9a76ef62e53322 +80 -0
- package/vendor/impeccable/bundle/blobs/f7b854effc55c8f07e40a415e0d6b5c333f4042fbc849fac73d52619c8d053a1 +54 -0
- package/vendor/impeccable/bundle/blobs/f964506c0fae87b3c2c1db7016ddc9be9ef970bbcf5548d684b997b5d5991586 +33 -0
- package/vendor/impeccable/bundle/blobs/f97a6891c80bbbc728edefcf4b638d1a823b38f3cb16ecd0fbb717734cc5c0c8 +46 -0
- package/vendor/impeccable/bundle/blobs/f9cbbad0cc08fb9bd69d4d3046067c6cf820b89cdaf7af8c81c671fb0a62b6ae +54 -0
- package/vendor/impeccable/bundle/blobs/fce6688138d2ceb1e3d2cde5231f54b1d8dc8748b4c95a7919aa83b6f924cf96 +127 -0
- package/vendor/impeccable/bundle/blobs/fd5579dbae1fc2495b7dddde48df9673acebd27953bbb56d506d3b470375c9e9 +37 -0
- package/vendor/impeccable/bundle/blobs/fe91fcf28638f95577af481a50edaf339d6c9a3ad3b9fa477bc81c116b8bc392 +139 -0
- package/vendor/impeccable/bundle/blobs/ff0ab1361f52d70d3ff0d23090d78794a75afdfa2f8c1cee5491dee69215faaa +105 -0
- package/vendor/impeccable/bundle/blobs/ff882c59c9aced92338aa194cc99a521ea2f083fd22eef3b1c1225e06bc72f66 +86 -0
- package/vendor/impeccable/bundle/manifest.json +1139 -0
- package/skills/dev-plan/evals/evals.json +0 -72
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# Chapter 10 - Async Patterns with Tokio
|
|
2
|
+
|
|
3
|
+
> Not part of the original Apollo handbook. Added to cover async Rust, which the other chapters only touch in passing (see [Chapter 4](chapter_04.md) for error traits across `.await`, and [Chapter 9](chapter_09.md) for `Send`/`Sync`).
|
|
4
|
+
|
|
5
|
+
Async Rust is not a separate language, but it does change which idioms are correct. Ownership, borrowing and error handling rules from the previous chapters still apply - what is new is that your code can be *suspended* at every `.await`, and everything held across that point must survive the suspension.
|
|
6
|
+
|
|
7
|
+
## 10.1 The Execution Model
|
|
8
|
+
|
|
9
|
+
A `Future` is **lazy**: nothing runs until something polls it. That is why an un-awaited future is a bug, not a background task.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Future (lazy) → poll() → Ready(value) | Pending
|
|
13
|
+
↑ ↓
|
|
14
|
+
Waker ← Runtime schedules
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
| Concept | Purpose |
|
|
18
|
+
|------------|------------------------------------------|
|
|
19
|
+
| `Future` | Lazy computation that may complete later |
|
|
20
|
+
| `async fn` | Function returning `impl Future` |
|
|
21
|
+
| `await` | Suspend until the future completes |
|
|
22
|
+
| `Task` | Spawned future running concurrently |
|
|
23
|
+
| `Runtime` | Executor that polls futures |
|
|
24
|
+
|
|
25
|
+
The practical consequences, each expanded later in this chapter:
|
|
26
|
+
|
|
27
|
+
* **Blocking a thread blocks every task on it.** Never call `std::thread::sleep`, blocking file I/O or CPU-bound loops inside `async fn` - see [10.9](#109-shared-state-and-resource-limits).
|
|
28
|
+
* **State held across `.await` must be `Send`** when the future is spawned on a multi-threaded runtime.
|
|
29
|
+
* **Cancellation is silent.** Dropping a future stops it wherever it was suspended, so cleanup belongs in `Drop`, not after the `.await` - see [10.6](#106-graceful-shutdown).
|
|
30
|
+
|
|
31
|
+
## 10.2 Project Setup
|
|
32
|
+
|
|
33
|
+
```toml
|
|
34
|
+
# Cargo.toml
|
|
35
|
+
[dependencies]
|
|
36
|
+
tokio = { version = "1", features = ["full"] }
|
|
37
|
+
futures = "0.3"
|
|
38
|
+
anyhow = "1.0"
|
|
39
|
+
tracing = "0.1"
|
|
40
|
+
tracing-subscriber = "0.3"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> `features = ["full"]` is fine for binaries. For libraries, enable only what you use (`rt`, `macros`, `sync`, `time`, ...) so downstream crates do not pay for the rest.
|
|
44
|
+
|
|
45
|
+
```rust
|
|
46
|
+
use anyhow::Result;
|
|
47
|
+
use tokio::time::{sleep, Duration};
|
|
48
|
+
|
|
49
|
+
#[tokio::main]
|
|
50
|
+
async fn main() -> Result<()> {
|
|
51
|
+
tracing_subscriber::fmt::init();
|
|
52
|
+
|
|
53
|
+
let result = fetch_data("https://api.example.com").await?;
|
|
54
|
+
println!("Got: {result}");
|
|
55
|
+
|
|
56
|
+
Ok(())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async fn fetch_data(url: &str) -> Result<String> {
|
|
60
|
+
sleep(Duration::from_millis(100)).await;
|
|
61
|
+
Ok(format!("Data from {url}"))
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 10.3 Concurrent Task Execution
|
|
66
|
+
|
|
67
|
+
`JoinSet` owns its tasks and aborts them when dropped, which makes it the default choice over a `Vec<JoinHandle<_>>`:
|
|
68
|
+
|
|
69
|
+
```rust
|
|
70
|
+
use anyhow::Result;
|
|
71
|
+
use tokio::task::JoinSet;
|
|
72
|
+
|
|
73
|
+
async fn fetch_all_concurrent(urls: Vec<String>) -> Result<Vec<String>> {
|
|
74
|
+
let mut set = JoinSet::new();
|
|
75
|
+
|
|
76
|
+
for url in urls {
|
|
77
|
+
set.spawn(async move { fetch_data(&url).await });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let mut results = Vec::new();
|
|
81
|
+
while let Some(res) = set.join_next().await {
|
|
82
|
+
match res {
|
|
83
|
+
Ok(Ok(data)) => results.push(data),
|
|
84
|
+
Ok(Err(e)) => tracing::error!("Task failed: {e}"),
|
|
85
|
+
Err(e) => tracing::error!("Join error: {e}"), // panic or abort
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Ok(results)
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> The nested `Result` is not noise: the outer one reports whether the *task* survived (panic/abort), the inner one whether the *work* succeeded. Collapsing them hides panics.
|
|
94
|
+
|
|
95
|
+
Unbounded spawning is a denial of service against yourself. When the input size is caller-controlled, bound the concurrency:
|
|
96
|
+
|
|
97
|
+
```rust
|
|
98
|
+
use futures::stream::{self, StreamExt};
|
|
99
|
+
|
|
100
|
+
async fn fetch_with_limit(urls: Vec<String>, limit: usize) -> Vec<Result<String>> {
|
|
101
|
+
stream::iter(urls)
|
|
102
|
+
.map(|url| async move { fetch_data(&url).await })
|
|
103
|
+
.buffer_unordered(limit) // at most `limit` in flight
|
|
104
|
+
.collect()
|
|
105
|
+
.await
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`select!` races futures and **drops the losers**:
|
|
110
|
+
|
|
111
|
+
```rust
|
|
112
|
+
use tokio::select;
|
|
113
|
+
|
|
114
|
+
async fn race_requests(url1: &str, url2: &str) -> Result<String> {
|
|
115
|
+
select! {
|
|
116
|
+
result = fetch_data(url1) => result,
|
|
117
|
+
result = fetch_data(url2) => result,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
> ❗ Every branch of `select!` must be cancel-safe. A future dropped mid-`.await` never resumes, so a branch that has already consumed bytes from a socket loses them. When in doubt, move the work into a spawned task and select on its handle instead.
|
|
123
|
+
|
|
124
|
+
## 10.4 Channels for Communication
|
|
125
|
+
|
|
126
|
+
Prefer message passing over shared mutable state: a channel makes ownership transfer explicit and avoids lock contention entirely.
|
|
127
|
+
|
|
128
|
+
| Channel | Shape | Use for |
|
|
129
|
+
|---------------|-----------------------------|----------------------------------|
|
|
130
|
+
| `mpsc` | many producers, one consumer | work queues, actor inboxes |
|
|
131
|
+
| `broadcast` | many producers, many consumers | fan-out events (each gets a copy) |
|
|
132
|
+
| `oneshot` | one producer, one value | request/response replies |
|
|
133
|
+
| `watch` | one producer, many consumers | latest-value state (config, health) |
|
|
134
|
+
|
|
135
|
+
```rust
|
|
136
|
+
use tokio::sync::{broadcast, mpsc, oneshot, watch};
|
|
137
|
+
|
|
138
|
+
// mpsc: bounded, so a slow consumer applies backpressure to producers
|
|
139
|
+
async fn mpsc_example() {
|
|
140
|
+
let (tx, mut rx) = mpsc::channel::<String>(100);
|
|
141
|
+
|
|
142
|
+
let tx2 = tx.clone();
|
|
143
|
+
tokio::spawn(async move {
|
|
144
|
+
let _ = tx2.send("Hello".to_string()).await;
|
|
145
|
+
});
|
|
146
|
+
drop(tx); // the loop below ends only once every sender is gone
|
|
147
|
+
|
|
148
|
+
while let Some(msg) = rx.recv().await {
|
|
149
|
+
println!("Got: {msg}");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// broadcast: every live receiver gets every message; slow ones get Lagged
|
|
154
|
+
async fn broadcast_example() {
|
|
155
|
+
let (tx, _) = broadcast::channel::<String>(100);
|
|
156
|
+
|
|
157
|
+
let mut rx1 = tx.subscribe();
|
|
158
|
+
let mut rx2 = tx.subscribe();
|
|
159
|
+
|
|
160
|
+
tx.send("Event".to_string()).unwrap();
|
|
161
|
+
|
|
162
|
+
let _ = rx1.recv().await;
|
|
163
|
+
let _ = rx2.recv().await;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// oneshot: a single value, consumed by awaiting the receiver
|
|
167
|
+
async fn oneshot_example() -> String {
|
|
168
|
+
let (tx, rx) = oneshot::channel::<String>();
|
|
169
|
+
|
|
170
|
+
tokio::spawn(async move {
|
|
171
|
+
let _ = tx.send("Result".to_string());
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
rx.await.expect("sender dropped without sending")
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// watch: receivers see only the latest value, never a backlog
|
|
178
|
+
async fn watch_example() {
|
|
179
|
+
let (tx, mut rx) = watch::channel("initial".to_string());
|
|
180
|
+
|
|
181
|
+
tokio::spawn(async move {
|
|
182
|
+
while rx.changed().await.is_ok() {
|
|
183
|
+
println!("New value: {}", *rx.borrow());
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
tx.send("updated".to_string()).unwrap();
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
> `mpsc::unbounded_channel` removes backpressure along with the bound - memory grows until the process dies. Reach for it only when the producer is provably bounded.
|
|
192
|
+
|
|
193
|
+
## 10.5 Async Error Handling
|
|
194
|
+
|
|
195
|
+
The rules from [Chapter 4](chapter_04.md) hold: `thiserror` for libraries, `anyhow` for binaries, `?` over match chains. Async adds one requirement - errors that cross a spawn or an `.await` boundary generally need `Send + Sync + 'static`.
|
|
196
|
+
|
|
197
|
+
```rust
|
|
198
|
+
use anyhow::{Context, Result};
|
|
199
|
+
use thiserror::Error;
|
|
200
|
+
|
|
201
|
+
#[derive(Error, Debug)]
|
|
202
|
+
pub enum ServiceError {
|
|
203
|
+
#[error("Network error: {0}")]
|
|
204
|
+
Network(#[from] reqwest::Error),
|
|
205
|
+
|
|
206
|
+
#[error("Database error: {0}")]
|
|
207
|
+
Database(#[from] sqlx::Error),
|
|
208
|
+
|
|
209
|
+
#[error("Not found: {0}")]
|
|
210
|
+
NotFound(String),
|
|
211
|
+
|
|
212
|
+
#[error("Timeout after {0:?}")]
|
|
213
|
+
Timeout(std::time::Duration),
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Binary/application code: anyhow plus context at each layer
|
|
217
|
+
async fn process_request(id: &str) -> Result<Response> {
|
|
218
|
+
let data = fetch_data(id).await.context("Failed to fetch data")?;
|
|
219
|
+
let parsed = parse_response(&data).context("Failed to parse response")?;
|
|
220
|
+
Ok(parsed)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Library code: a typed error the caller can match on
|
|
224
|
+
async fn get_user(db: &Db, id: &str) -> Result<User, ServiceError> {
|
|
225
|
+
match db.query(id).await? {
|
|
226
|
+
Some(user) => Ok(user),
|
|
227
|
+
None => Err(ServiceError::NotFound(id.to_string())),
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Every outbound call needs a deadline. Without one, a hung peer holds a task forever:
|
|
233
|
+
|
|
234
|
+
```rust
|
|
235
|
+
use std::future::Future;
|
|
236
|
+
use std::time::Duration;
|
|
237
|
+
use tokio::time::timeout;
|
|
238
|
+
|
|
239
|
+
async fn with_timeout<T, F>(duration: Duration, future: F) -> Result<T, ServiceError>
|
|
240
|
+
where
|
|
241
|
+
F: Future<Output = Result<T, ServiceError>>,
|
|
242
|
+
{
|
|
243
|
+
timeout(duration, future)
|
|
244
|
+
.await
|
|
245
|
+
.map_err(|_| ServiceError::Timeout(duration))?
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
> `timeout` cancels by dropping the future. Anything that was half-done is abandoned, so for non-idempotent work (a payment, a write) record intent *before* the call rather than assuming a timeout means "did not happen".
|
|
250
|
+
|
|
251
|
+
## 10.6 Graceful Shutdown
|
|
252
|
+
|
|
253
|
+
A task that ignores shutdown gets killed mid-write when the runtime drops. Give every long-lived task a cancellation branch.
|
|
254
|
+
|
|
255
|
+
```rust
|
|
256
|
+
use tokio::signal;
|
|
257
|
+
use tokio_util::sync::CancellationToken;
|
|
258
|
+
|
|
259
|
+
async fn run_server() -> Result<()> {
|
|
260
|
+
let token = CancellationToken::new();
|
|
261
|
+
let worker_token = token.clone();
|
|
262
|
+
|
|
263
|
+
let worker = tokio::spawn(async move {
|
|
264
|
+
loop {
|
|
265
|
+
tokio::select! {
|
|
266
|
+
_ = worker_token.cancelled() => {
|
|
267
|
+
tracing::info!("Task shutting down");
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
_ = do_work() => {}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
signal::ctrl_c().await?;
|
|
276
|
+
tracing::info!("Shutdown signal received");
|
|
277
|
+
|
|
278
|
+
token.cancel();
|
|
279
|
+
|
|
280
|
+
// Bound the wait: await the task, but do not hang forever on a stuck one
|
|
281
|
+
match tokio::time::timeout(Duration::from_secs(5), worker).await {
|
|
282
|
+
Ok(_) => tracing::info!("Clean shutdown"),
|
|
283
|
+
Err(_) => tracing::warn!("Worker did not stop in time"),
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
Ok(())
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
> Prefer joining the tasks over `sleep`-ing for a fixed grace period: a sleep is both too long on a fast shutdown and too short on a slow one. `CancellationToken` also has `child_token()`, which propagates cancellation down a task tree.
|
|
291
|
+
|
|
292
|
+
A `broadcast` channel works when you have no `tokio-util` dependency - every subscriber is woken by a single send:
|
|
293
|
+
|
|
294
|
+
```rust
|
|
295
|
+
use tokio::sync::broadcast;
|
|
296
|
+
|
|
297
|
+
async fn run_with_broadcast() -> Result<()> {
|
|
298
|
+
let (shutdown_tx, _) = broadcast::channel::<()>(1);
|
|
299
|
+
|
|
300
|
+
let mut rx = shutdown_tx.subscribe();
|
|
301
|
+
tokio::spawn(async move {
|
|
302
|
+
tokio::select! {
|
|
303
|
+
_ = rx.recv() => tracing::info!("Received shutdown"),
|
|
304
|
+
_ = async { loop { do_work().await } } => {}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
signal::ctrl_c().await?;
|
|
309
|
+
let _ = shutdown_tx.send(());
|
|
310
|
+
|
|
311
|
+
Ok(())
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## 10.7 Async Traits
|
|
316
|
+
|
|
317
|
+
Since Rust 1.75, `async fn` works directly in traits. Use it - it allocates nothing and needs no dependency:
|
|
318
|
+
|
|
319
|
+
```rust
|
|
320
|
+
pub trait Repository {
|
|
321
|
+
async fn get(&self, id: &str) -> Result<Entity>;
|
|
322
|
+
async fn save(&self, entity: &Entity) -> Result<()>;
|
|
323
|
+
async fn delete(&self, id: &str) -> Result<()>;
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
The catch is that such a trait is **not dyn-compatible** and its returned futures carry no `Send` bound, so a generic caller that spawns will not compile. Pick by how the trait is consumed:
|
|
328
|
+
|
|
329
|
+
| Need | Use |
|
|
330
|
+
|------------------------------------------|----------------------------------------------|
|
|
331
|
+
| Static dispatch, `impl Repository` bounds | native `async fn` in trait |
|
|
332
|
+
| `Send` bound for spawning | `fn get(..) -> impl Future<Output = ..> + Send` |
|
|
333
|
+
| `dyn Repository` / heterogeneous storage | `#[async_trait]` (boxes each future) |
|
|
334
|
+
|
|
335
|
+
This follows the rule from [Chapter 6](chapter_06.md): static where you can, dynamic where you must. `#[async_trait]` is not deprecated - it is the tool for the `dyn` case, at the cost of one `Box` allocation per call.
|
|
336
|
+
|
|
337
|
+
```rust
|
|
338
|
+
use async_trait::async_trait;
|
|
339
|
+
|
|
340
|
+
#[async_trait]
|
|
341
|
+
pub trait Repository: Send + Sync {
|
|
342
|
+
async fn get(&self, id: &str) -> Result<Entity>;
|
|
343
|
+
async fn save(&self, entity: &Entity) -> Result<()>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
pub struct PostgresRepository {
|
|
347
|
+
pool: sqlx::PgPool,
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
#[async_trait]
|
|
351
|
+
impl Repository for PostgresRepository {
|
|
352
|
+
async fn get(&self, id: &str) -> Result<Entity> {
|
|
353
|
+
sqlx::query_as!(Entity, "SELECT * FROM entities WHERE id = $1", id)
|
|
354
|
+
.fetch_one(&self.pool)
|
|
355
|
+
.await
|
|
356
|
+
.map_err(Into::into)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async fn save(&self, entity: &Entity) -> Result<()> {
|
|
360
|
+
sqlx::query!(
|
|
361
|
+
"INSERT INTO entities (id, data) VALUES ($1, $2)
|
|
362
|
+
ON CONFLICT (id) DO UPDATE SET data = $2",
|
|
363
|
+
entity.id,
|
|
364
|
+
entity.data
|
|
365
|
+
)
|
|
366
|
+
.execute(&self.pool)
|
|
367
|
+
.await?;
|
|
368
|
+
Ok(())
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Only possible because the trait is boxed by #[async_trait]
|
|
373
|
+
async fn process(repo: &dyn Repository, id: &str) -> Result<()> {
|
|
374
|
+
let entity = repo.get(id).await?;
|
|
375
|
+
repo.save(&entity).await
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## 10.8 Streams and Async Iteration
|
|
380
|
+
|
|
381
|
+
A `Stream` is the async counterpart of `Iterator`: many values over time, each awaited. Use one when results arrive incrementally and you do not want to buffer them all.
|
|
382
|
+
|
|
383
|
+
```rust
|
|
384
|
+
use async_stream::stream;
|
|
385
|
+
use futures::stream::{self, Stream, StreamExt};
|
|
386
|
+
|
|
387
|
+
fn numbers_stream() -> impl Stream<Item = i32> {
|
|
388
|
+
stream! {
|
|
389
|
+
for i in 0..10 {
|
|
390
|
+
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
391
|
+
yield i;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
async fn process_stream() {
|
|
397
|
+
let processed: Vec<_> = numbers_stream()
|
|
398
|
+
.filter(|n| futures::future::ready(*n % 2 == 0))
|
|
399
|
+
.map(|n| n * 2)
|
|
400
|
+
.collect()
|
|
401
|
+
.await;
|
|
402
|
+
|
|
403
|
+
println!("{processed:?}");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Amortize per-item cost (one DB round trip per chunk instead of per item)
|
|
407
|
+
async fn process_in_chunks() {
|
|
408
|
+
let mut chunks = numbers_stream().chunks(3);
|
|
409
|
+
|
|
410
|
+
while let Some(chunk) = chunks.next().await {
|
|
411
|
+
println!("Processing chunk: {chunk:?}");
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Interleave two sources, yielding whichever is ready first
|
|
416
|
+
async fn merge_streams() {
|
|
417
|
+
stream::select(numbers_stream(), numbers_stream())
|
|
418
|
+
.for_each(|n| async move { println!("Got: {n}") })
|
|
419
|
+
.await;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
> The same advice as [Chapter 1](chapter_01.md) applies: avoid an intermediate `.collect()` when the next stage can consume the stream directly.
|
|
424
|
+
|
|
425
|
+
## 10.9 Shared State and Resource Limits
|
|
426
|
+
|
|
427
|
+
Use `tokio::sync::Mutex`/`RwLock` **only** when the guard is held across an `.await`. Otherwise `std::sync` is faster and lets you lock from non-async code such as `Drop`.
|
|
428
|
+
|
|
429
|
+
```rust
|
|
430
|
+
use std::collections::HashMap;
|
|
431
|
+
use tokio::sync::RwLock;
|
|
432
|
+
|
|
433
|
+
struct Cache {
|
|
434
|
+
data: RwLock<HashMap<String, String>>,
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
impl Cache {
|
|
438
|
+
async fn get(&self, key: &str) -> Option<String> {
|
|
439
|
+
self.data.read().await.get(key).cloned()
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async fn set(&self, key: String, value: String) {
|
|
443
|
+
self.data.write().await.insert(key, value);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
> ❗ Never hold a lock across an `.await` that can block on the lock holder's own progress - that is the classic async deadlock. Narrow the critical section with a block, or `clone()` the value out and drop the guard before awaiting.
|
|
449
|
+
|
|
450
|
+
A `Semaphore` caps how much of a scarce resource is in flight at once. Note that the `Drop` below is **synchronous** - it cannot `.await`, so the free list uses `std::sync::Mutex`:
|
|
451
|
+
|
|
452
|
+
```rust
|
|
453
|
+
use std::sync::Mutex;
|
|
454
|
+
use tokio::sync::Semaphore;
|
|
455
|
+
|
|
456
|
+
struct Pool {
|
|
457
|
+
semaphore: Semaphore,
|
|
458
|
+
connections: Mutex<Vec<Connection>>, // std, not tokio: Drop cannot await
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
impl Pool {
|
|
462
|
+
fn new(size: usize) -> Self {
|
|
463
|
+
Self {
|
|
464
|
+
semaphore: Semaphore::new(size),
|
|
465
|
+
connections: Mutex::new((0..size).map(|_| Connection::new()).collect()),
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
async fn acquire(&self) -> PooledConnection<'_> {
|
|
470
|
+
// The permit guarantees a connection is available
|
|
471
|
+
let permit = self.semaphore.acquire().await.expect("semaphore never closed");
|
|
472
|
+
let conn = self.connections.lock().unwrap().pop().expect("permit implies a free conn");
|
|
473
|
+
PooledConnection { pool: self, conn: Some(conn), _permit: permit }
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
struct PooledConnection<'a> {
|
|
478
|
+
pool: &'a Pool,
|
|
479
|
+
conn: Option<Connection>,
|
|
480
|
+
_permit: tokio::sync::SemaphorePermit<'a>, // released on drop, after the push below
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
impl Drop for PooledConnection<'_> {
|
|
484
|
+
fn drop(&mut self) {
|
|
485
|
+
if let Some(conn) = self.conn.take() {
|
|
486
|
+
self.pool.connections.lock().unwrap().push(conn);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
> Spawning from `Drop` to run async cleanup does not work here: `tokio::spawn` requires `'static`, and `self.pool` is a borrow. Either make the cleanup synchronous as above, or hold an `Arc<Pool>` instead of a reference.
|
|
493
|
+
|
|
494
|
+
CPU-bound or blocking work must leave the async threads:
|
|
495
|
+
|
|
496
|
+
```rust
|
|
497
|
+
// Blocking I/O or long CPU work: move it off the runtime threads
|
|
498
|
+
let result = tokio::task::spawn_blocking(move || expensive_sync_work(input)).await?;
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## 10.10 Debugging and Instrumentation
|
|
502
|
+
|
|
503
|
+
Stack traces are near-useless across `.await` points; spans are how you regain the causal chain.
|
|
504
|
+
|
|
505
|
+
```rust
|
|
506
|
+
use tracing::{instrument, Instrument};
|
|
507
|
+
|
|
508
|
+
#[instrument(skip(pool))] // skip args that are large or secret
|
|
509
|
+
async fn fetch_user(pool: &PgPool, id: &str) -> Result<User> {
|
|
510
|
+
tracing::debug!("Fetching user");
|
|
511
|
+
// ...
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Attach a span to a spawned task - it is entered on every poll
|
|
515
|
+
let span = tracing::info_span!("worker", id = %worker_id);
|
|
516
|
+
tokio::spawn(
|
|
517
|
+
async move {
|
|
518
|
+
// ...
|
|
519
|
+
}
|
|
520
|
+
.instrument(span),
|
|
521
|
+
);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
For stuck tasks and starved workers, `tokio-console` shows every task's state and poll times live:
|
|
525
|
+
|
|
526
|
+
```toml
|
|
527
|
+
tokio = { version = "1", features = ["full", "tracing"] }
|
|
528
|
+
console-subscriber = "0.4"
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
```sh
|
|
532
|
+
RUSTFLAGS="--cfg tokio_unstable" cargo run
|
|
533
|
+
tokio-console
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## 10.11 Checklist
|
|
537
|
+
|
|
538
|
+
### ✅ Do
|
|
539
|
+
|
|
540
|
+
* **Bound concurrency** - `buffer_unordered`, `Semaphore` or a worker pool, never an unbounded `spawn` loop.
|
|
541
|
+
* **Use `JoinSet`** to own and abort groups of tasks instead of loose `JoinHandle`s.
|
|
542
|
+
* **Prefer channels over shared state**; reach for a lock only when a channel does not fit.
|
|
543
|
+
* **Put a timeout on every outbound call**, then decide what a timeout means for that operation.
|
|
544
|
+
* **Handle cancellation explicitly** with `CancellationToken` or a shutdown channel.
|
|
545
|
+
* **Instrument with `tracing`** - `#[instrument]` on async fns, `.instrument(span)` on spawned tasks.
|
|
546
|
+
|
|
547
|
+
### ❌ Don't
|
|
548
|
+
|
|
549
|
+
* **Don't block the runtime** - no `std::thread::sleep`, blocking I/O or heavy CPU work in `async fn`; use `spawn_blocking`.
|
|
550
|
+
* **Don't hold a lock across `.await`** - narrow the critical section or clone the value out first.
|
|
551
|
+
* **Don't use `tokio::sync::Mutex` by default** - `std::sync::Mutex` is cheaper unless the guard crosses an `.await`.
|
|
552
|
+
* **Don't ignore `JoinError`** - it is how a panicked task reports itself.
|
|
553
|
+
* **Don't forget `Send`** on futures you spawn, or on errors that cross task boundaries ([Chapter 9](chapter_09.md)).
|
|
554
|
+
* **Don't create a future you never await** - it does nothing at all.
|