@sayoriqwq/effect-harness 0.0.1
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/HARNESS.md +34 -0
- package/README.md +113 -0
- package/dist/bin/effect-harness.d.ts +2 -0
- package/dist/bin/effect-harness.js +39 -0
- package/dist/bin/effect-harness.js.map +1 -0
- package/dist/src/cli/Main.d.ts +6 -0
- package/dist/src/cli/Main.js +141 -0
- package/dist/src/cli/Main.js.map +1 -0
- package/dist/src/harness/CraftSkills.d.ts +14 -0
- package/dist/src/harness/CraftSkills.js +164 -0
- package/dist/src/harness/CraftSkills.js.map +1 -0
- package/dist/src/harness/Errors.d.ts +24 -0
- package/dist/src/harness/Errors.js +26 -0
- package/dist/src/harness/Errors.js.map +1 -0
- package/dist/src/harness/GuardrailRules.d.ts +6 -0
- package/dist/src/harness/GuardrailRules.js +303 -0
- package/dist/src/harness/GuardrailRules.js.map +1 -0
- package/dist/src/harness/Guardrails.d.ts +10 -0
- package/dist/src/harness/Guardrails.js +69 -0
- package/dist/src/harness/Guardrails.js.map +1 -0
- package/dist/src/harness/Init.d.ts +9 -0
- package/dist/src/harness/Init.js +234 -0
- package/dist/src/harness/Init.js.map +1 -0
- package/dist/src/harness/Model.d.ts +44 -0
- package/dist/src/harness/Model.js +169 -0
- package/dist/src/harness/Model.js.map +1 -0
- package/dist/src/harness/ModuleSources.d.ts +5 -0
- package/dist/src/harness/ModuleSources.js +47 -0
- package/dist/src/harness/ModuleSources.js.map +1 -0
- package/dist/src/harness/PnpmWorkspace.d.ts +2 -0
- package/dist/src/harness/PnpmWorkspace.js +23 -0
- package/dist/src/harness/PnpmWorkspace.js.map +1 -0
- package/dist/src/harness/Publish.d.ts +53 -0
- package/dist/src/harness/Publish.js +282 -0
- package/dist/src/harness/Publish.js.map +1 -0
- package/dist/src/harness/SelfVerify.d.ts +4 -0
- package/dist/src/harness/SelfVerify.js +56 -0
- package/dist/src/harness/SelfVerify.js.map +1 -0
- package/dist/src/harness/SourcePin.d.ts +12 -0
- package/dist/src/harness/SourcePin.js +320 -0
- package/dist/src/harness/SourcePin.js.map +1 -0
- package/dist/src/harness/Status.d.ts +12 -0
- package/dist/src/harness/Status.js +88 -0
- package/dist/src/harness/Status.js.map +1 -0
- package/dist/src/harness/TargetVerify.d.ts +8 -0
- package/dist/src/harness/TargetVerify.js +432 -0
- package/dist/src/harness/TargetVerify.js.map +1 -0
- package/dist/src/harness/TestContract.d.ts +6 -0
- package/dist/src/harness/TestContract.js +45 -0
- package/dist/src/harness/TestContract.js.map +1 -0
- package/dist/src/platform/Json.d.ts +8 -0
- package/dist/src/platform/Json.js +35 -0
- package/dist/src/platform/Json.js.map +1 -0
- package/dist/src/platform/ManagedFiles.d.ts +8 -0
- package/dist/src/platform/ManagedFiles.js +59 -0
- package/dist/src/platform/ManagedFiles.js.map +1 -0
- package/dist/src/platform/Process.d.ts +8 -0
- package/dist/src/platform/Process.js +80 -0
- package/dist/src/platform/Process.js.map +1 -0
- package/guide/default-capabilities.md +38 -0
- package/guide/index.md +49 -0
- package/guide/setup.md +64 -0
- package/harness/default-capabilities.md +32 -0
- package/harness/exposure.md +46 -0
- package/harness/feedback/index.md +60 -0
- package/harness/index.md +22 -0
- package/harness/official-inventory.md +85 -0
- package/harness/runtime/codex/AGENTS.fragment.md +28 -0
- package/harness/runtime/codex/agents/effect-worker.md +26 -0
- package/harness/runtime/codex/skills/effect-code/SKILL.md +72 -0
- package/harness/runtime/codex/skills/effect-code/agents/openai.yaml +4 -0
- package/harness/runtime/codex/skills/effect-feedback/SKILL.md +66 -0
- package/harness/runtime/codex/skills/effect-feedback/agents/openai.yaml +4 -0
- package/harness/source.md +52 -0
- package/harness/target-agent-contract.md +205 -0
- package/package.json +68 -0
- package/repos/craft-skills.manifest.json +34 -0
- package/repos/effect/.agents/skills/grill-me/SKILL.md +43 -0
- package/repos/effect/.agents/skills/jsdocs/SKILL.md +203 -0
- package/repos/effect/.agents/skills/scratchpad/SKILL.md +44 -0
- package/repos/effect/.agents/skills/scratchpad/agents/openai.yaml +7 -0
- package/repos/effect/.agents/skills/scratchpad/scripts/extract-example.mjs +260 -0
- package/repos/effect/.changeset/add-bigdecimal-sumall-multiplyall.md +5 -0
- package/repos/effect/.changeset/add-chunk-schema.md +5 -0
- package/repos/effect/.changeset/add-command-hidden.md +19 -0
- package/repos/effect/.changeset/add-config-nested.md +5 -0
- package/repos/effect/.changeset/add-flag-hidden.md +15 -0
- package/repos/effect/.changeset/add-from-string-schemas.md +5 -0
- package/repos/effect/.changeset/add-headers-remove-many.md +5 -0
- package/repos/effect/.changeset/add-indexeddb-kvs-layer.md +5 -0
- package/repos/effect/.changeset/add-make-msgpack.md +5 -0
- package/repos/effect/.changeset/add-make-option.md +5 -0
- package/repos/effect/.changeset/add-missing-tx-modules.md +11 -0
- package/repos/effect/.changeset/add-newtype-module.md +5 -0
- package/repos/effect/.changeset/add-scalar-show-operation-id.md +5 -0
- package/repos/effect/.changeset/add-schedule-tap.md +5 -0
- package/repos/effect/.changeset/add-schema-annotate-encoded.md +5 -0
- package/repos/effect/.changeset/add-schema-array-ensure.md +5 -0
- package/repos/effect/.changeset/add-schema-bigdecimal.md +5 -0
- package/repos/effect/.changeset/add-schema-datetime.md +5 -0
- package/repos/effect/.changeset/add-schema-option-from-optional-nullor.md +5 -0
- package/repos/effect/.changeset/add-schema-option-from-undefined-nullish.md +5 -0
- package/repos/effect/.changeset/add-schema-string-encoding.md +5 -0
- package/repos/effect/.changeset/add-sql-pglite.md +5 -0
- package/repos/effect/.changeset/add-standard-jsdoc-rule.md +5 -0
- package/repos/effect/.changeset/add-stream-broadcastn.md +5 -0
- package/repos/effect/.changeset/add-unstable-encoding-export.md +5 -0
- package/repos/effect/.changeset/afraid-cobras-like.md +5 -0
- package/repos/effect/.changeset/ai-openai-config-field-leak.md +6 -0
- package/repos/effect/.changeset/ai-openai-file-nullable-fields.md +5 -0
- package/repos/effect/.changeset/anthropic-4-6-structured-output.md +5 -0
- package/repos/effect/.changeset/asyncresult-exhaustive.md +5 -0
- package/repos/effect/.changeset/atom-stream-error-type.md +5 -0
- package/repos/effect/.changeset/beige-paths-sort.md +5 -0
- package/repos/effect/.changeset/better-apples-nail.md +5 -0
- package/repos/effect/.changeset/better-rocks-arrive.md +5 -0
- package/repos/effect/.changeset/big-pans-look.md +5 -0
- package/repos/effect/.changeset/blue-dingos-greet.md +5 -0
- package/repos/effect/.changeset/blue-ligers-cheat.md +5 -0
- package/repos/effect/.changeset/blue-onions-smile.md +5 -0
- package/repos/effect/.changeset/blue-ravens-type.md +5 -0
- package/repos/effect/.changeset/blue-trams-kiss.md +7 -0
- package/repos/effect/.changeset/bold-chairs-yawn.md +5 -0
- package/repos/effect/.changeset/bold-planets-shout.md +30 -0
- package/repos/effect/.changeset/breezy-meals-see.md +5 -0
- package/repos/effect/.changeset/bright-bugs-bow.md +5 -0
- package/repos/effect/.changeset/bright-canyons-clean.md +5 -0
- package/repos/effect/.changeset/bright-dogs-fail.md +5 -0
- package/repos/effect/.changeset/bright-flags-stand.md +5 -0
- package/repos/effect/.changeset/bright-laws-teach.md +5 -0
- package/repos/effect/.changeset/bright-lemons-dance.md +5 -0
- package/repos/effect/.changeset/bright-planes-smash.md +5 -0
- package/repos/effect/.changeset/bright-rats-attend.md +5 -0
- package/repos/effect/.changeset/bright-toes-rush.md +5 -0
- package/repos/effect/.changeset/bumpy-boxes-teach.md +5 -0
- package/repos/effect/.changeset/busy-lions-sneeze.md +5 -0
- package/repos/effect/.changeset/busy-maps-attend.md +7 -0
- package/repos/effect/.changeset/calm-buckets-own.md +5 -0
- package/repos/effect/.changeset/calm-carrots-march.md +7 -0
- package/repos/effect/.changeset/calm-cars-rest.md +5 -0
- package/repos/effect/.changeset/calm-panthers-nail.md +5 -0
- package/repos/effect/.changeset/calm-seas-smile.md +5 -0
- package/repos/effect/.changeset/calm-squids-hug.md +5 -0
- package/repos/effect/.changeset/chatty-poets-type.md +5 -0
- package/repos/effect/.changeset/chilled-mice-wash.md +5 -0
- package/repos/effect/.changeset/chilly-pumas-rule.md +5 -0
- package/repos/effect/.changeset/chubby-buckets-feel.md +5 -0
- package/repos/effect/.changeset/chubby-parents-flow.md +5 -0
- package/repos/effect/.changeset/chubby-planets-fall.md +5 -0
- package/repos/effect/.changeset/clean-balloons-tan.md +5 -0
- package/repos/effect/.changeset/clean-bulldogs-care.md +5 -0
- package/repos/effect/.changeset/clean-dryers-sneeze.md +5 -0
- package/repos/effect/.changeset/clean-geese-work.md +5 -0
- package/repos/effect/.changeset/clean-goats-wave.md +5 -0
- package/repos/effect/.changeset/clean-needles-shake.md +23 -0
- package/repos/effect/.changeset/clean-tires-guess.md +5 -0
- package/repos/effect/.changeset/clear-spies-boil.md +5 -0
- package/repos/effect/.changeset/cli-help-choices.md +5 -0
- package/repos/effect/.changeset/cold-knives-lie.md +35 -0
- package/repos/effect/.changeset/cold-rooms-show.md +5 -0
- package/repos/effect/.changeset/cold-sloths-wave.md +5 -0
- package/repos/effect/.changeset/compact-json-schema-enum.md +25 -0
- package/repos/effect/.changeset/config-withdefault-eager.md +7 -0
- package/repos/effect/.changeset/config.json +24 -0
- package/repos/effect/.changeset/consolidate-encoding.md +5 -0
- package/repos/effect/.changeset/consolidate-sql-error.md +16 -0
- package/repos/effect/.changeset/crisp-seas-warn.md +5 -0
- package/repos/effect/.changeset/cuddly-rooms-bet.md +5 -0
- package/repos/effect/.changeset/curly-poems-talk.md +5 -0
- package/repos/effect/.changeset/curly-spies-relax.md +5 -0
- package/repos/effect/.changeset/curvy-apples-float.md +5 -0
- package/repos/effect/.changeset/custom-http-security-openapi-generator.md +5 -0
- package/repos/effect/.changeset/cute-heads-thank.md +5 -0
- package/repos/effect/.changeset/cyan-loops-grow.md +5 -0
- package/repos/effect/.changeset/cyan-radios-switch.md +5 -0
- package/repos/effect/.changeset/deep-rivers-spend.md +5 -0
- package/repos/effect/.changeset/dirty-lamps-trade.md +5 -0
- package/repos/effect/.changeset/dirty-laws-wear.md +5 -0
- package/repos/effect/.changeset/duration-temporal-object-input.md +7 -0
- package/repos/effect/.changeset/eager-coats-cheat.md +5 -0
- package/repos/effect/.changeset/early-birds-dream.md +5 -0
- package/repos/effect/.changeset/early-donuts-argue.md +5 -0
- package/repos/effect/.changeset/early-peaches-check.md +6 -0
- package/repos/effect/.changeset/eff-691-default-logger-ordering.md +5 -0
- package/repos/effect/.changeset/eff-693-rpcgroup-handler-deps.md +5 -0
- package/repos/effect/.changeset/eff-694-cli-completions-module.md +5 -0
- package/repos/effect/.changeset/eff-695-layer-mock-dual-api.md +5 -0
- package/repos/effect/.changeset/eff-697-rpcserialization-json-array-decode.md +5 -0
- package/repos/effect/.changeset/eff-698-rpcserialization-unreachable-branch.md +5 -0
- package/repos/effect/.changeset/eff-700-httpapi-middleware-errors.md +12 -0
- package/repos/effect/.changeset/eff-701-httpapierror-respondable.md +5 -0
- package/repos/effect/.changeset/eff-704-stream-merge-predicate.md +5 -0
- package/repos/effect/.changeset/eff-705-layer-tap-apis.md +5 -0
- package/repos/effect/.changeset/eff-706-servicemap-mutate.md +6 -0
- package/repos/effect/.changeset/eff-716-response-id-tracker-map.md +5 -0
- package/repos/effect/.changeset/eff-717-openai-socket-cancel.md +5 -0
- package/repos/effect/.changeset/eff-718-embedding-model-surface.md +13 -0
- package/repos/effect/.changeset/eff-725-fix-catch-jsdoc.md +5 -0
- package/repos/effect/.changeset/eff-726-model-dimensions.md +7 -0
- package/repos/effect/.changeset/eff-727-cli-help-alignment.md +5 -0
- package/repos/effect/.changeset/eff-730-language-model-incremental-fallback.md +5 -0
- package/repos/effect/.changeset/eff-736-cached-with-ttl.md +5 -0
- package/repos/effect/.changeset/eff-738-cron-prev.md +5 -0
- package/repos/effect/.changeset/eff-739-openai-function-call-done.md +5 -0
- package/repos/effect/.changeset/eff-740-missing-summary-parts.md +5 -0
- package/repos/effect/.changeset/eff-742-http-client-request-web.md +5 -0
- package/repos/effect/.changeset/eff-744-sqlite-migrator-lock.md +5 -0
- package/repos/effect/.changeset/eff-746-fixed-iteration-catchup.md +5 -0
- package/repos/effect/.changeset/eff-747-unify-effect.md +5 -0
- package/repos/effect/.changeset/eff-754-url-builder-any.md +6 -0
- package/repos/effect/.changeset/eff-755-references-core.md +5 -0
- package/repos/effect/.changeset/eff-769-select-text-highlight.md +5 -0
- package/repos/effect/.changeset/eff-774-mutable-list-append-all-empty-array.md +5 -0
- package/repos/effect/.changeset/eff-777-schema-make-effect.md +5 -0
- package/repos/effect/.changeset/eff-778-http-middleware-path-logger.md +5 -0
- package/repos/effect/.changeset/eff-779-keyvaluestore-layer-sql.md +5 -0
- package/repos/effect/.changeset/eff-780-layer-unify.md +5 -0
- package/repos/effect/.changeset/eff-781-fix-stream-toqueue-types.md +5 -0
- package/repos/effect/.changeset/eff-782-httpapi-status-literals.md +5 -0
- package/repos/effect/.changeset/eff-783-atom-http-api-errors.md +5 -0
- package/repos/effect/.changeset/eff-819-cluster-workflow-shard-groups.md +5 -0
- package/repos/effect/.changeset/eight-turkeys-own.md +7 -0
- package/repos/effect/.changeset/eighty-lies-deny.md +5 -0
- package/repos/effect/.changeset/eighty-poets-draw.md +9 -0
- package/repos/effect/.changeset/eighty-swans-scream.md +5 -0
- package/repos/effect/.changeset/eighty-teeth-sniff.md +5 -0
- package/repos/effect/.changeset/eleven-apes-share.md +5 -0
- package/repos/effect/.changeset/eleven-numbers-bake.md +5 -0
- package/repos/effect/.changeset/empty-gifts-beg.md +5 -0
- package/repos/effect/.changeset/empty-http-rpc-client.md +5 -0
- package/repos/effect/.changeset/eventlog-unencrypted.md +5 -0
- package/repos/effect/.changeset/expand-schema-filter-output.md +24 -0
- package/repos/effect/.changeset/export-schema-encode-keys-interface.md +7 -0
- package/repos/effect/.changeset/extract-semaphore-latch.md +10 -0
- package/repos/effect/.changeset/fair-bees-relax.md +5 -0
- package/repos/effect/.changeset/fair-buttons-share.md +7 -0
- package/repos/effect/.changeset/fair-cooks-stop.md +5 -0
- package/repos/effect/.changeset/fair-cups-train.md +5 -0
- package/repos/effect/.changeset/fair-dryers-speak.md +5 -0
- package/repos/effect/.changeset/fair-forks-shake.md +5 -0
- package/repos/effect/.changeset/fair-pandas-prove.md +5 -0
- package/repos/effect/.changeset/fair-pants-float.md +5 -0
- package/repos/effect/.changeset/fair-poems-visit.md +5 -0
- package/repos/effect/.changeset/famous-wolves-lead.md +5 -0
- package/repos/effect/.changeset/fancy-glasses-grow.md +5 -0
- package/repos/effect/.changeset/fast-times-camp.md +5 -0
- package/repos/effect/.changeset/few-birds-matter.md +5 -0
- package/repos/effect/.changeset/few-cougars-dig.md +5 -0
- package/repos/effect/.changeset/few-foxes-grin.md +5 -0
- package/repos/effect/.changeset/few-mirrors-pull.md +14 -0
- package/repos/effect/.changeset/few-socks-poke.md +5 -0
- package/repos/effect/.changeset/fiber-runtime-start-metrics.md +5 -0
- package/repos/effect/.changeset/fiery-jokes-care.md +5 -0
- package/repos/effect/.changeset/fiery-mammals-call.md +5 -0
- package/repos/effect/.changeset/fine-walls-decide.md +5 -0
- package/repos/effect/.changeset/first-success-of.md +5 -0
- package/repos/effect/.changeset/five-parents-relax.md +5 -0
- package/repos/effect/.changeset/five-worms-rhyme.md +5 -0
- package/repos/effect/.changeset/fix-1332.md +5 -0
- package/repos/effect/.changeset/fix-1917.md +11 -0
- package/repos/effect/.changeset/fix-1927.md +5 -0
- package/repos/effect/.changeset/fix-1940.md +7 -0
- package/repos/effect/.changeset/fix-1947.md +7 -0
- package/repos/effect/.changeset/fix-2002.md +5 -0
- package/repos/effect/.changeset/fix-2012.md +5 -0
- package/repos/effect/.changeset/fix-2015.md +5 -0
- package/repos/effect/.changeset/fix-2260.md +5 -0
- package/repos/effect/.changeset/fix-2268.md +5 -0
- package/repos/effect/.changeset/fix-2271.md +5 -0
- package/repos/effect/.changeset/fix-2384.md +7 -0
- package/repos/effect/.changeset/fix-ai-empty-params-structured-output.md +5 -0
- package/repos/effect/.changeset/fix-ai-text-toolkit-typing.md +5 -0
- package/repos/effect/.changeset/fix-catch-orelse-error-erasure.md +5 -0
- package/repos/effect/.changeset/fix-class-constructor-defaults.md +5 -0
- package/repos/effect/.changeset/fix-cli-mixed-global-flag-context.md +7 -0
- package/repos/effect/.changeset/fix-config-withDefault.md +5 -0
- package/repos/effect/.changeset/fix-config-withdefault-filter.md +7 -0
- package/repos/effect/.changeset/fix-datetime-gmt.md +5 -0
- package/repos/effect/.changeset/fix-devtools-flush-on-teardown.md +10 -0
- package/repos/effect/.changeset/fix-duration-symmetric-rounding.md +5 -0
- package/repos/effect/.changeset/fix-entity-manager-defect-replay.md +5 -0
- package/repos/effect/.changeset/fix-entity-proxy-rpc-handler-context.md +5 -0
- package/repos/effect/.changeset/fix-entity-proxy-server-path-params.md +5 -0
- package/repos/effect/.changeset/fix-from-readable-stream-cancel-defect.md +5 -0
- package/repos/effect/.changeset/fix-graph-undirected-traversal.md +5 -0
- package/repos/effect/.changeset/fix-has-interrupts-only-empty.md +5 -0
- package/repos/effect/.changeset/fix-hashmap-bit31-ordering.md +5 -0
- package/repos/effect/.changeset/fix-headers-proto-enumerability.md +5 -0
- package/repos/effect/.changeset/fix-http-incoming-message-parse-options.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-endpoint-error-inference.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-schema-types.md +5 -0
- package/repos/effect/.changeset/fix-httpapi-security-middleware-cache.md +5 -0
- package/repos/effect/.changeset/fix-is-json-dag.md +7 -0
- package/repos/effect/.changeset/fix-json-schema-anyof-oneof-siblings.md +5 -0
- package/repos/effect/.changeset/fix-json-schema-import-json.md +5 -0
- package/repos/effect/.changeset/fix-keepalive-blocked-timers.md +5 -0
- package/repos/effect/.changeset/fix-mcp-param-name-resolution.md +5 -0
- package/repos/effect/.changeset/fix-mermaid-escape-special-chars.md +5 -0
- package/repos/effect/.changeset/fix-mutable-list-filter-length.md +5 -0
- package/repos/effect/.changeset/fix-object-keyword-json-schema.md +5 -0
- package/repos/effect/.changeset/fix-openai-mcp-tool-names.md +5 -0
- package/repos/effect/.changeset/fix-openapi-generator-form-urlencoded.md +5 -0
- package/repos/effect/.changeset/fix-openapi-generator-swagger2openapi.md +5 -0
- package/repos/effect/.changeset/fix-openapi-preserve-multiple-response-content-types.md +5 -0
- package/repos/effect/.changeset/fix-openrouter-sparse-array.md +5 -0
- package/repos/effect/.changeset/fix-otel-logger-clock-skew.md +7 -0
- package/repos/effect/.changeset/fix-otel-logger-severity-number.md +20 -0
- package/repos/effect/.changeset/fix-queue-collect-duplication.md +5 -0
- package/repos/effect/.changeset/fix-random-string-seeds.md +5 -0
- package/repos/effect/.changeset/fix-ratelimiter-tokenbucket-redis-ttl.md +5 -0
- package/repos/effect/.changeset/fix-remainder-scientific-notation.md +5 -0
- package/repos/effect/.changeset/fix-request-resolver-pending-batches-leak.md +5 -0
- package/repos/effect/.changeset/fix-retry-transient-autocomplete.md +5 -0
- package/repos/effect/.changeset/fix-rpc-http-requestids-finalizer.md +5 -0
- package/repos/effect/.changeset/fix-rpc-json-id-edges.md +5 -0
- package/repos/effect/.changeset/fix-schedule-fixed-double-exec.md +9 -0
- package/repos/effect/.changeset/fix-schedule-reduce-sync-state.md +5 -0
- package/repos/effect/.changeset/fix-schema-arbitrary-exclusive-bounds.md +5 -0
- package/repos/effect/.changeset/fix-schema-defect-message.md +5 -0
- package/repos/effect/.changeset/fix-schema-encode-keys-property-keys.md +5 -0
- package/repos/effect/.changeset/fix-schema-encodekeys-class.md +5 -0
- package/repos/effect/.changeset/fix-schema-encodekeys-struct.md +5 -0
- package/repos/effect/.changeset/fix-schema-identifier-expected-message.md +5 -0
- package/repos/effect/.changeset/fix-schema-is-uuid.md +5 -0
- package/repos/effect/.changeset/fix-schema-option-non-schema-failures.md +17 -0
- package/repos/effect/.changeset/fix-schema-parser-checks.md +9 -0
- package/repos/effect/.changeset/fix-searchparam-initial-decode.md +5 -0
- package/repos/effect/.changeset/fix-serializable-wire-transfer.md +7 -0
- package/repos/effect/.changeset/fix-stream-grouped-within-flush.md +5 -0
- package/repos/effect/.changeset/fix-stream-run-for-each-while.md +5 -0
- package/repos/effect/.changeset/fix-stream-scan-effect.md +5 -0
- package/repos/effect/.changeset/fix-stream-scoped-scope.md +5 -0
- package/repos/effect/.changeset/fix-strip-approval-artifacts-multi-round.md +13 -0
- package/repos/effect/.changeset/fix-struct-utility-types-simplify.md +5 -0
- package/repos/effect/.changeset/fix-structwithrest-index-signatures.md +6 -0
- package/repos/effect/.changeset/fix-tagged-union-class-sentinels.md +5 -0
- package/repos/effect/.changeset/fix-tagged-union-match-unify.md +6 -0
- package/repos/effect/.changeset/fix-to-tagged-union-isanyof-custom-tags.md +10 -0
- package/repos/effect/.changeset/fix-tuple-with-rest-post-rest-index-drift.md +5 -0
- package/repos/effect/.changeset/fix-tuple-with-rest-post-rest-validation.md +5 -0
- package/repos/effect/.changeset/fix-types-voidifempty.md +5 -0
- package/repos/effect/.changeset/fix-void-response-encoding.md +5 -0
- package/repos/effect/.changeset/fix-workflow-proxy-rpc-handler-context.md +5 -0
- package/repos/effect/.changeset/flat-chicken-remain.md +5 -0
- package/repos/effect/.changeset/floppy-cows-spend.md +5 -0
- package/repos/effect/.changeset/floppy-items-admire.md +5 -0
- package/repos/effect/.changeset/floppy-pigs-kiss.md +5 -0
- package/repos/effect/.changeset/fluffy-meals-matter.md +5 -0
- package/repos/effect/.changeset/fluffy-pumas-push.md +5 -0
- package/repos/effect/.changeset/forked-memo-maps.md +6 -0
- package/repos/effect/.changeset/forty-hounds-cheer.md +5 -0
- package/repos/effect/.changeset/forty-otters-cry.md +5 -0
- package/repos/effect/.changeset/forty-rings-film.md +7 -0
- package/repos/effect/.changeset/forty-signs-stay.md +5 -0
- package/repos/effect/.changeset/forty-swans-divide.md +5 -0
- package/repos/effect/.changeset/forty-trees-pay.md +5 -0
- package/repos/effect/.changeset/four-papayas-bow.md +5 -0
- package/repos/effect/.changeset/four-points-repeat.md +5 -0
- package/repos/effect/.changeset/fresh-cats-smash.md +5 -0
- package/repos/effect/.changeset/fresh-emus-cheat.md +5 -0
- package/repos/effect/.changeset/fresh-monkeys-smoke.md +9 -0
- package/repos/effect/.changeset/fruity-houses-learn.md +6 -0
- package/repos/effect/.changeset/full-adults-double.md +5 -0
- package/repos/effect/.changeset/funny-crabs-hang.md +6 -0
- package/repos/effect/.changeset/funny-forks-move.md +5 -0
- package/repos/effect/.changeset/fuzzy-camels-hunt.md +5 -0
- package/repos/effect/.changeset/fuzzy-dodos-help.md +5 -0
- package/repos/effect/.changeset/fuzzy-lions-perform.md +5 -0
- package/repos/effect/.changeset/fuzzy-planets-sneeze.md +5 -0
- package/repos/effect/.changeset/gold-meteors-move.md +5 -0
- package/repos/effect/.changeset/gold-readers-hug.md +5 -0
- package/repos/effect/.changeset/gold-rings-start.md +5 -0
- package/repos/effect/.changeset/good-tools-work.md +7 -0
- package/repos/effect/.changeset/graph-algorithm-fixes.md +5 -0
- package/repos/effect/.changeset/great-trains-mate.md +5 -0
- package/repos/effect/.changeset/great-trams-report.md +5 -0
- package/repos/effect/.changeset/green-beds-unref.md +7 -0
- package/repos/effect/.changeset/green-chips-wash.md +5 -0
- package/repos/effect/.changeset/green-moons-smile.md +5 -0
- package/repos/effect/.changeset/green-pugs-play.md +5 -0
- package/repos/effect/.changeset/green-rings-prove.md +5 -0
- package/repos/effect/.changeset/happy-mirrors-dream.md +5 -0
- package/repos/effect/.changeset/heavy-loops-cut.md +5 -0
- package/repos/effect/.changeset/heavy-trams-fix.md +5 -0
- package/repos/effect/.changeset/hip-socks-travel.md +5 -0
- package/repos/effect/.changeset/honest-pens-thank.md +5 -0
- package/repos/effect/.changeset/honest-rivers-notice.md +5 -0
- package/repos/effect/.changeset/hot-taxis-fry.md +5 -0
- package/repos/effect/.changeset/httpapi-endpoint-relax-constraints.md +5 -0
- package/repos/effect/.changeset/httpapi-schema-service-types.md +6 -0
- package/repos/effect/.changeset/huge-moons-rhyme.md +5 -0
- package/repos/effect/.changeset/humble-pigs-dig.md +5 -0
- package/repos/effect/.changeset/icy-flies-cross.md +5 -0
- package/repos/effect/.changeset/itchy-radios-poke.md +5 -0
- package/repos/effect/.changeset/itchy-results-bet.md +5 -0
- package/repos/effect/.changeset/itchy-shrimps-deny.md +5 -0
- package/repos/effect/.changeset/itchy-toes-promise.md +5 -0
- package/repos/effect/.changeset/k8s-last-transition-null.md +5 -0
- package/repos/effect/.changeset/khaki-cats-learn.md +5 -0
- package/repos/effect/.changeset/khaki-melons-appear.md +5 -0
- package/repos/effect/.changeset/kind-hounds-float.md +5 -0
- package/repos/effect/.changeset/kind-windows-fall.md +5 -0
- package/repos/effect/.changeset/late-hotels-rule.md +5 -0
- package/repos/effect/.changeset/late-lamps-care.md +5 -0
- package/repos/effect/.changeset/late-rivers-applaud.md +5 -0
- package/repos/effect/.changeset/layer-map-dynamic-idle-ttl.md +5 -0
- package/repos/effect/.changeset/lazy-queens-rush.md +5 -0
- package/repos/effect/.changeset/lazy-recursive-forward-refs.md +5 -0
- package/repos/effect/.changeset/lazy-timers-exist.md +5 -0
- package/repos/effect/.changeset/legal-pants-drop.md +5 -0
- package/repos/effect/.changeset/lemon-taxis-sin.md +5 -0
- package/repos/effect/.changeset/light-kids-sneeze.md +5 -0
- package/repos/effect/.changeset/little-dryers-allow.md +7 -0
- package/repos/effect/.changeset/long-cameras-think.md +5 -0
- package/repos/effect/.changeset/lovely-cobras-change.md +5 -0
- package/repos/effect/.changeset/lovely-frogs-rescue.md +5 -0
- package/repos/effect/.changeset/lucky-buttons-jump.md +5 -0
- package/repos/effect/.changeset/lucky-phones-listen.md +5 -0
- package/repos/effect/.changeset/lucky-worms-type.md +5 -0
- package/repos/effect/.changeset/mean-dingos-share.md +5 -0
- package/repos/effect/.changeset/mean-trains-smash.md +5 -0
- package/repos/effect/.changeset/metal-parts-yell.md +5 -0
- package/repos/effect/.changeset/mighty-games-matter.md +5 -0
- package/repos/effect/.changeset/modern-uuid-guid-filter.md +5 -0
- package/repos/effect/.changeset/nasty-geese-grow.md +5 -0
- package/repos/effect/.changeset/neat-goats-wave.md +5 -0
- package/repos/effect/.changeset/neat-kings-chew.md +5 -0
- package/repos/effect/.changeset/neat-lions-rest.md +5 -0
- package/repos/effect/.changeset/neat-snails-wash.md +5 -0
- package/repos/effect/.changeset/neat-taxis-notice.md +5 -0
- package/repos/effect/.changeset/new-dogs-swim.md +5 -0
- package/repos/effect/.changeset/new-toes-stop.md +5 -0
- package/repos/effect/.changeset/ninety-geese-exist.md +5 -0
- package/repos/effect/.changeset/odd-boats-think.md +5 -0
- package/repos/effect/.changeset/odd-bulldogs-sleep.md +5 -0
- package/repos/effect/.changeset/odd-fans-glow.md +5 -0
- package/repos/effect/.changeset/odd-forks-talk.md +5 -0
- package/repos/effect/.changeset/odd-laws-draw.md +5 -0
- package/repos/effect/.changeset/odd-owls-smoke.md +5 -0
- package/repos/effect/.changeset/odd-socks-boil.md +5 -0
- package/repos/effect/.changeset/odd-suns-dance.md +5 -0
- package/repos/effect/.changeset/old-brooms-cry.md +5 -0
- package/repos/effect/.changeset/old-facts-stand.md +5 -0
- package/repos/effect/.changeset/old-mirrors-float.md +5 -0
- package/repos/effect/.changeset/olive-poems-visit.md +5 -0
- package/repos/effect/.changeset/open-hotels-remain.md +5 -0
- package/repos/effect/.changeset/openai-compat-nullable-tool-name.md +7 -0
- package/repos/effect/.changeset/openai-compat-reasoning.md +5 -0
- package/repos/effect/.changeset/otel-resource-env-precedence.md +5 -0
- package/repos/effect/.changeset/perfect-buckets-tickle.md +5 -0
- package/repos/effect/.changeset/petite-months-allow.md +6 -0
- package/repos/effect/.changeset/platform-crypto-service.md +9 -0
- package/repos/effect/.changeset/platform-node-shared-barrel.md +5 -0
- package/repos/effect/.changeset/plenty-moons-pull.md +5 -0
- package/repos/effect/.changeset/polite-brooms-tickle.md +5 -0
- package/repos/effect/.changeset/polite-pigs-speak.md +5 -0
- package/repos/effect/.changeset/polite-tables-kneel.md +5 -0
- package/repos/effect/.changeset/port-react-hydration.md +8 -0
- package/repos/effect/.changeset/pre.json +588 -0
- package/repos/effect/.changeset/public-deer-ring.md +5 -0
- package/repos/effect/.changeset/public-jeans-stop.md +5 -0
- package/repos/effect/.changeset/pubsub-publish-false.md +5 -0
- package/repos/effect/.changeset/puny-pens-clap.md +6 -0
- package/repos/effect/.changeset/purple-bars-prove.md +5 -0
- package/repos/effect/.changeset/purple-schools-float.md +5 -0
- package/repos/effect/.changeset/purple-turtles-draw.md +5 -0
- package/repos/effect/.changeset/quick-dragons-fix.md +5 -0
- package/repos/effect/.changeset/quick-falcons-travel.md +5 -0
- package/repos/effect/.changeset/quick-geese-relax.md +5 -0
- package/repos/effect/.changeset/quick-lamps-dig.md +5 -0
- package/repos/effect/.changeset/quick-lizards-fall.md +5 -0
- package/repos/effect/.changeset/quick-trees-join.md +5 -0
- package/repos/effect/.changeset/quiet-carpets-grin.md +5 -0
- package/repos/effect/.changeset/quiet-files-hunt.md +5 -0
- package/repos/effect/.changeset/quiet-lamps-jam.md +5 -0
- package/repos/effect/.changeset/quiet-radios-wave.md +5 -0
- package/repos/effect/.changeset/quiet-redis-scripts.md +5 -0
- package/repos/effect/.changeset/ready-olives-divide.md +5 -0
- package/repos/effect/.changeset/real-trains-ring.md +5 -0
- package/repos/effect/.changeset/red-pigs-repair.md +5 -0
- package/repos/effect/.changeset/redacted-representation-options.md +7 -0
- package/repos/effect/.changeset/refactor-cli-global-flags.md +27 -0
- package/repos/effect/.changeset/refactor-config-provider.md +23 -0
- package/repos/effect/.changeset/refactor-representation-references.md +5 -0
- package/repos/effect/.changeset/remove-effect-transactionwith.md +5 -0
- package/repos/effect/.changeset/remove-http-span-counter.md +5 -0
- package/repos/effect/.changeset/remove-nullor.md +5 -0
- package/repos/effect/.changeset/remove-openapi-fromapi-options.md +7 -0
- package/repos/effect/.changeset/remove-types-mergerecord.md +5 -0
- package/repos/effect/.changeset/remove-unused-utils-apis.md +5 -0
- package/repos/effect/.changeset/rename-rebuild-out.md +5 -0
- package/repos/effect/.changeset/restore-schema-parse-options.md +5 -0
- package/repos/effect/.changeset/rich-dots-push.md +5 -0
- package/repos/effect/.changeset/rich-hoops-nail.md +5 -0
- package/repos/effect/.changeset/rich-sloths-draw.md +5 -0
- package/repos/effect/.changeset/ripe-lies-battle.md +5 -0
- package/repos/effect/.changeset/rpc-middleware-provides-fix.md +5 -0
- package/repos/effect/.changeset/scalar-custom-fetch.md +5 -0
- package/repos/effect/.changeset/schema-as-class.md +17 -0
- package/repos/effect/.changeset/schema-asserts-signature.md +5 -0
- package/repos/effect/.changeset/schema-clean-up-additionalProperties.md +7 -0
- package/repos/effect/.changeset/schema-datetime-utc-from-string.md +5 -0
- package/repos/effect/.changeset/schema-decoding-defaults-services.md +7 -0
- package/repos/effect/.changeset/schema-defaults-issue-channel.md +7 -0
- package/repos/effect/.changeset/schema-dollar-prefix.md +5 -0
- package/repos/effect/.changeset/schema-missing-self-generic.md +5 -0
- package/repos/effect/.changeset/schema-ordered-arbitrary-constraints.md +12 -0
- package/repos/effect/.changeset/schema-parser-adapter-errors.md +5 -0
- package/repos/effect/.changeset/schema-refactor-toCodecJson.md +5 -0
- package/repos/effect/.changeset/schema-remove-annotate-in.md +5 -0
- package/repos/effect/.changeset/schema-rename-makeUnsafe-to-make.md +7 -0
- package/repos/effect/.changeset/schema-rename-parser-makeUnsafe.md +5 -0
- package/repos/effect/.changeset/schema-result-combinators.md +5 -0
- package/repos/effect/.changeset/schema-struct-simplify.md +5 -0
- package/repos/effect/.changeset/seven-mugs-marry.md +5 -0
- package/repos/effect/.changeset/shaggy-birds-stay.md +5 -0
- package/repos/effect/.changeset/shaggy-cities-push.md +5 -0
- package/repos/effect/.changeset/shaggy-numbers-accept.md +5 -0
- package/repos/effect/.changeset/sharp-emus-applaud.md +5 -0
- package/repos/effect/.changeset/sharp-goats-wink.md +5 -0
- package/repos/effect/.changeset/sharp-pandas-care.md +5 -0
- package/repos/effect/.changeset/sharp-peas-march.md +5 -0
- package/repos/effect/.changeset/sharp-rules-draw.md +5 -0
- package/repos/effect/.changeset/sharp-singers-sort.md +5 -0
- package/repos/effect/.changeset/shiny-trains-hug.md +5 -0
- package/repos/effect/.changeset/short-cows-relate.md +5 -0
- package/repos/effect/.changeset/short-foxes-admire.md +5 -0
- package/repos/effect/.changeset/shy-cycles-flow.md +5 -0
- package/repos/effect/.changeset/shy-geckos-sniff.md +30 -0
- package/repos/effect/.changeset/silent-geckos-matter.md +5 -0
- package/repos/effect/.changeset/silent-needles-design.md +6 -0
- package/repos/effect/.changeset/silent-plants-matter.md +8 -0
- package/repos/effect/.changeset/silent-spoons-stare.md +5 -0
- package/repos/effect/.changeset/silly-loops-tickle.md +5 -0
- package/repos/effect/.changeset/silver-bulk-indexeddb.md +5 -0
- package/repos/effect/.changeset/silver-emus-smoke.md +5 -0
- package/repos/effect/.changeset/silver-kings-poke.md +5 -0
- package/repos/effect/.changeset/silver-snails-sqlite.md +17 -0
- package/repos/effect/.changeset/silver-wings-watch.md +5 -0
- package/repos/effect/.changeset/six-cups-taste.md +5 -0
- package/repos/effect/.changeset/sixty-mails-shout.md +5 -0
- package/repos/effect/.changeset/sixty-socks-yell.md +5 -0
- package/repos/effect/.changeset/slimy-planets-divide.md +5 -0
- package/repos/effect/.changeset/slimy-turtles-juggle.md +5 -0
- package/repos/effect/.changeset/slow-beans-battle.md +28 -0
- package/repos/effect/.changeset/slow-berries-enjoy.md +5 -0
- package/repos/effect/.changeset/small-bugs-hunt.md +5 -0
- package/repos/effect/.changeset/small-crabs-care.md +9 -0
- package/repos/effect/.changeset/small-pets-sit.md +6 -0
- package/repos/effect/.changeset/smart-ducks-jump.md +6 -0
- package/repos/effect/.changeset/smart-pillows-buy.md +6 -0
- package/repos/effect/.changeset/smart-timers-fly.md +5 -0
- package/repos/effect/.changeset/smart-tips-sort.md +5 -0
- package/repos/effect/.changeset/social-pumas-prove.md +5 -0
- package/repos/effect/.changeset/soft-comics-wink.md +5 -0
- package/repos/effect/.changeset/soft-delete-sqlmodel.md +5 -0
- package/repos/effect/.changeset/soft-seals-allow.md +5 -0
- package/repos/effect/.changeset/solid-cougars-attack.md +5 -0
- package/repos/effect/.changeset/solid-doors-ring.md +5 -0
- package/repos/effect/.changeset/solid-items-tease.md +5 -0
- package/repos/effect/.changeset/solid-towns-smoke.md +5 -0
- package/repos/effect/.changeset/sour-canyons-rescue.md +5 -0
- package/repos/effect/.changeset/sparkly-bears-act.md +5 -0
- package/repos/effect/.changeset/sparkly-coins-sit.md +5 -0
- package/repos/effect/.changeset/spotty-comics-fry.md +5 -0
- package/repos/effect/.changeset/sql-migrator-mjs-mts.md +5 -0
- package/repos/effect/.changeset/stale-dots-tell.md +5 -0
- package/repos/effect/.changeset/stale-snakes-know.md +5 -0
- package/repos/effect/.changeset/strict-areas-end.md +5 -0
- package/repos/effect/.changeset/strict-buckets-hug.md +8 -0
- package/repos/effect/.changeset/strip-resolved-approvals.md +5 -0
- package/repos/effect/.changeset/strong-balloons-tickle.md +5 -0
- package/repos/effect/.changeset/strong-bees-queue.md +5 -0
- package/repos/effect/.changeset/struct-record.md +5 -0
- package/repos/effect/.changeset/sunny-ads-hang.md +5 -0
- package/repos/effect/.changeset/sunny-bikes-sleep.md +5 -0
- package/repos/effect/.changeset/sunny-rooms-invent.md +5 -0
- package/repos/effect/.changeset/sweet-donuts-bet.md +5 -0
- package/repos/effect/.changeset/sweet-hotels-give.md +5 -0
- package/repos/effect/.changeset/sweet-views-learn.md +5 -0
- package/repos/effect/.changeset/swift-spiders-unpack.md +5 -0
- package/repos/effect/.changeset/swift-symbols-stand.md +5 -0
- package/repos/effect/.changeset/tagged-error-class-optional-empty-props.md +5 -0
- package/repos/effect/.changeset/tall-hairs-return.md +5 -0
- package/repos/effect/.changeset/tall-mails-listen.md +5 -0
- package/repos/effect/.changeset/tall-queens-cheer.md +5 -0
- package/repos/effect/.changeset/tall-wombats-wave.md +5 -0
- package/repos/effect/.changeset/tangy-colts-lose.md +5 -0
- package/repos/effect/.changeset/tasty-comics-send.md +5 -0
- package/repos/effect/.changeset/ten-kings-fry.md +5 -0
- package/repos/effect/.changeset/thick-pandas-wait.md +5 -0
- package/repos/effect/.changeset/thin-ducks-wonder.md +5 -0
- package/repos/effect/.changeset/thirty-ducks-go.md +5 -0
- package/repos/effect/.changeset/thirty-pans-love.md +5 -0
- package/repos/effect/.changeset/three-corners-sort.md +5 -0
- package/repos/effect/.changeset/three-ravens-jam.md +5 -0
- package/repos/effect/.changeset/three-tomatoes-wave.md +5 -0
- package/repos/effect/.changeset/tidy-foxes-own.md +5 -0
- package/repos/effect/.changeset/tidy-icons-glow.md +5 -0
- package/repos/effect/.changeset/tidy-stacks-encode.md +5 -0
- package/repos/effect/.changeset/tidy-stars-drive.md +5 -0
- package/repos/effect/.changeset/tiny-buckets-wave.md +5 -0
- package/repos/effect/.changeset/tiny-lilies-flash.md +5 -0
- package/repos/effect/.changeset/tiny-rabbits-smile.md +5 -0
- package/repos/effect/.changeset/tocodecjson-return-json-type.md +10 -0
- package/repos/effect/.changeset/tool-get-json-schema-tests.md +5 -0
- package/repos/effect/.changeset/true-actors-battle.md +5 -0
- package/repos/effect/.changeset/twenty-buttons-cheer.md +5 -0
- package/repos/effect/.changeset/two-roses-double.md +5 -0
- package/repos/effect/.changeset/unify-error-defect-stack-options.md +23 -0
- package/repos/effect/.changeset/update-schema-arbitrary-report.md +22 -0
- package/repos/effect/.changeset/upset-colts-stick.md +5 -0
- package/repos/effect/.changeset/vast-bananas-send.md +5 -0
- package/repos/effect/.changeset/vast-deserts-travel.md +5 -0
- package/repos/effect/.changeset/violet-peaches-feel.md +5 -0
- package/repos/effect/.changeset/vitest-layer-top-level-options.md +5 -0
- package/repos/effect/.changeset/wacky-grapes-poke.md +5 -0
- package/repos/effect/.changeset/wacky-rice-add.md +5 -0
- package/repos/effect/.changeset/warm-dolls-brake.md +5 -0
- package/repos/effect/.changeset/warm-friends-tie.md +5 -0
- package/repos/effect/.changeset/warm-snails-shop.md +7 -0
- package/repos/effect/.changeset/wet-news-invent.md +5 -0
- package/repos/effect/.changeset/wild-readers-clean.md +5 -0
- package/repos/effect/.changeset/wild-suns-bearer-space.md +5 -0
- package/repos/effect/.changeset/wise-ants-wave.md +6 -0
- package/repos/effect/.changeset/wise-flags-shift.md +22 -0
- package/repos/effect/.changeset/wise-oranges-stay.md +5 -0
- package/repos/effect/.changeset/witty-lobsters-share.md +5 -0
- package/repos/effect/.changeset/yellow-adults-study.md +5 -0
- package/repos/effect/.changeset/yellow-clocks-dance.md +5 -0
- package/repos/effect/.changeset/yellow-dingos-jump.md +5 -0
- package/repos/effect/.changeset/young-doors-change.md +5 -0
- package/repos/effect/.envrc +1 -0
- package/repos/effect/.github/actions/setup/action.yaml +33 -0
- package/repos/effect/.github/workflows/ai-codegen.yml +66 -0
- package/repos/effect/.github/workflows/bundle-comment.yml +72 -0
- package/repos/effect/.github/workflows/check.yml +195 -0
- package/repos/effect/.github/workflows/release.yml +47 -0
- package/repos/effect/.github/workflows/snapshot.yml +34 -0
- package/repos/effect/.oxlintrc.json +25 -0
- package/repos/effect/.patterns/effect.md +102 -0
- package/repos/effect/.patterns/jsdoc.md +53 -0
- package/repos/effect/.patterns/testing.md +44 -0
- package/repos/effect/.specs/README.md +2 -0
- package/repos/effect/.vscode/extensions.json +6 -0
- package/repos/effect/.vscode/settings.json +44 -0
- package/repos/effect/AGENTS.md +139 -0
- package/repos/effect/LICENSE +21 -0
- package/repos/effect/LLMS.md +343 -0
- package/repos/effect/MIGRATION.md +83 -0
- package/repos/effect/README.md +3 -0
- package/repos/effect/TODOS.md +28 -0
- package/repos/effect/ai-docs/README.md +44 -0
- package/repos/effect/ai-docs/package.json +36 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +39 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
- package/repos/effect/ai-docs/src/01_effect/01_basics/index.md +5 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/01_service.ts +45 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/10_reference.ts +10 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/20_layer-composition.ts +70 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/20_layer-unwrap.ts +66 -0
- package/repos/effect/ai-docs/src/01_effect/02_services/index.md +5 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/01_error-handling.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/10_catch-tags.ts +24 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/20_reason-errors.ts +64 -0
- package/repos/effect/ai-docs/src/01_effect/03_errors/index.md +1 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/10_acquire-release.ts +105 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/20_layer-side-effects.ts +31 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/30_layer-map.ts +86 -0
- package/repos/effect/ai-docs/src/01_effect/04_resources/index.md +3 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/10_run-main.ts +30 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/20_layer-launch.ts +27 -0
- package/repos/effect/ai-docs/src/01_effect/05_running/index.md +1 -0
- package/repos/effect/ai-docs/src/01_effect/06_pubsub/10_pubsub.ts +56 -0
- package/repos/effect/ai-docs/src/01_effect/06_pubsub/index.md +3 -0
- package/repos/effect/ai-docs/src/02_stream/10_creating-streams.ts +103 -0
- package/repos/effect/ai-docs/src/02_stream/20_consuming-streams.ts +137 -0
- package/repos/effect/ai-docs/src/02_stream/30_encoding.ts +165 -0
- package/repos/effect/ai-docs/src/02_stream/index.md +4 -0
- package/repos/effect/ai-docs/src/03_integration/10_managed-runtime.ts +129 -0
- package/repos/effect/ai-docs/src/03_integration/index.md +5 -0
- package/repos/effect/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
- package/repos/effect/ai-docs/src/05_batching/index.md +3 -0
- package/repos/effect/ai-docs/src/06_schedule/10_schedules.ts +102 -0
- package/repos/effect/ai-docs/src/06_schedule/index.md +3 -0
- package/repos/effect/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
- package/repos/effect/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
- package/repos/effect/ai-docs/src/07_datetime/index.md +5 -0
- package/repos/effect/ai-docs/src/08_observability/10_logging.ts +66 -0
- package/repos/effect/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
- package/repos/effect/ai-docs/src/08_observability/index.md +7 -0
- package/repos/effect/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
- package/repos/effect/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
- package/repos/effect/ai-docs/src/09_testing/index.md +1 -0
- package/repos/effect/ai-docs/src/50_http-client/10_basics.ts +102 -0
- package/repos/effect/ai-docs/src/50_http-client/index.md +3 -0
- package/repos/effect/ai-docs/src/51_http-server/10_basics.ts +116 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/api/Users.ts +91 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/domain/User.ts +12 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +36 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +71 -0
- package/repos/effect/ai-docs/src/51_http-server/fixtures/server/Users.ts +62 -0
- package/repos/effect/ai-docs/src/51_http-server/index.md +3 -0
- package/repos/effect/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
- package/repos/effect/ai-docs/src/60_child-process/index.md +3 -0
- package/repos/effect/ai-docs/src/70_cli/10_basics.ts +136 -0
- package/repos/effect/ai-docs/src/70_cli/index.md +5 -0
- package/repos/effect/ai-docs/src/71_ai/10_language-model.ts +156 -0
- package/repos/effect/ai-docs/src/71_ai/20_tools.ts +226 -0
- package/repos/effect/ai-docs/src/71_ai/30_chat.ts +158 -0
- package/repos/effect/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
- package/repos/effect/ai-docs/src/71_ai/index.md +5 -0
- package/repos/effect/ai-docs/src/80_cluster/10_entities.ts +97 -0
- package/repos/effect/ai-docs/src/80_cluster/index.md +4 -0
- package/repos/effect/ai-docs/src/index.md +12 -0
- package/repos/effect/ai-docs/tsconfig.json +24 -0
- package/repos/effect/cookbooks/schedule.md +3507 -0
- package/repos/effect/deno.json +33 -0
- package/repos/effect/docker-compose.yaml +18 -0
- package/repos/effect/dprint.json +32 -0
- package/repos/effect/flake.lock +27 -0
- package/repos/effect/flake.nix +24 -0
- package/repos/effect/jsdocs.config.json +16 -0
- package/repos/effect/migration/cause.md +163 -0
- package/repos/effect/migration/equality.md +72 -0
- package/repos/effect/migration/error-handling.md +106 -0
- package/repos/effect/migration/fiber-keep-alive.md +74 -0
- package/repos/effect/migration/fiberref.md +109 -0
- package/repos/effect/migration/forking.md +94 -0
- package/repos/effect/migration/generators.md +32 -0
- package/repos/effect/migration/layer-memoization.md +98 -0
- package/repos/effect/migration/runtime.md +88 -0
- package/repos/effect/migration/schema.md +1032 -0
- package/repos/effect/migration/scope.md +50 -0
- package/repos/effect/migration/services.md +235 -0
- package/repos/effect/migration/v3-to-v4.md +421 -0
- package/repos/effect/migration/yieldable.md +173 -0
- package/repos/effect/package.json +104 -0
- package/repos/effect/packages/ai/anthropic/CHANGELOG.md +611 -0
- package/repos/effect/packages/ai/anthropic/codegen.yml +63 -0
- package/repos/effect/packages/ai/anthropic/docgen.json +26 -0
- package/repos/effect/packages/ai/anthropic/package.json +67 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicClient.ts +432 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicConfig.ts +84 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicError.ts +212 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts +3098 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicTelemetry.ts +132 -0
- package/repos/effect/packages/ai/anthropic/src/AnthropicTool.ts +2512 -0
- package/repos/effect/packages/ai/anthropic/src/Generated.ts +12600 -0
- package/repos/effect/packages/ai/anthropic/src/index.ts +40 -0
- package/repos/effect/packages/ai/anthropic/src/internal/errors.ts +370 -0
- package/repos/effect/packages/ai/anthropic/src/internal/utilities.ts +26 -0
- package/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts +300 -0
- package/repos/effect/packages/ai/anthropic/tsconfig.json +8 -0
- package/repos/effect/packages/ai/anthropic/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openai/CHANGELOG.md +668 -0
- package/repos/effect/packages/ai/openai/codegen.yaml +41 -0
- package/repos/effect/packages/ai/openai/docgen.json +24 -0
- package/repos/effect/packages/ai/openai/package.json +67 -0
- package/repos/effect/packages/ai/openai/src/Generated.ts +35774 -0
- package/repos/effect/packages/ai/openai/src/OpenAiClient.ts +730 -0
- package/repos/effect/packages/ai/openai/src/OpenAiClientGenerated.ts +202 -0
- package/repos/effect/packages/ai/openai/src/OpenAiConfig.ts +93 -0
- package/repos/effect/packages/ai/openai/src/OpenAiEmbeddingModel.ts +258 -0
- package/repos/effect/packages/ai/openai/src/OpenAiError.ts +242 -0
- package/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts +3133 -0
- package/repos/effect/packages/ai/openai/src/OpenAiSchema.ts +1286 -0
- package/repos/effect/packages/ai/openai/src/OpenAiTelemetry.ts +162 -0
- package/repos/effect/packages/ai/openai/src/OpenAiTool.ts +342 -0
- package/repos/effect/packages/ai/openai/src/index.ts +55 -0
- package/repos/effect/packages/ai/openai/src/internal/errors.ts +349 -0
- package/repos/effect/packages/ai/openai/src/internal/utilities.ts +33 -0
- package/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts +798 -0
- package/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts +289 -0
- package/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts +1528 -0
- package/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts +273 -0
- package/repos/effect/packages/ai/openai/tsconfig.json +8 -0
- package/repos/effect/packages/ai/openai/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openai-compat/CHANGELOG.md +626 -0
- package/repos/effect/packages/ai/openai-compat/docgen.json +24 -0
- package/repos/effect/packages/ai/openai-compat/package.json +69 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts +1221 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiConfig.ts +87 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiEmbeddingModel.ts +254 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts +178 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts +1951 -0
- package/repos/effect/packages/ai/openai-compat/src/OpenAiTelemetry.ts +164 -0
- package/repos/effect/packages/ai/openai-compat/src/index.ts +35 -0
- package/repos/effect/packages/ai/openai-compat/src/internal/errors.ts +327 -0
- package/repos/effect/packages/ai/openai-compat/src/internal/utilities.ts +33 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts +474 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiEmbeddingModel.test.ts +216 -0
- package/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts +1505 -0
- package/repos/effect/packages/ai/openai-compat/tsconfig.json +8 -0
- package/repos/effect/packages/ai/openai-compat/vitest.config.ts +6 -0
- package/repos/effect/packages/ai/openrouter/CHANGELOG.md +607 -0
- package/repos/effect/packages/ai/openrouter/codegen.yml +35 -0
- package/repos/effect/packages/ai/openrouter/docgen.json +24 -0
- package/repos/effect/packages/ai/openrouter/package.json +67 -0
- package/repos/effect/packages/ai/openrouter/src/Generated.ts +10028 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterClient.ts +357 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterConfig.ts +99 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterError.ts +225 -0
- package/repos/effect/packages/ai/openrouter/src/OpenRouterLanguageModel.ts +1796 -0
- package/repos/effect/packages/ai/openrouter/src/index.ts +30 -0
- package/repos/effect/packages/ai/openrouter/src/internal/errors.ts +375 -0
- package/repos/effect/packages/ai/openrouter/src/internal/utilities.ts +92 -0
- package/repos/effect/packages/ai/openrouter/tsconfig.json +10 -0
- package/repos/effect/packages/ai/openrouter/vitest.config.ts +6 -0
- package/repos/effect/packages/atom/react/CHANGELOG.md +599 -0
- package/repos/effect/packages/atom/react/LICENSE +21 -0
- package/repos/effect/packages/atom/react/README.md +7 -0
- package/repos/effect/packages/atom/react/docgen.json +25 -0
- package/repos/effect/packages/atom/react/package.json +79 -0
- package/repos/effect/packages/atom/react/src/Hooks.ts +476 -0
- package/repos/effect/packages/atom/react/src/ReactHydration.ts +109 -0
- package/repos/effect/packages/atom/react/src/RegistryContext.ts +108 -0
- package/repos/effect/packages/atom/react/src/ScopedAtom.ts +151 -0
- package/repos/effect/packages/atom/react/src/index.ts +23 -0
- package/repos/effect/packages/atom/react/test/index.test.tsx +650 -0
- package/repos/effect/packages/atom/react/tsconfig.json +8 -0
- package/repos/effect/packages/atom/react/vitest.config.ts +9 -0
- package/repos/effect/packages/atom/react/vitest.setup.ts +8 -0
- package/repos/effect/packages/atom/solid/CHANGELOG.md +595 -0
- package/repos/effect/packages/atom/solid/LICENSE +21 -0
- package/repos/effect/packages/atom/solid/README.md +7 -0
- package/repos/effect/packages/atom/solid/docgen.json +26 -0
- package/repos/effect/packages/atom/solid/package.json +72 -0
- package/repos/effect/packages/atom/solid/src/Hooks.ts +359 -0
- package/repos/effect/packages/atom/solid/src/RegistryContext.ts +80 -0
- package/repos/effect/packages/atom/solid/src/index.ts +13 -0
- package/repos/effect/packages/atom/solid/test/index.test.tsx +296 -0
- package/repos/effect/packages/atom/solid/tsconfig.json +8 -0
- package/repos/effect/packages/atom/solid/vitest.config.ts +15 -0
- package/repos/effect/packages/atom/solid/vitest.setup.ts +8 -0
- package/repos/effect/packages/atom/vue/CHANGELOG.md +593 -0
- package/repos/effect/packages/atom/vue/LICENSE +21 -0
- package/repos/effect/packages/atom/vue/README.md +7 -0
- package/repos/effect/packages/atom/vue/docgen.json +24 -0
- package/repos/effect/packages/atom/vue/package.json +68 -0
- package/repos/effect/packages/atom/vue/src/index.ts +211 -0
- package/repos/effect/packages/atom/vue/test/index.test.ts +5 -0
- package/repos/effect/packages/atom/vue/tsconfig.json +14 -0
- package/repos/effect/packages/atom/vue/vitest.config.ts +8 -0
- package/repos/effect/packages/effect/CHANGELOG.md +1607 -0
- package/repos/effect/packages/effect/CONFIG.md +690 -0
- package/repos/effect/packages/effect/HTTPAPI.md +3213 -0
- package/repos/effect/packages/effect/LICENSE +21 -0
- package/repos/effect/packages/effect/MCP.md +369 -0
- package/repos/effect/packages/effect/OPTIC.md +620 -0
- package/repos/effect/packages/effect/README.md +53 -0
- package/repos/effect/packages/effect/SCHEMA.md +7284 -0
- package/repos/effect/packages/effect/benchmark/schema/Enums.ts +40 -0
- package/repos/effect/packages/effect/benchmark/schema/Optic.ts +79 -0
- package/repos/effect/packages/effect/benchmark/schema/array.ts +74 -0
- package/repos/effect/packages/effect/benchmark/schema/filter.ts +74 -0
- package/repos/effect/packages/effect/benchmark/schema/object.ts +82 -0
- package/repos/effect/packages/effect/benchmark/schema/tagged-union.ts +69 -0
- package/repos/effect/packages/effect/benchmark/schema/transformation.ts +91 -0
- package/repos/effect/packages/effect/benchmark/stream/splitLines.ts +46 -0
- package/repos/effect/packages/effect/docgen.json +38 -0
- package/repos/effect/packages/effect/package.json +127 -0
- package/repos/effect/packages/effect/src/Array.ts +4908 -0
- package/repos/effect/packages/effect/src/BigDecimal.ts +1943 -0
- package/repos/effect/packages/effect/src/BigInt.ts +1029 -0
- package/repos/effect/packages/effect/src/Boolean.ts +481 -0
- package/repos/effect/packages/effect/src/Brand.ts +318 -0
- package/repos/effect/packages/effect/src/Cache.ts +1295 -0
- package/repos/effect/packages/effect/src/Cause.ts +1939 -0
- package/repos/effect/packages/effect/src/Channel.ts +8615 -0
- package/repos/effect/packages/effect/src/ChannelSchema.ts +308 -0
- package/repos/effect/packages/effect/src/Chunk.ts +2976 -0
- package/repos/effect/packages/effect/src/Clock.ts +194 -0
- package/repos/effect/packages/effect/src/Combiner.ts +316 -0
- package/repos/effect/packages/effect/src/Config.ts +1416 -0
- package/repos/effect/packages/effect/src/ConfigProvider.ts +1159 -0
- package/repos/effect/packages/effect/src/Console.ts +653 -0
- package/repos/effect/packages/effect/src/Context.ts +1339 -0
- package/repos/effect/packages/effect/src/Cron.ts +1212 -0
- package/repos/effect/packages/effect/src/Crypto.ts +318 -0
- package/repos/effect/packages/effect/src/Data.ts +774 -0
- package/repos/effect/packages/effect/src/DateTime.ts +2922 -0
- package/repos/effect/packages/effect/src/Deferred.ts +917 -0
- package/repos/effect/packages/effect/src/Differ.ts +32 -0
- package/repos/effect/packages/effect/src/Duration.ts +1827 -0
- package/repos/effect/packages/effect/src/Effect.ts +15347 -0
- package/repos/effect/packages/effect/src/Effectable.ts +68 -0
- package/repos/effect/packages/effect/src/Encoding.ts +1046 -0
- package/repos/effect/packages/effect/src/Equal.ts +550 -0
- package/repos/effect/packages/effect/src/Equivalence.ts +870 -0
- package/repos/effect/packages/effect/src/ErrorReporter.ts +543 -0
- package/repos/effect/packages/effect/src/ExecutionPlan.ts +416 -0
- package/repos/effect/packages/effect/src/Exit.ts +1085 -0
- package/repos/effect/packages/effect/src/Fiber.ts +632 -0
- package/repos/effect/packages/effect/src/FiberHandle.ts +815 -0
- package/repos/effect/packages/effect/src/FiberMap.ts +1030 -0
- package/repos/effect/packages/effect/src/FiberSet.ts +713 -0
- package/repos/effect/packages/effect/src/FileSystem.ts +1394 -0
- package/repos/effect/packages/effect/src/Filter.ts +827 -0
- package/repos/effect/packages/effect/src/Formatter.ts +319 -0
- package/repos/effect/packages/effect/src/Function.ts +1415 -0
- package/repos/effect/packages/effect/src/Graph.ts +4892 -0
- package/repos/effect/packages/effect/src/HKT.ts +213 -0
- package/repos/effect/packages/effect/src/Hash.ts +539 -0
- package/repos/effect/packages/effect/src/HashMap.ts +1236 -0
- package/repos/effect/packages/effect/src/HashRing.ts +426 -0
- package/repos/effect/packages/effect/src/HashSet.ts +605 -0
- package/repos/effect/packages/effect/src/Inspectable.ts +329 -0
- package/repos/effect/packages/effect/src/Iterable.ts +2483 -0
- package/repos/effect/packages/effect/src/JsonPatch.ts +469 -0
- package/repos/effect/packages/effect/src/JsonPointer.ts +80 -0
- package/repos/effect/packages/effect/src/JsonSchema.ts +948 -0
- package/repos/effect/packages/effect/src/Latch.ts +373 -0
- package/repos/effect/packages/effect/src/Layer.ts +2773 -0
- package/repos/effect/packages/effect/src/LayerMap.ts +468 -0
- package/repos/effect/packages/effect/src/LogLevel.ts +412 -0
- package/repos/effect/packages/effect/src/Logger.ts +1284 -0
- package/repos/effect/packages/effect/src/ManagedRuntime.ts +381 -0
- package/repos/effect/packages/effect/src/Match.ts +2606 -0
- package/repos/effect/packages/effect/src/Metric.ts +4058 -0
- package/repos/effect/packages/effect/src/MutableHashMap.ts +845 -0
- package/repos/effect/packages/effect/src/MutableHashSet.ts +422 -0
- package/repos/effect/packages/effect/src/MutableList.ts +967 -0
- package/repos/effect/packages/effect/src/MutableRef.ts +822 -0
- package/repos/effect/packages/effect/src/Newtype.ts +319 -0
- package/repos/effect/packages/effect/src/NonEmptyIterable.ts +221 -0
- package/repos/effect/packages/effect/src/Number.ts +860 -0
- package/repos/effect/packages/effect/src/Optic.ts +1701 -0
- package/repos/effect/packages/effect/src/Option.ts +2664 -0
- package/repos/effect/packages/effect/src/Order.ts +982 -0
- package/repos/effect/packages/effect/src/Ordering.ts +182 -0
- package/repos/effect/packages/effect/src/PartitionedSemaphore.ts +561 -0
- package/repos/effect/packages/effect/src/Path.ts +870 -0
- package/repos/effect/packages/effect/src/Pipeable.ts +674 -0
- package/repos/effect/packages/effect/src/PlatformError.ts +221 -0
- package/repos/effect/packages/effect/src/Pool.ts +699 -0
- package/repos/effect/packages/effect/src/Predicate.ts +1872 -0
- package/repos/effect/packages/effect/src/PrimaryKey.ts +123 -0
- package/repos/effect/packages/effect/src/PubSub.ts +2797 -0
- package/repos/effect/packages/effect/src/Pull.ts +376 -0
- package/repos/effect/packages/effect/src/Queue.ts +1962 -0
- package/repos/effect/packages/effect/src/Random.ts +549 -0
- package/repos/effect/packages/effect/src/RcMap.ts +612 -0
- package/repos/effect/packages/effect/src/RcRef.ts +225 -0
- package/repos/effect/packages/effect/src/Record.ts +1563 -0
- package/repos/effect/packages/effect/src/Redactable.ts +168 -0
- package/repos/effect/packages/effect/src/Redacted.ts +314 -0
- package/repos/effect/packages/effect/src/Reducer.ts +178 -0
- package/repos/effect/packages/effect/src/Ref.ts +801 -0
- package/repos/effect/packages/effect/src/References.ts +786 -0
- package/repos/effect/packages/effect/src/RegExp.ts +82 -0
- package/repos/effect/packages/effect/src/Request.ts +598 -0
- package/repos/effect/packages/effect/src/RequestResolver.ts +1249 -0
- package/repos/effect/packages/effect/src/Resource.ts +184 -0
- package/repos/effect/packages/effect/src/Result.ts +1939 -0
- package/repos/effect/packages/effect/src/Runtime.ts +432 -0
- package/repos/effect/packages/effect/src/Schedule.ts +3564 -0
- package/repos/effect/packages/effect/src/Scheduler.ts +285 -0
- package/repos/effect/packages/effect/src/Schema.ts +14653 -0
- package/repos/effect/packages/effect/src/SchemaAST.ts +3903 -0
- package/repos/effect/packages/effect/src/SchemaGetter.ts +1870 -0
- package/repos/effect/packages/effect/src/SchemaIssue.ts +1176 -0
- package/repos/effect/packages/effect/src/SchemaParser.ts +1105 -0
- package/repos/effect/packages/effect/src/SchemaRepresentation.ts +3944 -0
- package/repos/effect/packages/effect/src/SchemaTransformation.ts +1818 -0
- package/repos/effect/packages/effect/src/SchemaUtils.ts +51 -0
- package/repos/effect/packages/effect/src/Scope.ts +572 -0
- package/repos/effect/packages/effect/src/ScopedCache.ts +820 -0
- package/repos/effect/packages/effect/src/ScopedRef.ts +192 -0
- package/repos/effect/packages/effect/src/Semaphore.ts +517 -0
- package/repos/effect/packages/effect/src/Sink.ts +2174 -0
- package/repos/effect/packages/effect/src/Stdio.ts +143 -0
- package/repos/effect/packages/effect/src/Stream.ts +11722 -0
- package/repos/effect/packages/effect/src/String.ts +1427 -0
- package/repos/effect/packages/effect/src/Struct.ts +979 -0
- package/repos/effect/packages/effect/src/SubscriptionRef.ts +1021 -0
- package/repos/effect/packages/effect/src/Symbol.ts +31 -0
- package/repos/effect/packages/effect/src/SynchronizedRef.ts +668 -0
- package/repos/effect/packages/effect/src/Take.ts +46 -0
- package/repos/effect/packages/effect/src/Terminal.ts +188 -0
- package/repos/effect/packages/effect/src/Tracer.ts +683 -0
- package/repos/effect/packages/effect/src/Trie.ts +953 -0
- package/repos/effect/packages/effect/src/Tuple.ts +737 -0
- package/repos/effect/packages/effect/src/TxChunk.ts +822 -0
- package/repos/effect/packages/effect/src/TxDeferred.ts +319 -0
- package/repos/effect/packages/effect/src/TxHashMap.ts +2165 -0
- package/repos/effect/packages/effect/src/TxHashSet.ts +908 -0
- package/repos/effect/packages/effect/src/TxPriorityQueue.ts +567 -0
- package/repos/effect/packages/effect/src/TxPubSub.ts +684 -0
- package/repos/effect/packages/effect/src/TxQueue.ts +1488 -0
- package/repos/effect/packages/effect/src/TxReentrantLock.ts +655 -0
- package/repos/effect/packages/effect/src/TxRef.ts +282 -0
- package/repos/effect/packages/effect/src/TxSemaphore.ts +707 -0
- package/repos/effect/packages/effect/src/TxSubscriptionRef.ts +518 -0
- package/repos/effect/packages/effect/src/Types.ts +1121 -0
- package/repos/effect/packages/effect/src/UndefinedOr.ts +239 -0
- package/repos/effect/packages/effect/src/Unify.ts +314 -0
- package/repos/effect/packages/effect/src/Utils.ts +221 -0
- package/repos/effect/packages/effect/src/index.ts +712 -0
- package/repos/effect/packages/effect/src/internal/array.ts +8 -0
- package/repos/effect/packages/effect/src/internal/concurrency.ts +52 -0
- package/repos/effect/packages/effect/src/internal/core.ts +666 -0
- package/repos/effect/packages/effect/src/internal/dateTime.ts +1264 -0
- package/repos/effect/packages/effect/src/internal/doNotation.ts +117 -0
- package/repos/effect/packages/effect/src/internal/effect.ts +6427 -0
- package/repos/effect/packages/effect/src/internal/equal.ts +28 -0
- package/repos/effect/packages/effect/src/internal/errors.ts +9 -0
- package/repos/effect/packages/effect/src/internal/executionPlan.ts +120 -0
- package/repos/effect/packages/effect/src/internal/hashMap.ts +1309 -0
- package/repos/effect/packages/effect/src/internal/hashSet.ts +190 -0
- package/repos/effect/packages/effect/src/internal/layer.ts +88 -0
- package/repos/effect/packages/effect/src/internal/matcher.ts +637 -0
- package/repos/effect/packages/effect/src/internal/metric.ts +2 -0
- package/repos/effect/packages/effect/src/internal/option.ts +98 -0
- package/repos/effect/packages/effect/src/internal/random.ts +20 -0
- package/repos/effect/packages/effect/src/internal/rcRef.ts +189 -0
- package/repos/effect/packages/effect/src/internal/record.ts +18 -0
- package/repos/effect/packages/effect/src/internal/redacted.ts +19 -0
- package/repos/effect/packages/effect/src/internal/references.ts +72 -0
- package/repos/effect/packages/effect/src/internal/request.ts +205 -0
- package/repos/effect/packages/effect/src/internal/result.ts +112 -0
- package/repos/effect/packages/effect/src/internal/schedule.ts +248 -0
- package/repos/effect/packages/effect/src/internal/schema/annotations.ts +37 -0
- package/repos/effect/packages/effect/src/internal/schema/arbitrary.ts +894 -0
- package/repos/effect/packages/effect/src/internal/schema/cause.ts +26 -0
- package/repos/effect/packages/effect/src/internal/schema/equivalence.ts +154 -0
- package/repos/effect/packages/effect/src/internal/schema/representation.ts +799 -0
- package/repos/effect/packages/effect/src/internal/schema/schema.ts +128 -0
- package/repos/effect/packages/effect/src/internal/stream.ts +28 -0
- package/repos/effect/packages/effect/src/internal/tracer.ts +41 -0
- package/repos/effect/packages/effect/src/internal/trie.ts +733 -0
- package/repos/effect/packages/effect/src/internal/version.ts +2 -0
- package/repos/effect/packages/effect/src/testing/FastCheck.ts +89 -0
- package/repos/effect/packages/effect/src/testing/TestClock.ts +547 -0
- package/repos/effect/packages/effect/src/testing/TestConsole.ts +369 -0
- package/repos/effect/packages/effect/src/testing/TestSchema.ts +567 -0
- package/repos/effect/packages/effect/src/testing/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/ai/AiError.ts +1629 -0
- package/repos/effect/packages/effect/src/unstable/ai/AnthropicStructuredOutput.ts +407 -0
- package/repos/effect/packages/effect/src/unstable/ai/Chat.ts +931 -0
- package/repos/effect/packages/effect/src/unstable/ai/EmbeddingModel.ts +269 -0
- package/repos/effect/packages/effect/src/unstable/ai/IdGenerator.ts +300 -0
- package/repos/effect/packages/effect/src/unstable/ai/LanguageModel.ts +2221 -0
- package/repos/effect/packages/effect/src/unstable/ai/McpSchema.ts +2527 -0
- package/repos/effect/packages/effect/src/unstable/ai/McpServer.ts +1468 -0
- package/repos/effect/packages/effect/src/unstable/ai/Model.ts +166 -0
- package/repos/effect/packages/effect/src/unstable/ai/OpenAiStructuredOutput.ts +476 -0
- package/repos/effect/packages/effect/src/unstable/ai/Prompt.ts +2234 -0
- package/repos/effect/packages/effect/src/unstable/ai/Response.ts +2582 -0
- package/repos/effect/packages/effect/src/unstable/ai/ResponseIdTracker.ts +139 -0
- package/repos/effect/packages/effect/src/unstable/ai/Telemetry.ts +515 -0
- package/repos/effect/packages/effect/src/unstable/ai/Tokenizer.ts +176 -0
- package/repos/effect/packages/effect/src/unstable/ai/Tool.ts +2003 -0
- package/repos/effect/packages/effect/src/unstable/ai/Toolkit.ts +554 -0
- package/repos/effect/packages/effect/src/unstable/ai/index.ts +90 -0
- package/repos/effect/packages/effect/src/unstable/ai/internal/codec-transformer.ts +13 -0
- package/repos/effect/packages/effect/src/unstable/cli/Argument.ts +749 -0
- package/repos/effect/packages/effect/src/unstable/cli/CliError.ts +549 -0
- package/repos/effect/packages/effect/src/unstable/cli/CliOutput.ts +607 -0
- package/repos/effect/packages/effect/src/unstable/cli/Command.ts +1610 -0
- package/repos/effect/packages/effect/src/unstable/cli/Completions.ts +123 -0
- package/repos/effect/packages/effect/src/unstable/cli/Flag.ts +986 -0
- package/repos/effect/packages/effect/src/unstable/cli/GlobalFlag.ts +295 -0
- package/repos/effect/packages/effect/src/unstable/cli/HelpDoc.ts +323 -0
- package/repos/effect/packages/effect/src/unstable/cli/Param.ts +2193 -0
- package/repos/effect/packages/effect/src/unstable/cli/Primitive.ts +766 -0
- package/repos/effect/packages/effect/src/unstable/cli/Prompt.ts +3852 -0
- package/repos/effect/packages/effect/src/unstable/cli/SEMANTICS.md +157 -0
- package/repos/effect/packages/effect/src/unstable/cli/index.ts +60 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/ansi.ts +152 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/auto-suggest.ts +41 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/command.ts +340 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/bash.ts +222 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/descriptor.ts +133 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/fish.ts +253 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/completions/zsh.ts +220 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/config.ts +272 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/help.ts +181 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/lexer.ts +70 -0
- package/repos/effect/packages/effect/src/unstable/cli/internal/parser.ts +932 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterCron.ts +163 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterError.ts +238 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterMetrics.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterSchema.ts +170 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ClusterWorkflowEngine.ts +778 -0
- package/repos/effect/packages/effect/src/unstable/cluster/DeliverAt.ts +58 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Entity.ts +779 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityAddress.ts +93 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityId.ts +50 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityProxy.ts +263 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityProxyServer.ts +149 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityResource.ts +184 -0
- package/repos/effect/packages/effect/src/unstable/cluster/EntityType.ts +52 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Envelope.ts +433 -0
- package/repos/effect/packages/effect/src/unstable/cluster/HttpRunner.ts +345 -0
- package/repos/effect/packages/effect/src/unstable/cluster/K8sHttpClient.ts +297 -0
- package/repos/effect/packages/effect/src/unstable/cluster/MachineId.ts +54 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Message.ts +314 -0
- package/repos/effect/packages/effect/src/unstable/cluster/MessageStorage.ts +1072 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Reply.ts +455 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Runner.ts +129 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerAddress.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerHealth.ts +145 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerServer.ts +220 -0
- package/repos/effect/packages/effect/src/unstable/cluster/RunnerStorage.ts +243 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Runners.ts +690 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardId.ts +178 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Sharding.ts +1488 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardingConfig.ts +367 -0
- package/repos/effect/packages/effect/src/unstable/cluster/ShardingRegistrationEvent.ts +76 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SingleRunner.ts +75 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Singleton.ts +56 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SingletonAddress.ts +49 -0
- package/repos/effect/packages/effect/src/unstable/cluster/Snowflake.ts +282 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SocketRunner.ts +96 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SqlMessageStorage.ts +1045 -0
- package/repos/effect/packages/effect/src/unstable/cluster/SqlRunnerStorage.ts +700 -0
- package/repos/effect/packages/effect/src/unstable/cluster/TestRunner.ts +36 -0
- package/repos/effect/packages/effect/src/unstable/cluster/index.ts +195 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/entityManager.ts +678 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/entityReaper.ts +58 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/hash.ts +23 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/interruptors.ts +2 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/resourceMap.ts +100 -0
- package/repos/effect/packages/effect/src/unstable/cluster/internal/resourceRef.ts +99 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevTools.ts +68 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsClient.ts +236 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsSchema.ts +558 -0
- package/repos/effect/packages/effect/src/unstable/devtools/DevToolsServer.ts +94 -0
- package/repos/effect/packages/effect/src/unstable/devtools/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Msgpack.ts +383 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Ndjson.ts +602 -0
- package/repos/effect/packages/effect/src/unstable/encoding/Sse.ts +593 -0
- package/repos/effect/packages/effect/src/unstable/encoding/index.ts +20 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/Event.ts +447 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventGroup.ts +193 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventJournal.ts +795 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLog.ts +1030 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogEncryption.ts +169 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogMessage.ts +354 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogRemote.ts +377 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServer.ts +242 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServerEncrypted.ts +268 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogServerUnencrypted.ts +898 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/EventLogSessionAuth.ts +524 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventJournal.ts +353 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventLogServerEncrypted.ts +343 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +527 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/index.ts +75 -0
- package/repos/effect/packages/effect/src/unstable/eventlog/internal/identityRootSecretDerivation.ts +153 -0
- package/repos/effect/packages/effect/src/unstable/http/Cookies.ts +952 -0
- package/repos/effect/packages/effect/src/unstable/http/Etag.ts +141 -0
- package/repos/effect/packages/effect/src/unstable/http/FetchHttpClient.ts +123 -0
- package/repos/effect/packages/effect/src/unstable/http/FindMyWay.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/http/Headers.ts +438 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpBody.ts +545 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClient.ts +1630 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientError.ts +328 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientRequest.ts +968 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpClientResponse.ts +408 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpEffect.ts +400 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpIncomingMessage.ts +153 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpMethod.ts +124 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpMiddleware.ts +394 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpPlatform.ts +165 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpRouter.ts +1341 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServer.ts +329 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerError.ts +374 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerRequest.ts +1081 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerRespondable.ts +115 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpServerResponse.ts +1381 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpStaticServer.ts +464 -0
- package/repos/effect/packages/effect/src/unstable/http/HttpTraceContext.ts +160 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipart.ts +830 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/HeadersParser.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Node.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Search.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta/Web.ts +14 -0
- package/repos/effect/packages/effect/src/unstable/http/Multipasta.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/http/Template.ts +262 -0
- package/repos/effect/packages/effect/src/unstable/http/Url.ts +330 -0
- package/repos/effect/packages/effect/src/unstable/http/UrlParams.ts +678 -0
- package/repos/effect/packages/effect/src/unstable/http/index.ts +145 -0
- package/repos/effect/packages/effect/src/unstable/http/internal/preResponseHandler.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApi.ts +316 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiBuilder.ts +1015 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiClient.ts +1005 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiEndpoint.ts +1545 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiError.ts +443 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiGroup.ts +381 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiMiddleware.ts +478 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiScalar.ts +267 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSchema.ts +733 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSecurity.ts +244 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiSwagger.ts +68 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/HttpApiTest.ts +112 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/OpenApi.ts +1098 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/index.ts +70 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/html.ts +18 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/httpApiScalar.ts +5 -0
- package/repos/effect/packages/effect/src/unstable/httpapi/internal/httpApiSwagger.ts +9 -0
- package/repos/effect/packages/effect/src/unstable/observability/Otlp.ts +172 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpExporter.ts +149 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpLogger.ts +340 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpMetrics.ts +826 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpResource.ts +288 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpSerialization.ts +66 -0
- package/repos/effect/packages/effect/src/unstable/observability/OtlpTracer.ts +442 -0
- package/repos/effect/packages/effect/src/unstable/observability/PrometheusMetrics.ts +468 -0
- package/repos/effect/packages/effect/src/unstable/observability/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/otlpEnv.ts +39 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/otlpProtobuf.ts +779 -0
- package/repos/effect/packages/effect/src/unstable/observability/internal/protobuf.ts +262 -0
- package/repos/effect/packages/effect/src/unstable/persistence/KeyValueStore.ts +864 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Persistable.ts +252 -0
- package/repos/effect/packages/effect/src/unstable/persistence/PersistedCache.ts +111 -0
- package/repos/effect/packages/effect/src/unstable/persistence/PersistedQueue.ts +1196 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Persistence.ts +1071 -0
- package/repos/effect/packages/effect/src/unstable/persistence/RateLimiter.ts +748 -0
- package/repos/effect/packages/effect/src/unstable/persistence/Redis.ts +188 -0
- package/repos/effect/packages/effect/src/unstable/persistence/index.ts +40 -0
- package/repos/effect/packages/effect/src/unstable/process/ChildProcess.ts +1036 -0
- package/repos/effect/packages/effect/src/unstable/process/ChildProcessSpawner.ts +285 -0
- package/repos/effect/packages/effect/src/unstable/process/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AsyncResult.ts +1081 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Atom.ts +2520 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomHttpApi.ts +352 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRef.ts +352 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRegistry.ts +1127 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/AtomRpc.ts +305 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Hydration.ts +155 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/Reactivity.ts +348 -0
- package/repos/effect/packages/effect/src/unstable/reactivity/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/rpc/Rpc.ts +1255 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcClient.ts +1370 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcClientError.ts +57 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcGroup.ts +409 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcMessage.ts +402 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcMiddleware.ts +344 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcSchema.ts +97 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcSerialization.ts +546 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcServer.ts +1492 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcTest.ts +56 -0
- package/repos/effect/packages/effect/src/unstable/rpc/RpcWorker.ts +118 -0
- package/repos/effect/packages/effect/src/unstable/rpc/Utils.ts +120 -0
- package/repos/effect/packages/effect/src/unstable/rpc/index.ts +65 -0
- package/repos/effect/packages/effect/src/unstable/schema/Model.ts +862 -0
- package/repos/effect/packages/effect/src/unstable/schema/VariantSchema.ts +604 -0
- package/repos/effect/packages/effect/src/unstable/schema/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/socket/Socket.ts +911 -0
- package/repos/effect/packages/effect/src/unstable/socket/SocketServer.ts +147 -0
- package/repos/effect/packages/effect/src/unstable/socket/index.ts +15 -0
- package/repos/effect/packages/effect/src/unstable/sql/Migrator.ts +440 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlClient.ts +342 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlConnection.ts +83 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlError.ts +590 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlModel.ts +359 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlResolver.ts +380 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlSchema.ts +172 -0
- package/repos/effect/packages/effect/src/unstable/sql/SqlStream.ts +81 -0
- package/repos/effect/packages/effect/src/unstable/sql/Statement.ts +1500 -0
- package/repos/effect/packages/effect/src/unstable/sql/index.ts +50 -0
- package/repos/effect/packages/effect/src/unstable/workers/Transferable.ts +191 -0
- package/repos/effect/packages/effect/src/unstable/workers/Worker.ts +245 -0
- package/repos/effect/packages/effect/src/unstable/workers/WorkerError.ts +148 -0
- package/repos/effect/packages/effect/src/unstable/workers/WorkerRunner.ts +57 -0
- package/repos/effect/packages/effect/src/unstable/workers/index.ts +25 -0
- package/repos/effect/packages/effect/src/unstable/workflow/Activity.ts +322 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableClock.ts +117 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableDeferred.ts +653 -0
- package/repos/effect/packages/effect/src/unstable/workflow/DurableQueue.ts +360 -0
- package/repos/effect/packages/effect/src/unstable/workflow/Workflow.ts +898 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowEngine.ts +759 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowProxy.ts +212 -0
- package/repos/effect/packages/effect/src/unstable/workflow/WorkflowProxyServer.ts +151 -0
- package/repos/effect/packages/effect/src/unstable/workflow/index.ts +45 -0
- package/repos/effect/packages/effect/src/unstable/workflow/internal/crypto.ts +15 -0
- package/repos/effect/packages/effect/test/Array.test.ts +1579 -0
- package/repos/effect/packages/effect/test/AtomRef.test.ts +27 -0
- package/repos/effect/packages/effect/test/BigDecimal.test.ts +525 -0
- package/repos/effect/packages/effect/test/BigInt.test.ts +57 -0
- package/repos/effect/packages/effect/test/Boolean.test.ts +289 -0
- package/repos/effect/packages/effect/test/Brand.test.ts +160 -0
- package/repos/effect/packages/effect/test/Cache.test.ts +1423 -0
- package/repos/effect/packages/effect/test/Cause.test.ts +834 -0
- package/repos/effect/packages/effect/test/Channel.test.ts +556 -0
- package/repos/effect/packages/effect/test/Chunk.test.ts +874 -0
- package/repos/effect/packages/effect/test/Combiner.test.ts +42 -0
- package/repos/effect/packages/effect/test/Config.test.ts +1416 -0
- package/repos/effect/packages/effect/test/ConfigProvider.test.ts +726 -0
- package/repos/effect/packages/effect/test/Cron.test.ts +401 -0
- package/repos/effect/packages/effect/test/Crypto.test.ts +86 -0
- package/repos/effect/packages/effect/test/Data.test.ts +269 -0
- package/repos/effect/packages/effect/test/DateTime.test.ts +953 -0
- package/repos/effect/packages/effect/test/Deferred.test.ts +165 -0
- package/repos/effect/packages/effect/test/Duration.test.ts +679 -0
- package/repos/effect/packages/effect/test/Effect.test.ts +2658 -0
- package/repos/effect/packages/effect/test/EffectEager.test.ts +678 -0
- package/repos/effect/packages/effect/test/EffectKeepAlive.test.ts +71 -0
- package/repos/effect/packages/effect/test/Equal.test.ts +1278 -0
- package/repos/effect/packages/effect/test/Equivalence.test.ts +170 -0
- package/repos/effect/packages/effect/test/ExecutionPlan.test.ts +117 -0
- package/repos/effect/packages/effect/test/Exit.test.ts +12 -0
- package/repos/effect/packages/effect/test/Fiber.test.ts +9 -0
- package/repos/effect/packages/effect/test/FiberHandle.test.ts +146 -0
- package/repos/effect/packages/effect/test/FiberMap.test.ts +171 -0
- package/repos/effect/packages/effect/test/FiberSet.test.ts +119 -0
- package/repos/effect/packages/effect/test/Formatter.test.ts +247 -0
- package/repos/effect/packages/effect/test/Function.test.ts +333 -0
- package/repos/effect/packages/effect/test/Graph.test.ts +3505 -0
- package/repos/effect/packages/effect/test/HashMap.test.ts +618 -0
- package/repos/effect/packages/effect/test/HashSet.test.ts +298 -0
- package/repos/effect/packages/effect/test/HttpClient.test.ts +131 -0
- package/repos/effect/packages/effect/test/Iterable.test.ts +486 -0
- package/repos/effect/packages/effect/test/JsonPatch.test.ts +948 -0
- package/repos/effect/packages/effect/test/JsonPointer.test.ts +353 -0
- package/repos/effect/packages/effect/test/JsonSchema.test.ts +1253 -0
- package/repos/effect/packages/effect/test/Latch.test.ts +21 -0
- package/repos/effect/packages/effect/test/Layer.test.ts +648 -0
- package/repos/effect/packages/effect/test/LayerMap.test.ts +98 -0
- package/repos/effect/packages/effect/test/LogLevel.test.ts +28 -0
- package/repos/effect/packages/effect/test/Logger.test.ts +154 -0
- package/repos/effect/packages/effect/test/ManagedRuntime.test.ts +58 -0
- package/repos/effect/packages/effect/test/Match.test.ts +27 -0
- package/repos/effect/packages/effect/test/Metric.test.ts +682 -0
- package/repos/effect/packages/effect/test/Migrator.test.ts +69 -0
- package/repos/effect/packages/effect/test/MutableHashMap.test.ts +309 -0
- package/repos/effect/packages/effect/test/MutableHashSet.test.ts +10 -0
- package/repos/effect/packages/effect/test/MutableList.test.ts +58 -0
- package/repos/effect/packages/effect/test/Newtype.test.ts +90 -0
- package/repos/effect/packages/effect/test/Number.test.ts +422 -0
- package/repos/effect/packages/effect/test/Optic.test.ts +452 -0
- package/repos/effect/packages/effect/test/Option.test.ts +564 -0
- package/repos/effect/packages/effect/test/Order.test.ts +163 -0
- package/repos/effect/packages/effect/test/Ordering.test.ts +18 -0
- package/repos/effect/packages/effect/test/PartitionedSemaphore.test.ts +74 -0
- package/repos/effect/packages/effect/test/Pathfinding.test.ts +426 -0
- package/repos/effect/packages/effect/test/Pool.test.ts +422 -0
- package/repos/effect/packages/effect/test/Predicate.test.ts +555 -0
- package/repos/effect/packages/effect/test/PubSub.test.ts +538 -0
- package/repos/effect/packages/effect/test/Queue.test.ts +317 -0
- package/repos/effect/packages/effect/test/Random.test.ts +238 -0
- package/repos/effect/packages/effect/test/RcMap.test.ts +237 -0
- package/repos/effect/packages/effect/test/RcRef.test.ts +97 -0
- package/repos/effect/packages/effect/test/Record.test.ts +395 -0
- package/repos/effect/packages/effect/test/Redacted.test.ts +59 -0
- package/repos/effect/packages/effect/test/Reducer.test.ts +12 -0
- package/repos/effect/packages/effect/test/Ref.test.ts +187 -0
- package/repos/effect/packages/effect/test/Request.test.ts +305 -0
- package/repos/effect/packages/effect/test/Resource.test.ts +59 -0
- package/repos/effect/packages/effect/test/Result.test.ts +517 -0
- package/repos/effect/packages/effect/test/Schedule.test.ts +395 -0
- package/repos/effect/packages/effect/test/Scheduler.test.ts +70 -0
- package/repos/effect/packages/effect/test/Scope.test.ts +19 -0
- package/repos/effect/packages/effect/test/ScopedCache.test.ts +2316 -0
- package/repos/effect/packages/effect/test/ScopedRef.test.ts +80 -0
- package/repos/effect/packages/effect/test/Semaphore.test.ts +469 -0
- package/repos/effect/packages/effect/test/Sink.test.ts +230 -0
- package/repos/effect/packages/effect/test/Stream.test.ts +4712 -0
- package/repos/effect/packages/effect/test/String.test.ts +690 -0
- package/repos/effect/packages/effect/test/Struct.test.ts +216 -0
- package/repos/effect/packages/effect/test/SubscriptionRef.test.ts +90 -0
- package/repos/effect/packages/effect/test/Symbol.test.ts +50 -0
- package/repos/effect/packages/effect/test/SynchronizedRef.test.ts +105 -0
- package/repos/effect/packages/effect/test/TestClock.test.ts +71 -0
- package/repos/effect/packages/effect/test/Tracer.test.ts +410 -0
- package/repos/effect/packages/effect/test/Trie.test.ts +531 -0
- package/repos/effect/packages/effect/test/Tuple.test.ts +127 -0
- package/repos/effect/packages/effect/test/TxChunk.test.ts +342 -0
- package/repos/effect/packages/effect/test/TxDeferred.test.ts +197 -0
- package/repos/effect/packages/effect/test/TxHashMap.test.ts +963 -0
- package/repos/effect/packages/effect/test/TxHashSet.test.ts +442 -0
- package/repos/effect/packages/effect/test/TxPriorityQueue.test.ts +187 -0
- package/repos/effect/packages/effect/test/TxPubSub.test.ts +391 -0
- package/repos/effect/packages/effect/test/TxQueue.test.ts +1260 -0
- package/repos/effect/packages/effect/test/TxReentrantLock.test.ts +413 -0
- package/repos/effect/packages/effect/test/TxSemaphore.test.ts +283 -0
- package/repos/effect/packages/effect/test/TxSubscriptionRef.test.ts +197 -0
- package/repos/effect/packages/effect/test/UndefinedOr.test.ts +65 -0
- package/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts +652 -0
- package/repos/effect/packages/effect/test/cluster/Entity.test.ts +81 -0
- package/repos/effect/packages/effect/test/cluster/K8sHttpClient.test.ts +34 -0
- package/repos/effect/packages/effect/test/cluster/MessageStorage.test.ts +196 -0
- package/repos/effect/packages/effect/test/cluster/Sharding.test.ts +578 -0
- package/repos/effect/packages/effect/test/cluster/TestEntity.ts +132 -0
- package/repos/effect/packages/effect/test/reactivity/AsyncResult.test.ts +41 -0
- package/repos/effect/packages/effect/test/reactivity/Atom.test.ts +2551 -0
- package/repos/effect/packages/effect/test/reactivity/AtomHttpApi.test.ts +86 -0
- package/repos/effect/packages/effect/test/reactivity/AtomRpc.test.ts +70 -0
- package/repos/effect/packages/effect/test/rpc/Rpc.test.ts +73 -0
- package/repos/effect/packages/effect/test/rpc/RpcClient.test.ts +58 -0
- package/repos/effect/packages/effect/test/rpc/RpcSerialization.test.ts +171 -0
- package/repos/effect/packages/effect/test/schema/HMR.test.ts +72 -0
- package/repos/effect/packages/effect/test/schema/Schema.test.ts +9133 -0
- package/repos/effect/packages/effect/test/schema/SchemaAST.test.ts +280 -0
- package/repos/effect/packages/effect/test/schema/SchemaGetter.test.ts +383 -0
- package/repos/effect/packages/effect/test/schema/SchemaIssue.test.ts +9 -0
- package/repos/effect/packages/effect/test/schema/SchemaParser.test.ts +323 -0
- package/repos/effect/packages/effect/test/schema/fixtures/HMR-Class.ts +5 -0
- package/repos/effect/packages/effect/test/schema/fixtures/HMR-sanity-check.ts +3 -0
- package/repos/effect/packages/effect/test/schema/representation/fromASTs.test.ts +820 -0
- package/repos/effect/packages/effect/test/schema/representation/fromJsonSchemaDocument.test.ts +2137 -0
- package/repos/effect/packages/effect/test/schema/representation/toCodeDocument.test.ts +2089 -0
- package/repos/effect/packages/effect/test/schema/representation/toJsonSchemaMultiDocument.test.ts +39 -0
- package/repos/effect/packages/effect/test/schema/representation/toSchema.test.ts +506 -0
- package/repos/effect/packages/effect/test/schema/toArbitrary.test.ts +1693 -0
- package/repos/effect/packages/effect/test/schema/toCodec.test.ts +3149 -0
- package/repos/effect/packages/effect/test/schema/toDifferJsonPatch.test.ts +239 -0
- package/repos/effect/packages/effect/test/schema/toEquivalence.test.ts +519 -0
- package/repos/effect/packages/effect/test/schema/toFormatter.test.ts +565 -0
- package/repos/effect/packages/effect/test/schema/toIso.test.ts +394 -0
- package/repos/effect/packages/effect/test/schema/toJsonSchemaDocument.test.ts +3630 -0
- package/repos/effect/packages/effect/test/schema/toStandardJSONSchemaV1.test.ts +126 -0
- package/repos/effect/packages/effect/test/schema/toStandardSchemaV1.test.ts +495 -0
- package/repos/effect/packages/effect/test/schema/v3-v4.test.ts +250 -0
- package/repos/effect/packages/effect/test/testing/TestSchema.test.ts +78 -0
- package/repos/effect/packages/effect/test/unstable/ai/AiError.test.ts +823 -0
- package/repos/effect/packages/effect/test/unstable/ai/AnthropicStructuredOutput.test.ts +593 -0
- package/repos/effect/packages/effect/test/unstable/ai/Chat.test.ts +147 -0
- package/repos/effect/packages/effect/test/unstable/ai/EmbeddingModel.test.ts +185 -0
- package/repos/effect/packages/effect/test/unstable/ai/LanguageModel.test.ts +1714 -0
- package/repos/effect/packages/effect/test/unstable/ai/LanguageModelTrackerLifecycle.test.ts +413 -0
- package/repos/effect/packages/effect/test/unstable/ai/McpServer.test.ts +82 -0
- package/repos/effect/packages/effect/test/unstable/ai/Model.test.ts +16 -0
- package/repos/effect/packages/effect/test/unstable/ai/OpenAiStructuredOutput.test.ts +723 -0
- package/repos/effect/packages/effect/test/unstable/ai/Prompt.test.ts +346 -0
- package/repos/effect/packages/effect/test/unstable/ai/ResponseIdTracker.test.ts +424 -0
- package/repos/effect/packages/effect/test/unstable/ai/Tool.test.ts +1264 -0
- package/repos/effect/packages/effect/test/unstable/ai/utils.ts +68 -0
- package/repos/effect/packages/effect/test/unstable/cli/Arguments.test.ts +390 -0
- package/repos/effect/packages/effect/test/unstable/cli/Command.test.ts +1801 -0
- package/repos/effect/packages/effect/test/unstable/cli/Errors.test.ts +150 -0
- package/repos/effect/packages/effect/test/unstable/cli/Help.test.ts +572 -0
- package/repos/effect/packages/effect/test/unstable/cli/LogLevel.test.ts +202 -0
- package/repos/effect/packages/effect/test/unstable/cli/Param.test.ts +391 -0
- package/repos/effect/packages/effect/test/unstable/cli/Primitive.test.ts +321 -0
- package/repos/effect/packages/effect/test/unstable/cli/Prompt.test.ts +597 -0
- package/repos/effect/packages/effect/test/unstable/cli/completions/completions.test.ts +656 -0
- package/repos/effect/packages/effect/test/unstable/cli/completions/descriptor.test.ts +245 -0
- package/repos/effect/packages/effect/test/unstable/cli/fixtures/ComprehensiveCli.ts +422 -0
- package/repos/effect/packages/effect/test/unstable/cli/services/MockTerminal.ts +135 -0
- package/repos/effect/packages/effect/test/unstable/cli/services/TestActions.ts +36 -0
- package/repos/effect/packages/effect/test/unstable/encoding/Ndjson.test.ts +18 -0
- package/repos/effect/packages/effect/test/unstable/encoding/Sse.test.ts +62 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventJournal.test.ts +25 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLog.test.ts +104 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogIdentityDerivation.test.ts +85 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogRemote.test.ts +176 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/EventLogSessionAuth.test.ts +130 -0
- package/repos/effect/packages/effect/test/unstable/eventlog/SqlEventLogServerUnencryptedStorageTest.ts +169 -0
- package/repos/effect/packages/effect/test/unstable/http/Cookies.test.ts +80 -0
- package/repos/effect/packages/effect/test/unstable/http/Headers.test.ts +73 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpClient.test.ts +306 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpClientRequest.test.ts +164 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpEffect.test.ts +254 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpMiddleware.test.ts +57 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerError.test.ts +121 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerRequest.test.ts +157 -0
- package/repos/effect/packages/effect/test/unstable/http/HttpServerResponse.test.ts +76 -0
- package/repos/effect/packages/effect/test/unstable/http/Multipart.test.ts +69 -0
- package/repos/effect/packages/effect/test/unstable/http/Url.test.ts +98 -0
- package/repos/effect/packages/effect/test/unstable/http/UrlParams.test.ts +30 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiBuilder.test.ts +186 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiClient.test.ts +446 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiEndpoint.test.ts +160 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiSchema.test.ts +108 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/HttpApiSecurity.test.ts +41 -0
- package/repos/effect/packages/effect/test/unstable/httpapi/OpenApi.test.ts +39 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpConfig.test.ts +151 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpExporter.test.ts +108 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpMetrics.test.ts +518 -0
- package/repos/effect/packages/effect/test/unstable/observability/OtlpResource.test.ts +84 -0
- package/repos/effect/packages/effect/test/unstable/observability/PrometheusMetrics.test.ts +417 -0
- package/repos/effect/packages/effect/test/unstable/persistence/KeyValueStore.test.ts +164 -0
- package/repos/effect/packages/effect/test/unstable/persistence/KeyValueStoreTest.ts +85 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedCache.test.ts +4 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedCacheTest.ts +111 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedQueue.test.ts +4 -0
- package/repos/effect/packages/effect/test/unstable/persistence/PersistedQueueTest.ts +106 -0
- package/repos/effect/packages/effect/test/unstable/persistence/RateLimiter.test.ts +145 -0
- package/repos/effect/packages/effect/test/unstable/persistence/Redis.test.ts +43 -0
- package/repos/effect/packages/effect/test/unstable/process/ChildProcess.test.ts +352 -0
- package/repos/effect/packages/effect/test/unstable/schema/VariantSchema.test.ts +72 -0
- package/repos/effect/packages/effect/test/unstable/sql/SqlError.test.ts +228 -0
- package/repos/effect/packages/effect/test/unstable/sql/SqlSchema.test.ts +168 -0
- package/repos/effect/packages/effect/test/unstable/workers/WorkerError.test.ts +90 -0
- package/repos/effect/packages/effect/test/unstable/workflow/DurableQueue.test.ts +105 -0
- package/repos/effect/packages/effect/test/unstable/workflow/WorkflowEngine.test.ts +60 -0
- package/repos/effect/packages/effect/test/utils/assert.ts +182 -0
- package/repos/effect/packages/effect/test/utils/chunkCoordination.ts +36 -0
- package/repos/effect/packages/effect/test/utils/counter.ts +54 -0
- package/repos/effect/packages/effect/tsconfig.json +8 -0
- package/repos/effect/packages/effect/typetest/AiError.tst.ts +49 -0
- package/repos/effect/packages/effect/typetest/Array.tst.ts +1289 -0
- package/repos/effect/packages/effect/typetest/Brand.tst.ts +51 -0
- package/repos/effect/packages/effect/typetest/Channel.tst.ts +112 -0
- package/repos/effect/packages/effect/typetest/Config.tst.ts +31 -0
- package/repos/effect/packages/effect/typetest/Data.tst.ts +121 -0
- package/repos/effect/packages/effect/typetest/Effect.tst.ts +976 -0
- package/repos/effect/packages/effect/typetest/Equivalence.tst.ts +19 -0
- package/repos/effect/packages/effect/typetest/Newtype.tst.ts +72 -0
- package/repos/effect/packages/effect/typetest/Optic.tst.ts +130 -0
- package/repos/effect/packages/effect/typetest/Option.tst.ts +72 -0
- package/repos/effect/packages/effect/typetest/Order.tst.ts +19 -0
- package/repos/effect/packages/effect/typetest/Predicate.tst.ts +251 -0
- package/repos/effect/packages/effect/typetest/Result.tst.ts +353 -0
- package/repos/effect/packages/effect/typetest/Schedule.tst.ts +21 -0
- package/repos/effect/packages/effect/typetest/Stream.tst.ts +197 -0
- package/repos/effect/packages/effect/typetest/Struct.tst.ts +422 -0
- package/repos/effect/packages/effect/typetest/Tuple.tst.ts +177 -0
- package/repos/effect/packages/effect/typetest/Types.tst.ts +364 -0
- package/repos/effect/packages/effect/typetest/VariantSchema.tst.ts +76 -0
- package/repos/effect/packages/effect/typetest/schema/Array.tst.ts +46 -0
- package/repos/effect/packages/effect/typetest/schema/Literals.tst.ts +58 -0
- package/repos/effect/packages/effect/typetest/schema/Record.tst.ts +145 -0
- package/repos/effect/packages/effect/typetest/schema/Schema.tst.ts +1854 -0
- package/repos/effect/packages/effect/typetest/schema/Struct.tst.ts +745 -0
- package/repos/effect/packages/effect/typetest/schema/Tuple.tst.ts +199 -0
- package/repos/effect/packages/effect/typetest/schema/Union.tst.ts +198 -0
- package/repos/effect/packages/effect/typetest/schema/api.tst.ts +276 -0
- package/repos/effect/packages/effect/typetest/schema/toArbitrary.tst.ts +65 -0
- package/repos/effect/packages/effect/typetest/schema/toIso.tst.ts +282 -0
- package/repos/effect/packages/effect/typetest/unstable/ai/LanguageModel.tst.ts +191 -0
- package/repos/effect/packages/effect/typetest/unstable/ai/Tool.tst.ts +33 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Command.tst.ts +124 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Param.tst.ts +20 -0
- package/repos/effect/packages/effect/typetest/unstable/cli/Prompt.tst.ts +97 -0
- package/repos/effect/packages/effect/typetest/unstable/encoding/Ndjson.tst.ts +24 -0
- package/repos/effect/packages/effect/typetest/unstable/http/HttpClient.tst.ts +143 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiBuilder.tst.ts +98 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiClient.tst.ts +677 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiEndpoint.tst.ts +466 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiMiddleware.tst.ts +90 -0
- package/repos/effect/packages/effect/typetest/unstable/httpapi/HttpApiSchema.tst.ts +135 -0
- package/repos/effect/packages/effect/typetest/unstable/reactivity/AsyncResult.tst.ts +65 -0
- package/repos/effect/packages/effect/typetest/unstable/reactivity/AtomHttpApi.tst.ts +63 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/Rpc.tst.ts +74 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcGroup.tst.ts +61 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcMiddleware.tst.ts +41 -0
- package/repos/effect/packages/effect/typetest/unstable/rpc/RpcServer.tst.ts +26 -0
- package/repos/effect/packages/effect/typetest/unstable/sql/SqlSchema.tst.ts +75 -0
- package/repos/effect/packages/effect/typetest/unstable/workflow/Workflow.tst.ts +16 -0
- package/repos/effect/packages/effect/vitest.config.ts +11 -0
- package/repos/effect/packages/opentelemetry/CHANGELOG.md +620 -0
- package/repos/effect/packages/opentelemetry/LICENSE +21 -0
- package/repos/effect/packages/opentelemetry/README.md +5 -0
- package/repos/effect/packages/opentelemetry/docgen.json +30 -0
- package/repos/effect/packages/opentelemetry/package.json +126 -0
- package/repos/effect/packages/opentelemetry/src/Logger.ts +193 -0
- package/repos/effect/packages/opentelemetry/src/Metrics.ts +138 -0
- package/repos/effect/packages/opentelemetry/src/NodeSdk.ts +162 -0
- package/repos/effect/packages/opentelemetry/src/Resource.ts +147 -0
- package/repos/effect/packages/opentelemetry/src/Tracer.ts +594 -0
- package/repos/effect/packages/opentelemetry/src/WebSdk.ts +140 -0
- package/repos/effect/packages/opentelemetry/src/index.ts +35 -0
- package/repos/effect/packages/opentelemetry/src/internal/attributes.ts +28 -0
- package/repos/effect/packages/opentelemetry/src/internal/metrics.ts +463 -0
- package/repos/effect/packages/opentelemetry/src/internal/utilities.ts +5 -0
- package/repos/effect/packages/opentelemetry/test/Logger.test.ts +122 -0
- package/repos/effect/packages/opentelemetry/test/Metrics.test.ts +339 -0
- package/repos/effect/packages/opentelemetry/test/Tracer.test.ts +167 -0
- package/repos/effect/packages/opentelemetry/tsconfig.json +8 -0
- package/repos/effect/packages/opentelemetry/vitest.config.ts +6 -0
- package/repos/effect/packages/platform-browser/CHANGELOG.md +637 -0
- package/repos/effect/packages/platform-browser/LICENSE +21 -0
- package/repos/effect/packages/platform-browser/README.md +1 -0
- package/repos/effect/packages/platform-browser/docgen.json +21 -0
- package/repos/effect/packages/platform-browser/package.json +74 -0
- package/repos/effect/packages/platform-browser/src/BrowserCrypto.ts +97 -0
- package/repos/effect/packages/platform-browser/src/BrowserHttpClient.ts +430 -0
- package/repos/effect/packages/platform-browser/src/BrowserKeyValueStore.ts +177 -0
- package/repos/effect/packages/platform-browser/src/BrowserPersistence.ts +334 -0
- package/repos/effect/packages/platform-browser/src/BrowserRuntime.ts +53 -0
- package/repos/effect/packages/platform-browser/src/BrowserSocket.ts +52 -0
- package/repos/effect/packages/platform-browser/src/BrowserStream.ts +56 -0
- package/repos/effect/packages/platform-browser/src/BrowserWorker.ts +98 -0
- package/repos/effect/packages/platform-browser/src/BrowserWorkerRunner.ts +199 -0
- package/repos/effect/packages/platform-browser/src/Clipboard.ts +143 -0
- package/repos/effect/packages/platform-browser/src/Geolocation.ts +233 -0
- package/repos/effect/packages/platform-browser/src/IndexedDb.ts +113 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbDatabase.ts +648 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbQueryBuilder.ts +2032 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbTable.ts +260 -0
- package/repos/effect/packages/platform-browser/src/IndexedDbVersion.ts +138 -0
- package/repos/effect/packages/platform-browser/src/Permissions.ts +146 -0
- package/repos/effect/packages/platform-browser/src/index.ts +90 -0
- package/repos/effect/packages/platform-browser/test/BrowserCrypto.test.ts +74 -0
- package/repos/effect/packages/platform-browser/test/BrowserHttpClient.test.ts +91 -0
- package/repos/effect/packages/platform-browser/test/BrowserKeyValueStore.test.ts +23 -0
- package/repos/effect/packages/platform-browser/test/BrowserPersistence.test.ts +209 -0
- package/repos/effect/packages/platform-browser/test/BrowserPersistencePersistedCache.test.ts +29 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbDatabase.test.ts +253 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbQueryBuilder.test.ts +1459 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbTable.test.ts +101 -0
- package/repos/effect/packages/platform-browser/test/IndexedDbVersion.test.ts +50 -0
- package/repos/effect/packages/platform-browser/test/Permissions.test.ts +12 -0
- package/repos/effect/packages/platform-browser/test/RpcWorker.test.ts +19 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-e2e.ts +141 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-schemas.ts +157 -0
- package/repos/effect/packages/platform-browser/test/fixtures/rpc-worker.ts +12 -0
- package/repos/effect/packages/platform-browser/tsconfig.json +8 -0
- package/repos/effect/packages/platform-browser/vitest.config.ts +17 -0
- package/repos/effect/packages/platform-browser/vitest.setup.ts +5 -0
- package/repos/effect/packages/platform-bun/CHANGELOG.md +691 -0
- package/repos/effect/packages/platform-bun/LICENSE +21 -0
- package/repos/effect/packages/platform-bun/README.md +7 -0
- package/repos/effect/packages/platform-bun/docgen.json +20 -0
- package/repos/effect/packages/platform-bun/package.json +73 -0
- package/repos/effect/packages/platform-bun/src/BunChildProcessSpawner.ts +6 -0
- package/repos/effect/packages/platform-bun/src/BunClusterHttp.ts +174 -0
- package/repos/effect/packages/platform-bun/src/BunClusterSocket.ts +153 -0
- package/repos/effect/packages/platform-bun/src/BunCrypto.ts +24 -0
- package/repos/effect/packages/platform-bun/src/BunFileSystem.ts +20 -0
- package/repos/effect/packages/platform-bun/src/BunHttpClient.ts +9 -0
- package/repos/effect/packages/platform-bun/src/BunHttpPlatform.ts +50 -0
- package/repos/effect/packages/platform-bun/src/BunHttpServer.ts +600 -0
- package/repos/effect/packages/platform-bun/src/BunHttpServerRequest.ts +19 -0
- package/repos/effect/packages/platform-bun/src/BunMultipart.ts +54 -0
- package/repos/effect/packages/platform-bun/src/BunPath.ts +37 -0
- package/repos/effect/packages/platform-bun/src/BunRedis.ts +88 -0
- package/repos/effect/packages/platform-bun/src/BunRuntime.ts +52 -0
- package/repos/effect/packages/platform-bun/src/BunServices.ts +49 -0
- package/repos/effect/packages/platform-bun/src/BunSink.ts +8 -0
- package/repos/effect/packages/platform-bun/src/BunSocket.ts +54 -0
- package/repos/effect/packages/platform-bun/src/BunSocketServer.ts +8 -0
- package/repos/effect/packages/platform-bun/src/BunStdio.ts +22 -0
- package/repos/effect/packages/platform-bun/src/BunStream.ts +68 -0
- package/repos/effect/packages/platform-bun/src/BunTerminal.ts +32 -0
- package/repos/effect/packages/platform-bun/src/BunWorker.ts +92 -0
- package/repos/effect/packages/platform-bun/src/BunWorkerRunner.ts +113 -0
- package/repos/effect/packages/platform-bun/src/index.ts +115 -0
- package/repos/effect/packages/platform-bun/tsconfig.json +12 -0
- package/repos/effect/packages/platform-node/CHANGELOG.md +695 -0
- package/repos/effect/packages/platform-node/LICENSE +21 -0
- package/repos/effect/packages/platform-node/README.md +7 -0
- package/repos/effect/packages/platform-node/docgen.json +24 -0
- package/repos/effect/packages/platform-node/package.json +82 -0
- package/repos/effect/packages/platform-node/src/Mime.ts +25 -0
- package/repos/effect/packages/platform-node/src/NodeChildProcessSpawner.ts +6 -0
- package/repos/effect/packages/platform-node/src/NodeClusterHttp.ts +155 -0
- package/repos/effect/packages/platform-node/src/NodeClusterSocket.ts +176 -0
- package/repos/effect/packages/platform-node/src/NodeCrypto.ts +24 -0
- package/repos/effect/packages/platform-node/src/NodeFileSystem.ts +21 -0
- package/repos/effect/packages/platform-node/src/NodeHttpClient.ts +664 -0
- package/repos/effect/packages/platform-node/src/NodeHttpIncomingMessage.ts +141 -0
- package/repos/effect/packages/platform-node/src/NodeHttpPlatform.ts +70 -0
- package/repos/effect/packages/platform-node/src/NodeHttpServer.ts +646 -0
- package/repos/effect/packages/platform-node/src/NodeHttpServerRequest.ts +33 -0
- package/repos/effect/packages/platform-node/src/NodeMultipart.ts +183 -0
- package/repos/effect/packages/platform-node/src/NodePath.ts +40 -0
- package/repos/effect/packages/platform-node/src/NodeRedis.ts +92 -0
- package/repos/effect/packages/platform-node/src/NodeRuntime.ts +53 -0
- package/repos/effect/packages/platform-node/src/NodeServices.ts +50 -0
- package/repos/effect/packages/platform-node/src/NodeSink.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeSocket.ts +72 -0
- package/repos/effect/packages/platform-node/src/NodeSocketServer.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeStdio.ts +22 -0
- package/repos/effect/packages/platform-node/src/NodeStream.ts +8 -0
- package/repos/effect/packages/platform-node/src/NodeTerminal.ts +32 -0
- package/repos/effect/packages/platform-node/src/NodeWorker.ts +121 -0
- package/repos/effect/packages/platform-node/src/NodeWorkerRunner.ts +110 -0
- package/repos/effect/packages/platform-node/src/Undici.ts +29 -0
- package/repos/effect/packages/platform-node/src/index.ts +130 -0
- package/repos/effect/packages/platform-node/test/HttpApi.test.ts +1831 -0
- package/repos/effect/packages/platform-node/test/HttpStaticServer.test.ts +253 -0
- package/repos/effect/packages/platform-node/test/HttpStaticServerConditional.test.ts +296 -0
- package/repos/effect/packages/platform-node/test/NodeCrypto.test.ts +59 -0
- package/repos/effect/packages/platform-node/test/NodeHttpClient.test.ts +157 -0
- package/repos/effect/packages/platform-node/test/NodeHttpPlatform.test.ts +51 -0
- package/repos/effect/packages/platform-node/test/NodeHttpServer.test.ts +598 -0
- package/repos/effect/packages/platform-node/test/NodeRedis.test.ts +31 -0
- package/repos/effect/packages/platform-node/test/NodeSocket.test.ts +153 -0
- package/repos/effect/packages/platform-node/test/OpenApi.test.ts +1573 -0
- package/repos/effect/packages/platform-node/test/RpcServer.test.ts +213 -0
- package/repos/effect/packages/platform-node/test/__snapshots__/HttpApi.test.ts.snap +715 -0
- package/repos/effect/packages/platform-node/test/cluster/MessageStorageTest.ts +196 -0
- package/repos/effect/packages/platform-node/test/cluster/SocketRunner.test.ts +120 -0
- package/repos/effect/packages/platform-node/test/cluster/SqlMessageStorage.test.ts +222 -0
- package/repos/effect/packages/platform-node/test/cluster/SqlRunnerStorage.test.ts +101 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/conditional.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/custom/home.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/file.binx +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/guide/index.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/hello.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/index.html +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server/range.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/http-static-server-outside.txt +1 -0
- package/repos/effect/packages/platform-node/test/fixtures/mysql2-utils.ts +64 -0
- package/repos/effect/packages/platform-node/test/fixtures/pg-utils.ts +39 -0
- package/repos/effect/packages/platform-node/test/fixtures/rpc-e2e.ts +149 -0
- package/repos/effect/packages/platform-node/test/fixtures/rpc-schemas.ts +175 -0
- package/repos/effect/packages/platform-node/test/fixtures/text.txt +1 -0
- package/repos/effect/packages/platform-node/tsconfig.json +12 -0
- package/repos/effect/packages/platform-node/vitest.config.ts +6 -0
- package/repos/effect/packages/platform-node-shared/CHANGELOG.md +617 -0
- package/repos/effect/packages/platform-node-shared/LICENSE +21 -0
- package/repos/effect/packages/platform-node-shared/README.md +7 -0
- package/repos/effect/packages/platform-node-shared/docgen.json +38 -0
- package/repos/effect/packages/platform-node-shared/package.json +76 -0
- package/repos/effect/packages/platform-node-shared/src/NodeChildProcessSpawner.ts +713 -0
- package/repos/effect/packages/platform-node-shared/src/NodeClusterSocket.ts +70 -0
- package/repos/effect/packages/platform-node-shared/src/NodeCrypto.ts +60 -0
- package/repos/effect/packages/platform-node-shared/src/NodeFileSystem.ts +652 -0
- package/repos/effect/packages/platform-node-shared/src/NodePath.ts +80 -0
- package/repos/effect/packages/platform-node-shared/src/NodeRuntime.ts +59 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSink.ts +116 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSocket.ts +269 -0
- package/repos/effect/packages/platform-node-shared/src/NodeSocketServer.ts +301 -0
- package/repos/effect/packages/platform-node-shared/src/NodeStdio.ts +67 -0
- package/repos/effect/packages/platform-node-shared/src/NodeStream.ts +445 -0
- package/repos/effect/packages/platform-node-shared/src/NodeTerminal.ts +129 -0
- package/repos/effect/packages/platform-node-shared/src/index.ts +65 -0
- package/repos/effect/packages/platform-node-shared/src/internal/utils.ts +51 -0
- package/repos/effect/packages/platform-node-shared/test/NodeChildProcessSpawner.test.ts +1069 -0
- package/repos/effect/packages/platform-node-shared/test/NodeFileSystem.test.ts +214 -0
- package/repos/effect/packages/platform-node-shared/test/NodeSink.test.ts +153 -0
- package/repos/effect/packages/platform-node-shared/test/NodeStream.test.ts +173 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/no-permissions.sh +3 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/parent-exits-early.sh +31 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/bash/spawn-children.sh +32 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/SHOUTING +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/integer +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/nested/config +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/config/secret +1 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/helloworld.tar.gz +0 -0
- package/repos/effect/packages/platform-node-shared/test/fixtures/text.txt +1 -0
- package/repos/effect/packages/platform-node-shared/tsconfig.json +11 -0
- package/repos/effect/packages/platform-node-shared/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/clickhouse/CHANGELOG.md +681 -0
- package/repos/effect/packages/sql/clickhouse/LICENSE +21 -0
- package/repos/effect/packages/sql/clickhouse/README.md +7 -0
- package/repos/effect/packages/sql/clickhouse/docgen.json +24 -0
- package/repos/effect/packages/sql/clickhouse/package.json +72 -0
- package/repos/effect/packages/sql/clickhouse/src/ClickhouseClient.ts +546 -0
- package/repos/effect/packages/sql/clickhouse/src/ClickhouseMigrator.ts +51 -0
- package/repos/effect/packages/sql/clickhouse/src/index.ts +15 -0
- package/repos/effect/packages/sql/clickhouse/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/clickhouse/test/SqlErrorClassification.test.ts +75 -0
- package/repos/effect/packages/sql/clickhouse/tsconfig.json +12 -0
- package/repos/effect/packages/sql/clickhouse/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/d1/CHANGELOG.md +597 -0
- package/repos/effect/packages/sql/d1/LICENSE +21 -0
- package/repos/effect/packages/sql/d1/README.md +7 -0
- package/repos/effect/packages/sql/d1/docgen.json +24 -0
- package/repos/effect/packages/sql/d1/package.json +75 -0
- package/repos/effect/packages/sql/d1/src/D1Client.ts +249 -0
- package/repos/effect/packages/sql/d1/src/index.ts +10 -0
- package/repos/effect/packages/sql/d1/test/Client.test.ts +65 -0
- package/repos/effect/packages/sql/d1/test/Resolver.test.ts +176 -0
- package/repos/effect/packages/sql/d1/test/utils.ts +38 -0
- package/repos/effect/packages/sql/d1/tsconfig.json +8 -0
- package/repos/effect/packages/sql/d1/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/libsql/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/libsql/LICENSE +21 -0
- package/repos/effect/packages/sql/libsql/README.md +7 -0
- package/repos/effect/packages/sql/libsql/docgen.json +24 -0
- package/repos/effect/packages/sql/libsql/package.json +73 -0
- package/repos/effect/packages/sql/libsql/src/LibsqlClient.ts +381 -0
- package/repos/effect/packages/sql/libsql/src/LibsqlMigrator.ts +46 -0
- package/repos/effect/packages/sql/libsql/src/index.ts +15 -0
- package/repos/effect/packages/sql/libsql/test/Client.test.ts +106 -0
- package/repos/effect/packages/sql/libsql/test/Resolver.test.ts +177 -0
- package/repos/effect/packages/sql/libsql/test/util.ts +54 -0
- package/repos/effect/packages/sql/libsql/tsconfig.json +9 -0
- package/repos/effect/packages/sql/libsql/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/mssql/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/mssql/LICENSE +21 -0
- package/repos/effect/packages/sql/mssql/README.md +7 -0
- package/repos/effect/packages/sql/mssql/docgen.json +24 -0
- package/repos/effect/packages/sql/mssql/package.json +70 -0
- package/repos/effect/packages/sql/mssql/src/MssqlClient.ts +732 -0
- package/repos/effect/packages/sql/mssql/src/MssqlMigrator.ts +45 -0
- package/repos/effect/packages/sql/mssql/src/Parameter.ts +64 -0
- package/repos/effect/packages/sql/mssql/src/Procedure.ts +213 -0
- package/repos/effect/packages/sql/mssql/src/index.ts +32 -0
- package/repos/effect/packages/sql/mssql/test/Client.test.ts +91 -0
- package/repos/effect/packages/sql/mssql/test/SqlErrorClassification.test.ts +206 -0
- package/repos/effect/packages/sql/mssql/tsconfig.json +8 -0
- package/repos/effect/packages/sql/mssql/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/mysql2/CHANGELOG.md +603 -0
- package/repos/effect/packages/sql/mysql2/LICENSE +21 -0
- package/repos/effect/packages/sql/mysql2/README.md +7 -0
- package/repos/effect/packages/sql/mysql2/docgen.json +24 -0
- package/repos/effect/packages/sql/mysql2/package.json +71 -0
- package/repos/effect/packages/sql/mysql2/src/MysqlClient.ts +517 -0
- package/repos/effect/packages/sql/mysql2/src/MysqlMigrator.ts +102 -0
- package/repos/effect/packages/sql/mysql2/src/index.ts +15 -0
- package/repos/effect/packages/sql/mysql2/test/Client.test.ts +34 -0
- package/repos/effect/packages/sql/mysql2/test/KeyValueStore.test.ts +16 -0
- package/repos/effect/packages/sql/mysql2/test/Model.test.ts +227 -0
- package/repos/effect/packages/sql/mysql2/test/MysqlClient.test.ts +35 -0
- package/repos/effect/packages/sql/mysql2/test/Persistence.test.ts +22 -0
- package/repos/effect/packages/sql/mysql2/test/SqlErrorClassification.test.ts +133 -0
- package/repos/effect/packages/sql/mysql2/test/SqlEventLogServerUnencrypted.test.ts +7 -0
- package/repos/effect/packages/sql/mysql2/test/utils.ts +64 -0
- package/repos/effect/packages/sql/mysql2/tsconfig.json +9 -0
- package/repos/effect/packages/sql/mysql2/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/pg/CHANGELOG.md +3432 -0
- package/repos/effect/packages/sql/pg/LICENSE +21 -0
- package/repos/effect/packages/sql/pg/README.md +7 -0
- package/repos/effect/packages/sql/pg/docgen.json +24 -0
- package/repos/effect/packages/sql/pg/package.json +77 -0
- package/repos/effect/packages/sql/pg/src/PgClient.ts +947 -0
- package/repos/effect/packages/sql/pg/src/PgMigrator.ts +120 -0
- package/repos/effect/packages/sql/pg/src/index.ts +15 -0
- package/repos/effect/packages/sql/pg/test/Client.test.ts +373 -0
- package/repos/effect/packages/sql/pg/test/KeyValueStore.test.ts +16 -0
- package/repos/effect/packages/sql/pg/test/Persistence.test.ts +20 -0
- package/repos/effect/packages/sql/pg/test/SqlErrorClassification.test.ts +81 -0
- package/repos/effect/packages/sql/pg/test/SqlEventLogServerUnencrypted.test.ts +7 -0
- package/repos/effect/packages/sql/pg/test/TransactionAcquire.test.ts +52 -0
- package/repos/effect/packages/sql/pg/test/utils.ts +49 -0
- package/repos/effect/packages/sql/pg/tsconfig.json +9 -0
- package/repos/effect/packages/sql/pg/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/pglite/CHANGELOG.md +198 -0
- package/repos/effect/packages/sql/pglite/LICENSE +21 -0
- package/repos/effect/packages/sql/pglite/README.md +7 -0
- package/repos/effect/packages/sql/pglite/docgen.json +24 -0
- package/repos/effect/packages/sql/pglite/package.json +74 -0
- package/repos/effect/packages/sql/pglite/src/PgliteClient.ts +503 -0
- package/repos/effect/packages/sql/pglite/src/PgliteMigrator.ts +44 -0
- package/repos/effect/packages/sql/pglite/src/index.ts +15 -0
- package/repos/effect/packages/sql/pglite/test/Client.test.ts +149 -0
- package/repos/effect/packages/sql/pglite/test/Migrator.test.ts +45 -0
- package/repos/effect/packages/sql/pglite/test/SqlErrorClassification.test.ts +56 -0
- package/repos/effect/packages/sql/pglite/test/Transaction.test.ts +62 -0
- package/repos/effect/packages/sql/pglite/tsconfig.json +8 -0
- package/repos/effect/packages/sql/pglite/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-bun/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-bun/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-bun/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-bun/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-bun/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-bun/src/SqliteClient.ts +262 -0
- package/repos/effect/packages/sql/sqlite-bun/src/SqliteMigrator.ts +90 -0
- package/repos/effect/packages/sql/sqlite-bun/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-bun/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-bun/tsconfig.json +11 -0
- package/repos/effect/packages/sql/sqlite-bun/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-do/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-do/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-do/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-do/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-do/package.json +68 -0
- package/repos/effect/packages/sql/sqlite-do/src/SqliteClient.ts +249 -0
- package/repos/effect/packages/sql/sqlite-do/src/SqliteMigrator.ts +45 -0
- package/repos/effect/packages/sql/sqlite-do/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-do/test/Client.test.ts +24 -0
- package/repos/effect/packages/sql/sqlite-do/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-do/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-node/CHANGELOG.md +3415 -0
- package/repos/effect/packages/sql/sqlite-node/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-node/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-node/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-node/package.json +72 -0
- package/repos/effect/packages/sql/sqlite-node/src/SqliteClient.ts +312 -0
- package/repos/effect/packages/sql/sqlite-node/src/SqliteMigrator.ts +90 -0
- package/repos/effect/packages/sql/sqlite-node/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-node/test/Client.test.ts +75 -0
- package/repos/effect/packages/sql/sqlite-node/test/KeyValueStore.test.ts +29 -0
- package/repos/effect/packages/sql/sqlite-node/test/Persistence.test.ts +109 -0
- package/repos/effect/packages/sql/sqlite-node/test/Resolver.test.ts +183 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventJournal.test.ts +84 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventLogServerEncrypted.test.ts +249 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqlEventLogServerUnencrypted.test.ts +110 -0
- package/repos/effect/packages/sql/sqlite-node/test/SqliteMigrator.test.ts +48 -0
- package/repos/effect/packages/sql/sqlite-node/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-node/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-react-native/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-react-native/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-react-native/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-react-native/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-react-native/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/SqliteClient.ts +354 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/SqliteMigrator.ts +55 -0
- package/repos/effect/packages/sql/sqlite-react-native/src/index.ts +15 -0
- package/repos/effect/packages/sql/sqlite-react-native/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-react-native/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-react-native/vitest.config.ts +6 -0
- package/repos/effect/packages/sql/sqlite-wasm/CHANGELOG.md +601 -0
- package/repos/effect/packages/sql/sqlite-wasm/LICENSE +21 -0
- package/repos/effect/packages/sql/sqlite-wasm/README.md +7 -0
- package/repos/effect/packages/sql/sqlite-wasm/docgen.json +24 -0
- package/repos/effect/packages/sql/sqlite-wasm/package.json +69 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/OpfsWorker.ts +118 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/SqliteClient.ts +551 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/SqliteMigrator.ts +55 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/index.ts +14 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/internal/opfsWorker.ts +7 -0
- package/repos/effect/packages/sql/sqlite-wasm/src/sqlite-wasm.d.ts +47 -0
- package/repos/effect/packages/sql/sqlite-wasm/test/Client.test.ts +6 -0
- package/repos/effect/packages/sql/sqlite-wasm/tsconfig.json +8 -0
- package/repos/effect/packages/sql/sqlite-wasm/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/ai-codegen/codegen.schema.json +92 -0
- package/repos/effect/packages/tools/ai-codegen/docgen.json +4 -0
- package/repos/effect/packages/tools/ai-codegen/package.json +61 -0
- package/repos/effect/packages/tools/ai-codegen/src/Config.ts +292 -0
- package/repos/effect/packages/tools/ai-codegen/src/Discovery.ts +197 -0
- package/repos/effect/packages/tools/ai-codegen/src/Generator.ts +183 -0
- package/repos/effect/packages/tools/ai-codegen/src/Glob.ts +56 -0
- package/repos/effect/packages/tools/ai-codegen/src/PostProcess.ts +157 -0
- package/repos/effect/packages/tools/ai-codegen/src/SpecFetcher.ts +154 -0
- package/repos/effect/packages/tools/ai-codegen/src/bin.ts +10 -0
- package/repos/effect/packages/tools/ai-codegen/src/main.ts +237 -0
- package/repos/effect/packages/tools/ai-codegen/tsconfig.json +15 -0
- package/repos/effect/packages/tools/ai-docgen/docgen.json +4 -0
- package/repos/effect/packages/tools/ai-docgen/package.json +60 -0
- package/repos/effect/packages/tools/ai-docgen/src/Glob.ts +48 -0
- package/repos/effect/packages/tools/ai-docgen/src/main.ts +186 -0
- package/repos/effect/packages/tools/ai-docgen/tsconfig.json +14 -0
- package/repos/effect/packages/tools/bundle/docgen.json +4 -0
- package/repos/effect/packages/tools/bundle/fixtures/basic.ts +3 -0
- package/repos/effect/packages/tools/bundle/fixtures/batching.ts +25 -0
- package/repos/effect/packages/tools/bundle/fixtures/brand.ts +5 -0
- package/repos/effect/packages/tools/bundle/fixtures/cache.ts +10 -0
- package/repos/effect/packages/tools/bundle/fixtures/config.ts +13 -0
- package/repos/effect/packages/tools/bundle/fixtures/differ.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/http-client.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/logger.ts +5 -0
- package/repos/effect/packages/tools/bundle/fixtures/metric.ts +13 -0
- package/repos/effect/packages/tools/bundle/fixtures/optic.ts +6 -0
- package/repos/effect/packages/tools/bundle/fixtures/pubsub.ts +22 -0
- package/repos/effect/packages/tools/bundle/fixtures/queue.ts +18 -0
- package/repos/effect/packages/tools/bundle/fixtures/schedule.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-fromJsonSchemaDocument.ts +16 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-representation-roundtrip.ts +16 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-string-transformation.ts +20 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-string.ts +8 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-template-literal.ts +8 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toArbitraryLazy.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toCodeDocument.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toCodecJson.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toEquivalence.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toFormatter.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toJsonSchemaDocument.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema-toRepresentation.ts +9 -0
- package/repos/effect/packages/tools/bundle/fixtures/schema.ts +12 -0
- package/repos/effect/packages/tools/bundle/fixtures/stm.ts +21 -0
- package/repos/effect/packages/tools/bundle/fixtures/stream.ts +7 -0
- package/repos/effect/packages/tools/bundle/package.json +52 -0
- package/repos/effect/packages/tools/bundle/src/Cli.ts +104 -0
- package/repos/effect/packages/tools/bundle/src/Fixtures.ts +51 -0
- package/repos/effect/packages/tools/bundle/src/Plugins.ts +131 -0
- package/repos/effect/packages/tools/bundle/src/Reporter.ts +200 -0
- package/repos/effect/packages/tools/bundle/src/Rollup.ts +179 -0
- package/repos/effect/packages/tools/bundle/src/bin.ts +23 -0
- package/repos/effect/packages/tools/bundle/tsconfig.fixtures.json +13 -0
- package/repos/effect/packages/tools/bundle/tsconfig.json +9 -0
- package/repos/effect/packages/tools/bundle/tsconfig.src.json +13 -0
- package/repos/effect/packages/tools/jsdocs/docgen.json +4 -0
- package/repos/effect/packages/tools/jsdocs/package.json +64 -0
- package/repos/effect/packages/tools/jsdocs/src/Jsdocs.ts +3303 -0
- package/repos/effect/packages/tools/jsdocs/src/bin.ts +23 -0
- package/repos/effect/packages/tools/jsdocs/test/jsdocs.test.ts +979 -0
- package/repos/effect/packages/tools/jsdocs/tsconfig.json +8 -0
- package/repos/effect/packages/tools/jsdocs/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/openapi-generator/CHANGELOG.md +691 -0
- package/repos/effect/packages/tools/openapi-generator/LICENSE +21 -0
- package/repos/effect/packages/tools/openapi-generator/docgen.json +4 -0
- package/repos/effect/packages/tools/openapi-generator/package.json +78 -0
- package/repos/effect/packages/tools/openapi-generator/src/HttpApiTransformer.ts +552 -0
- package/repos/effect/packages/tools/openapi-generator/src/JsonSchemaGenerator.ts +319 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiGenerator.ts +1201 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiPatch.ts +539 -0
- package/repos/effect/packages/tools/openapi-generator/src/OpenApiTransformer.ts +1019 -0
- package/repos/effect/packages/tools/openapi-generator/src/ParsedOperation.ts +277 -0
- package/repos/effect/packages/tools/openapi-generator/src/Utils.ts +111 -0
- package/repos/effect/packages/tools/openapi-generator/src/bin.ts +10 -0
- package/repos/effect/packages/tools/openapi-generator/src/main.ts +116 -0
- package/repos/effect/packages/tools/openapi-generator/test/JsonSchemaGenerator.test.ts +173 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiGenerator.test.ts +2130 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiGeneratorCli.test.ts +147 -0
- package/repos/effect/packages/tools/openapi-generator/test/OpenApiPatch.test.ts +380 -0
- package/repos/effect/packages/tools/openapi-generator/test/Utils.test.ts +33 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/cli-basic-spec.json +35 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/cli-warning-spec.json +57 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/invalid-op.json +7 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/missing-path.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/missing-value.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-add.json +8 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-multiple.json +17 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-patch.yaml +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-remove.json +6 -0
- package/repos/effect/packages/tools/openapi-generator/test/fixtures/patches/valid-replace.json +7 -0
- package/repos/effect/packages/tools/openapi-generator/tsconfig.json +9 -0
- package/repos/effect/packages/tools/openapi-generator/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/oxc/docgen.json +4 -0
- package/repos/effect/packages/tools/oxc/oxlintrc.json +83 -0
- package/repos/effect/packages/tools/oxc/package.json +72 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/index.ts +18 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/jsdocs.ts +108 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-bigint-literals.ts +25 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-import-from-barrel-package.ts +144 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-js-extension-imports.ts +73 -0
- package/repos/effect/packages/tools/oxc/src/oxlint/rules/no-opaque-instance-fields.ts +92 -0
- package/repos/effect/packages/tools/oxc/test/jsdocs.test.ts +75 -0
- package/repos/effect/packages/tools/oxc/test/no-import-from-barrel-package.test.ts +182 -0
- package/repos/effect/packages/tools/oxc/test/no-js-extension-imports.test.ts +120 -0
- package/repos/effect/packages/tools/oxc/test/no-opaque-instance-fields.test.ts +276 -0
- package/repos/effect/packages/tools/oxc/test/utils.ts +61 -0
- package/repos/effect/packages/tools/oxc/tsconfig.json +8 -0
- package/repos/effect/packages/tools/oxc/vitest.config.ts +6 -0
- package/repos/effect/packages/tools/utils/docgen.json +4 -0
- package/repos/effect/packages/tools/utils/package.json +59 -0
- package/repos/effect/packages/tools/utils/src/Codegen.ts +214 -0
- package/repos/effect/packages/tools/utils/src/Glob.ts +61 -0
- package/repos/effect/packages/tools/utils/src/bin.ts +16 -0
- package/repos/effect/packages/tools/utils/src/commands/codegen.ts +44 -0
- package/repos/effect/packages/tools/utils/tsconfig.json +9 -0
- package/repos/effect/packages/vitest/CHANGELOG.md +601 -0
- package/repos/effect/packages/vitest/LICENSE +21 -0
- package/repos/effect/packages/vitest/README.md +320 -0
- package/repos/effect/packages/vitest/docgen.json +24 -0
- package/repos/effect/packages/vitest/package.json +60 -0
- package/repos/effect/packages/vitest/src/index.ts +259 -0
- package/repos/effect/packages/vitest/src/internal/internal.ts +374 -0
- package/repos/effect/packages/vitest/src/utils.ts +321 -0
- package/repos/effect/packages/vitest/test/index.test.ts +222 -0
- package/repos/effect/packages/vitest/test/isolation.test.ts +105 -0
- package/repos/effect/packages/vitest/test/nested-isolation.test.ts +212 -0
- package/repos/effect/packages/vitest/tsconfig.json +11 -0
- package/repos/effect/packages/vitest/typetest/index.tst.ts +56 -0
- package/repos/effect/packages/vitest/vitest.config.ts +6 -0
- package/repos/effect/patches/@changesets__assemble-release-plan.patch +26 -0
- package/repos/effect/patches/@changesets__get-github-info.patch +44 -0
- package/repos/effect/pnpm-lock.yaml +13483 -0
- package/repos/effect/pnpm-workspace.yaml +10 -0
- package/repos/effect/scripts/bundle-compare.sh +42 -0
- package/repos/effect/scripts/check-cookbook-schedule.ts +390 -0
- package/repos/effect/scripts/circular.mjs +26 -0
- package/repos/effect/scripts/clean.mjs +19 -0
- package/repos/effect/scripts/codemod.mjs +22 -0
- package/repos/effect/scripts/codemods/jsdoc.ts +79 -0
- package/repos/effect/scripts/docs.mjs +64 -0
- package/repos/effect/scripts/package-scalar.mjs +14 -0
- package/repos/effect/scripts/package-swagger.mjs +23 -0
- package/repos/effect/scripts/package.json +22 -0
- package/repos/effect/scripts/tsconfig.json +18 -0
- package/repos/effect/scripts/version.mjs +9 -0
- package/repos/effect/scripts/version.template.txt +2 -0
- package/repos/effect/scripts/worktree-setup.sh +27 -0
- package/repos/effect/stats.txt +30 -0
- package/repos/effect/tsconfig.base.json +46 -0
- package/repos/effect/tsconfig.json +128 -0
- package/repos/effect/tsconfig.packages.json +39 -0
- package/repos/effect/tstyche.json +7 -0
- package/repos/effect/vitest.config.ts +31 -0
- package/repos/effect/vitest.setup.ts +4 -0
- package/repos/effect/vitest.shared.ts +61 -0
- package/repos/effect.subtree.json +16 -0
|
@@ -0,0 +1,3852 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds interactive terminal prompts for CLI applications.
|
|
3
|
+
*
|
|
4
|
+
* A `Prompt<A>` describes a small terminal UI that renders frames, reads
|
|
5
|
+
* keyboard input, validates responses, and eventually produces an `A`. Prompts
|
|
6
|
+
* can ask for simple values, selections, lists, files, hidden text, or custom
|
|
7
|
+
* interactions. This module includes prompt constructors, tools for combining
|
|
8
|
+
* and transforming prompt output, and support for running prompts through the
|
|
9
|
+
* `Terminal` service.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
12
|
+
*/
|
|
13
|
+
import * as Arr from "../../Array.ts"
|
|
14
|
+
import type { NoSuchElementError } from "../../Cause.ts"
|
|
15
|
+
import type * as Cause from "../../Cause.ts"
|
|
16
|
+
import * as Data from "../../Data.ts"
|
|
17
|
+
import * as Effect from "../../Effect.ts"
|
|
18
|
+
import * as Effectable from "../../Effectable.ts"
|
|
19
|
+
import * as FileSystem from "../../FileSystem.ts"
|
|
20
|
+
import { dual, pipe } from "../../Function.ts"
|
|
21
|
+
import * as EffectNumber from "../../Number.ts"
|
|
22
|
+
import * as Option from "../../Option.ts"
|
|
23
|
+
import * as Path from "../../Path.ts"
|
|
24
|
+
import * as Predicate from "../../Predicate.ts"
|
|
25
|
+
import * as Queue from "../../Queue.ts"
|
|
26
|
+
import * as Redacted from "../../Redacted.ts"
|
|
27
|
+
import * as Terminal from "../../Terminal.ts"
|
|
28
|
+
import type { Covariant } from "../../Types.ts"
|
|
29
|
+
import * as Ansi from "./internal/ansi.ts"
|
|
30
|
+
import type * as Primitive from "./Primitive.ts"
|
|
31
|
+
|
|
32
|
+
const TypeId = "~effect/cli/Prompt"
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Represents an interactive terminal prompt that produces an `Output` value.
|
|
36
|
+
*
|
|
37
|
+
* **Details**
|
|
38
|
+
*
|
|
39
|
+
* A `Prompt` is an `Effect` that may fail with `Terminal.QuitError` and
|
|
40
|
+
* requires the prompt environment needed to render frames, read input, and
|
|
41
|
+
* access files or paths when a prompt uses them.
|
|
42
|
+
*
|
|
43
|
+
* @category models
|
|
44
|
+
* @since 4.0.0
|
|
45
|
+
*/
|
|
46
|
+
export interface Prompt<Output> extends Effect.Effect<Output, Terminal.QuitError, Environment> {
|
|
47
|
+
readonly [TypeId]: {
|
|
48
|
+
readonly _Output: Covariant<Output>
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns `true` if the provided value is a `Prompt`.
|
|
54
|
+
*
|
|
55
|
+
* @category guards
|
|
56
|
+
* @since 4.0.0
|
|
57
|
+
*/
|
|
58
|
+
export const isPrompt = (u: unknown): u is Prompt<unknown> => Predicate.hasProperty(u, TypeId)
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Represents the services available to a custom `Prompt`.
|
|
62
|
+
*
|
|
63
|
+
* @category models
|
|
64
|
+
* @since 4.0.0
|
|
65
|
+
*/
|
|
66
|
+
export type Environment = FileSystem.FileSystem | Path.Path | Terminal.Terminal
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Represents the action that should be taken by a `Prompt` based upon user
|
|
70
|
+
* input or an external event received during the current frame.
|
|
71
|
+
*
|
|
72
|
+
* @category models
|
|
73
|
+
* @since 4.0.0
|
|
74
|
+
*/
|
|
75
|
+
export type Action<State, Output> = Data.TaggedEnum<{
|
|
76
|
+
readonly Beep: {}
|
|
77
|
+
readonly NextFrame: { readonly state: State }
|
|
78
|
+
readonly Submit: { readonly value: Output }
|
|
79
|
+
}>
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Type-level definition for the tagged `Prompt.Action` variants.
|
|
83
|
+
*
|
|
84
|
+
* **Details**
|
|
85
|
+
*
|
|
86
|
+
* It connects the action state and output type parameters to the `Beep`,
|
|
87
|
+
* `NextFrame`, and `Submit` action cases.
|
|
88
|
+
*
|
|
89
|
+
* @category models
|
|
90
|
+
* @since 4.0.0
|
|
91
|
+
*/
|
|
92
|
+
export interface ActionDefinition extends Data.TaggedEnum.WithGenerics<2> {
|
|
93
|
+
readonly taggedEnum: Action<this["A"], this["B"]>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Represents the input that should be processed by a `Prompt` based upon user
|
|
98
|
+
* input or an external event received during the current frame.
|
|
99
|
+
*
|
|
100
|
+
* @category models
|
|
101
|
+
* @since 4.0.0
|
|
102
|
+
*/
|
|
103
|
+
export type ProcessInput<A> = Data.TaggedEnum<{
|
|
104
|
+
readonly Input: { readonly input: Terminal.UserInput }
|
|
105
|
+
readonly Event: { readonly value: A }
|
|
106
|
+
}>
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Represents the set of handlers used by a `Prompt`.
|
|
110
|
+
*
|
|
111
|
+
* **Details**
|
|
112
|
+
*
|
|
113
|
+
* The handlers render the current frame, process user input into the next
|
|
114
|
+
* `Prompt.Action`, and clear the terminal screen before the next frame.
|
|
115
|
+
*
|
|
116
|
+
* @category models
|
|
117
|
+
* @since 4.0.0
|
|
118
|
+
*/
|
|
119
|
+
export interface Handlers<State, Output, Input = Terminal.UserInput> {
|
|
120
|
+
/**
|
|
121
|
+
* A function that is called to render the current frame of the `Prompt`.
|
|
122
|
+
*/
|
|
123
|
+
readonly render: (
|
|
124
|
+
state: State,
|
|
125
|
+
action: Action<State, Output>
|
|
126
|
+
) => Effect.Effect<string, never, Environment>
|
|
127
|
+
/**
|
|
128
|
+
* A function that is called to process user input and determine the next
|
|
129
|
+
* `Prompt.Action` that should be taken.
|
|
130
|
+
*/
|
|
131
|
+
readonly process: (
|
|
132
|
+
input: Input,
|
|
133
|
+
state: State
|
|
134
|
+
) => Effect.Effect<Action<State, Output>, never, Environment>
|
|
135
|
+
/**
|
|
136
|
+
* A function that is called to clear the terminal screen before rendering
|
|
137
|
+
* the next frame of the `Prompt`.
|
|
138
|
+
*/
|
|
139
|
+
readonly clear: (
|
|
140
|
+
state: State,
|
|
141
|
+
action: Action<State, Output>
|
|
142
|
+
) => Effect.Effect<string, never, Environment>
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Options for a confirmation prompt that asks the user to choose a boolean
|
|
147
|
+
* yes/no value.
|
|
148
|
+
*
|
|
149
|
+
* @category options
|
|
150
|
+
* @since 4.0.0
|
|
151
|
+
*/
|
|
152
|
+
export interface ConfirmOptions {
|
|
153
|
+
/**
|
|
154
|
+
* The message to display in the prompt.
|
|
155
|
+
*/
|
|
156
|
+
readonly message: string
|
|
157
|
+
/**
|
|
158
|
+
* The initial value of the confirm prompt (defaults to `false`).
|
|
159
|
+
*/
|
|
160
|
+
readonly initial?: boolean
|
|
161
|
+
/**
|
|
162
|
+
* The label to display after a user has responded to the prompt.
|
|
163
|
+
*/
|
|
164
|
+
readonly label?: {
|
|
165
|
+
/**
|
|
166
|
+
* The label used if the prompt is confirmed (defaults to `"yes"`).
|
|
167
|
+
*/
|
|
168
|
+
readonly confirm: string
|
|
169
|
+
/**
|
|
170
|
+
* The label used if the prompt is not confirmed (defaults to `"no"`).
|
|
171
|
+
*/
|
|
172
|
+
readonly deny: string
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The placeholder to display when a user is responding to the prompt.
|
|
176
|
+
*/
|
|
177
|
+
readonly placeholder?: {
|
|
178
|
+
/**
|
|
179
|
+
* The placeholder to use if the `initial` value of the prompt is `true`
|
|
180
|
+
* (defaults to `"(Y/n)"`).
|
|
181
|
+
*/
|
|
182
|
+
readonly defaultConfirm?: string
|
|
183
|
+
/**
|
|
184
|
+
* The placeholder to use if the `initial` value of the prompt is `false`
|
|
185
|
+
* (defaults to `"(y/N)"`).
|
|
186
|
+
*/
|
|
187
|
+
readonly defaultDeny?: string
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Options for a date prompt, including the displayed message, initial value,
|
|
193
|
+
* format mask, validation, and locale labels.
|
|
194
|
+
*
|
|
195
|
+
* @category options
|
|
196
|
+
* @since 4.0.0
|
|
197
|
+
*/
|
|
198
|
+
export interface DateOptions {
|
|
199
|
+
/**
|
|
200
|
+
* The message to display in the prompt.
|
|
201
|
+
*/
|
|
202
|
+
readonly message: string
|
|
203
|
+
/**
|
|
204
|
+
* The initial date value to display in the prompt (defaults to the current
|
|
205
|
+
* date).
|
|
206
|
+
*/
|
|
207
|
+
readonly initial?: globalThis.Date
|
|
208
|
+
/**
|
|
209
|
+
* The format mask of the date (defaults to `YYYY-MM-DD HH:mm:ss`).
|
|
210
|
+
*/
|
|
211
|
+
readonly dateMask?: string
|
|
212
|
+
/**
|
|
213
|
+
* An effectful function that can be used to validate the value entered into
|
|
214
|
+
* the prompt before final submission.
|
|
215
|
+
*/
|
|
216
|
+
readonly validate?: (value: globalThis.Date) => Effect.Effect<globalThis.Date, string>
|
|
217
|
+
/**
|
|
218
|
+
* Custom locales that can be used in place of the defaults.
|
|
219
|
+
*/
|
|
220
|
+
readonly locales?: {
|
|
221
|
+
/**
|
|
222
|
+
* The full names of each month of the year.
|
|
223
|
+
*/
|
|
224
|
+
readonly months: [
|
|
225
|
+
string,
|
|
226
|
+
string,
|
|
227
|
+
string,
|
|
228
|
+
string,
|
|
229
|
+
string,
|
|
230
|
+
string,
|
|
231
|
+
string,
|
|
232
|
+
string,
|
|
233
|
+
string,
|
|
234
|
+
string,
|
|
235
|
+
string,
|
|
236
|
+
string
|
|
237
|
+
]
|
|
238
|
+
/**
|
|
239
|
+
* The short names of each month of the year.
|
|
240
|
+
*/
|
|
241
|
+
readonly monthsShort: [
|
|
242
|
+
string,
|
|
243
|
+
string,
|
|
244
|
+
string,
|
|
245
|
+
string,
|
|
246
|
+
string,
|
|
247
|
+
string,
|
|
248
|
+
string,
|
|
249
|
+
string,
|
|
250
|
+
string,
|
|
251
|
+
string,
|
|
252
|
+
string,
|
|
253
|
+
string
|
|
254
|
+
]
|
|
255
|
+
/**
|
|
256
|
+
* The full names of each day of the week.
|
|
257
|
+
*/
|
|
258
|
+
readonly weekdays: [string, string, string, string, string, string, string]
|
|
259
|
+
/**
|
|
260
|
+
* The short names of each day of the week.
|
|
261
|
+
*/
|
|
262
|
+
readonly weekdaysShort: [string, string, string, string, string, string, string]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Options for an integer prompt, including bounds, keyboard step sizes, and
|
|
268
|
+
* additional validation.
|
|
269
|
+
*
|
|
270
|
+
* @category options
|
|
271
|
+
* @since 4.0.0
|
|
272
|
+
*/
|
|
273
|
+
export interface IntegerOptions {
|
|
274
|
+
/**
|
|
275
|
+
* The message to display in the prompt.
|
|
276
|
+
*/
|
|
277
|
+
readonly message: string
|
|
278
|
+
/**
|
|
279
|
+
* The default value of the integer prompt.
|
|
280
|
+
*/
|
|
281
|
+
readonly default?: number
|
|
282
|
+
/**
|
|
283
|
+
* The minimum value that can be entered by the user (defaults to `-Infinity`).
|
|
284
|
+
*/
|
|
285
|
+
readonly min?: number
|
|
286
|
+
/**
|
|
287
|
+
* The maximum value that can be entered by the user (defaults to `Infinity`).
|
|
288
|
+
*/
|
|
289
|
+
readonly max?: number
|
|
290
|
+
/**
|
|
291
|
+
* The value that will be used to increment the prompt value when using the
|
|
292
|
+
* up arrow key (defaults to `1`).
|
|
293
|
+
*/
|
|
294
|
+
readonly incrementBy?: number
|
|
295
|
+
/**
|
|
296
|
+
* The value that will be used to decrement the prompt value when using the
|
|
297
|
+
* down arrow key (defaults to `1`).
|
|
298
|
+
*/
|
|
299
|
+
readonly decrementBy?: number
|
|
300
|
+
/**
|
|
301
|
+
* An effectful function that can be used to validate the value entered into
|
|
302
|
+
* the prompt before final submission.
|
|
303
|
+
*/
|
|
304
|
+
readonly validate?: (value: number) => Effect.Effect<number, string>
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Options for a floating-point number prompt.
|
|
309
|
+
*
|
|
310
|
+
* **Details**
|
|
311
|
+
*
|
|
312
|
+
* In addition to the numeric bounds and step settings from `IntegerOptions`,
|
|
313
|
+
* the prompt can be configured with a display precision.
|
|
314
|
+
*
|
|
315
|
+
* @category options
|
|
316
|
+
* @since 4.0.0
|
|
317
|
+
*/
|
|
318
|
+
export interface FloatOptions extends IntegerOptions {
|
|
319
|
+
/**
|
|
320
|
+
* The precision to use for the floating point value (defaults to `2`).
|
|
321
|
+
*/
|
|
322
|
+
readonly precision?: number
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Options for a text prompt that returns a list of strings by splitting the
|
|
327
|
+
* input on a delimiter.
|
|
328
|
+
*
|
|
329
|
+
* @category options
|
|
330
|
+
* @since 4.0.0
|
|
331
|
+
*/
|
|
332
|
+
export interface ListOptions extends TextOptions {
|
|
333
|
+
/**
|
|
334
|
+
* The delimiter that separates list entries.
|
|
335
|
+
*/
|
|
336
|
+
readonly delimiter?: string
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Options for a file-system selection prompt.
|
|
341
|
+
*
|
|
342
|
+
* **Details**
|
|
343
|
+
*
|
|
344
|
+
* They control which path type can be selected, the starting directory, paging,
|
|
345
|
+
* and filtering of displayed entries.
|
|
346
|
+
*
|
|
347
|
+
* @category options
|
|
348
|
+
* @since 4.0.0
|
|
349
|
+
*/
|
|
350
|
+
export interface FileOptions {
|
|
351
|
+
/**
|
|
352
|
+
* The path type that will be selected, defaulting to `"file"`.
|
|
353
|
+
*/
|
|
354
|
+
readonly type?: Primitive.PathType
|
|
355
|
+
/**
|
|
356
|
+
* The message to display in the prompt, defaulting to `"Choose a file"`.
|
|
357
|
+
*/
|
|
358
|
+
readonly message?: string
|
|
359
|
+
/**
|
|
360
|
+
* Where the user will initially be prompted to select files from, defaulting
|
|
361
|
+
* to the current working directory.
|
|
362
|
+
*/
|
|
363
|
+
readonly startingPath?: string
|
|
364
|
+
/**
|
|
365
|
+
* The default path to select when the prompt is first displayed.
|
|
366
|
+
*/
|
|
367
|
+
readonly default?: string
|
|
368
|
+
/**
|
|
369
|
+
* The number of choices to display at one time, defaulting to `10`.
|
|
370
|
+
*/
|
|
371
|
+
readonly maxPerPage?: number
|
|
372
|
+
/**
|
|
373
|
+
* A predicate or effect that keeps a file in the prompt when it returns
|
|
374
|
+
* `true`, defaulting to returning all files.
|
|
375
|
+
*/
|
|
376
|
+
readonly filter?: (file: string) => boolean | Effect.Effect<boolean, never, Environment>
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Options for a prompt that asks the user to select one value from a list of
|
|
381
|
+
* choices.
|
|
382
|
+
*
|
|
383
|
+
* @category options
|
|
384
|
+
* @since 4.0.0
|
|
385
|
+
*/
|
|
386
|
+
export interface SelectOptions<A> {
|
|
387
|
+
/**
|
|
388
|
+
* The message to display in the prompt.
|
|
389
|
+
*/
|
|
390
|
+
readonly message: string
|
|
391
|
+
/**
|
|
392
|
+
* The choices to display to the user.
|
|
393
|
+
*/
|
|
394
|
+
readonly choices: ReadonlyArray<SelectChoice<A>>
|
|
395
|
+
/**
|
|
396
|
+
* The number of choices to display at one time (defaults to `10`).
|
|
397
|
+
*/
|
|
398
|
+
readonly maxPerPage?: number
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Options for an autocomplete prompt that lets the user filter selectable
|
|
403
|
+
* choices by typing.
|
|
404
|
+
*
|
|
405
|
+
* @category options
|
|
406
|
+
* @since 4.0.0
|
|
407
|
+
*/
|
|
408
|
+
export interface AutoCompleteOptions<A> extends SelectOptions<A> {
|
|
409
|
+
/**
|
|
410
|
+
* The label used for the filter display (defaults to "filter").
|
|
411
|
+
*/
|
|
412
|
+
readonly filterLabel?: string
|
|
413
|
+
/**
|
|
414
|
+
* The placeholder shown when the filter is empty (defaults to "type to filter").
|
|
415
|
+
*/
|
|
416
|
+
readonly filterPlaceholder?: string
|
|
417
|
+
/**
|
|
418
|
+
* The message displayed when no choices match (defaults to "No matches").
|
|
419
|
+
*/
|
|
420
|
+
readonly emptyMessage?: string
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Options for a multi-select prompt, including bulk-selection labels and
|
|
425
|
+
* minimum or maximum selection counts.
|
|
426
|
+
*
|
|
427
|
+
* @category options
|
|
428
|
+
* @since 4.0.0
|
|
429
|
+
*/
|
|
430
|
+
export interface MultiSelectOptions {
|
|
431
|
+
/**
|
|
432
|
+
* Text for the "Select All" option (defaults to "Select All").
|
|
433
|
+
*/
|
|
434
|
+
readonly selectAll?: string
|
|
435
|
+
/**
|
|
436
|
+
* Text for the "Select None" option (defaults to "Select None").
|
|
437
|
+
*/
|
|
438
|
+
readonly selectNone?: string
|
|
439
|
+
/**
|
|
440
|
+
* Text for the "Inverse Selection" option (defaults to "Inverse Selection").
|
|
441
|
+
*/
|
|
442
|
+
readonly inverseSelection?: string
|
|
443
|
+
/**
|
|
444
|
+
* The minimum number of choices that must be selected.
|
|
445
|
+
*/
|
|
446
|
+
readonly min?: number
|
|
447
|
+
/**
|
|
448
|
+
* The maximum number of choices that can be selected.
|
|
449
|
+
*/
|
|
450
|
+
readonly max?: number
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Represents one choice displayed by select, autocomplete, and multi-select
|
|
455
|
+
* prompts.
|
|
456
|
+
*
|
|
457
|
+
* @category models
|
|
458
|
+
* @since 4.0.0
|
|
459
|
+
*/
|
|
460
|
+
export interface SelectChoice<A> {
|
|
461
|
+
/**
|
|
462
|
+
* The name of the select option that is displayed to the user.
|
|
463
|
+
*/
|
|
464
|
+
readonly title: string
|
|
465
|
+
/**
|
|
466
|
+
* The underlying value of the select option.
|
|
467
|
+
*/
|
|
468
|
+
readonly value: A
|
|
469
|
+
/**
|
|
470
|
+
* An optional description for the select option which will be displayed
|
|
471
|
+
* to the user.
|
|
472
|
+
*/
|
|
473
|
+
readonly description?: string
|
|
474
|
+
/**
|
|
475
|
+
* Whether or not this select option is disabled.
|
|
476
|
+
*/
|
|
477
|
+
readonly disabled?: boolean
|
|
478
|
+
/**
|
|
479
|
+
* Whether this option should be selected by default (only used by MultiSelect).
|
|
480
|
+
*/
|
|
481
|
+
readonly selected?: boolean
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Options for text-entry prompts, including the displayed message, default
|
|
486
|
+
* text, and effectful validation before submission.
|
|
487
|
+
*
|
|
488
|
+
* @category options
|
|
489
|
+
* @since 4.0.0
|
|
490
|
+
*/
|
|
491
|
+
export interface TextOptions {
|
|
492
|
+
/**
|
|
493
|
+
* The message to display in the prompt.
|
|
494
|
+
*/
|
|
495
|
+
readonly message: string
|
|
496
|
+
/**
|
|
497
|
+
* The default value of the text option.
|
|
498
|
+
*/
|
|
499
|
+
readonly default?: string
|
|
500
|
+
/**
|
|
501
|
+
* An effectful function that can be used to validate the value entered into
|
|
502
|
+
* the prompt before final submission.
|
|
503
|
+
*/
|
|
504
|
+
readonly validate?: (value: string) => Effect.Effect<string, string>
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Options for a toggle prompt that lets the user switch between active and
|
|
509
|
+
* inactive boolean states.
|
|
510
|
+
*
|
|
511
|
+
* @category options
|
|
512
|
+
* @since 4.0.0
|
|
513
|
+
*/
|
|
514
|
+
export interface ToggleOptions {
|
|
515
|
+
/**
|
|
516
|
+
* The message to display in the prompt.
|
|
517
|
+
*/
|
|
518
|
+
readonly message: string
|
|
519
|
+
/**
|
|
520
|
+
* The intitial value of the toggle prompt (defaults to `false`).
|
|
521
|
+
*/
|
|
522
|
+
readonly initial?: boolean
|
|
523
|
+
/**
|
|
524
|
+
* The text to display when the toggle is in the active state (defaults to
|
|
525
|
+
* `on`).
|
|
526
|
+
*/
|
|
527
|
+
readonly active?: string
|
|
528
|
+
/**
|
|
529
|
+
* The text to display when the toggle is in the inactive state (defaults to
|
|
530
|
+
* `off`).
|
|
531
|
+
*/
|
|
532
|
+
readonly inactive?: string
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const defaultFigures = {
|
|
536
|
+
arrowUp: "↑",
|
|
537
|
+
arrowDown: "↓",
|
|
538
|
+
arrowLeft: "←",
|
|
539
|
+
arrowRight: "→",
|
|
540
|
+
radioOn: "◉",
|
|
541
|
+
radioOff: "◯",
|
|
542
|
+
checkboxOn: "☒",
|
|
543
|
+
checkboxOff: "☐",
|
|
544
|
+
tick: "✔",
|
|
545
|
+
cross: "✖",
|
|
546
|
+
ellipsis: "…",
|
|
547
|
+
pointerSmall: "›",
|
|
548
|
+
line: "─",
|
|
549
|
+
pointer: "❯"
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const windowsFigures = {
|
|
553
|
+
arrowUp: defaultFigures.arrowUp,
|
|
554
|
+
arrowDown: defaultFigures.arrowDown,
|
|
555
|
+
arrowLeft: defaultFigures.arrowLeft,
|
|
556
|
+
arrowRight: defaultFigures.arrowRight,
|
|
557
|
+
radioOn: "(*)",
|
|
558
|
+
radioOff: "( )",
|
|
559
|
+
checkboxOn: "[*]",
|
|
560
|
+
checkboxOff: "[ ]",
|
|
561
|
+
tick: "√",
|
|
562
|
+
cross: "×",
|
|
563
|
+
ellipsis: "...",
|
|
564
|
+
pointerSmall: "»",
|
|
565
|
+
line: "─",
|
|
566
|
+
pointer: ">"
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** @internal */
|
|
570
|
+
export const platformFigures = Effect.map(
|
|
571
|
+
Effect.sync(() => process.platform === "win32"),
|
|
572
|
+
(isWindows) => isWindows ? windowsFigures : defaultFigures
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Type alias for any `Prompt`, regardless of its output type.
|
|
577
|
+
*
|
|
578
|
+
* @category utility types
|
|
579
|
+
* @since 4.0.0
|
|
580
|
+
*/
|
|
581
|
+
export type Any = Prompt<unknown>
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Namespace containing return-type helpers for `Prompt.all`.
|
|
585
|
+
*
|
|
586
|
+
* @since 4.0.0
|
|
587
|
+
*/
|
|
588
|
+
export declare namespace All {
|
|
589
|
+
/**
|
|
590
|
+
* Computes the prompt returned by `Prompt.all` for an iterable of prompts.
|
|
591
|
+
*
|
|
592
|
+
* **Details**
|
|
593
|
+
*
|
|
594
|
+
* The resulting prompt produces an array of each prompt's output value.
|
|
595
|
+
*
|
|
596
|
+
* @category utility types
|
|
597
|
+
* @since 4.0.0
|
|
598
|
+
*/
|
|
599
|
+
export type ReturnIterable<T extends Iterable<Any>> = [T] extends [Iterable<Prompt<infer A>>] ? Prompt<Array<A>>
|
|
600
|
+
: never
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Computes the prompt returned by `Prompt.all` for a readonly tuple or array
|
|
604
|
+
* of prompts, preserving tuple positions in the output type.
|
|
605
|
+
*
|
|
606
|
+
* @category utility types
|
|
607
|
+
* @since 4.0.0
|
|
608
|
+
*/
|
|
609
|
+
export type ReturnTuple<T extends ReadonlyArray<unknown>> = Prompt<
|
|
610
|
+
T[number] extends never ? []
|
|
611
|
+
: { -readonly [K in keyof T]: [T[K]] extends [Prompt<infer _A>] ? _A : never }
|
|
612
|
+
> extends infer X ? X : never
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Computes the prompt returned by `Prompt.all` for a record of prompts,
|
|
616
|
+
* preserving the record keys and replacing each prompt with its output type.
|
|
617
|
+
*
|
|
618
|
+
* @category utility types
|
|
619
|
+
* @since 4.0.0
|
|
620
|
+
*/
|
|
621
|
+
export type ReturnObject<T> = [T] extends [{ [K: string]: Any }] ? Prompt<
|
|
622
|
+
{
|
|
623
|
+
-readonly [K in keyof T]: [T[K]] extends [Prompt<infer _A>] ? _A : never
|
|
624
|
+
}
|
|
625
|
+
>
|
|
626
|
+
: never
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Computes the return prompt type for `Prompt.all` based on the input
|
|
630
|
+
* structure.
|
|
631
|
+
*
|
|
632
|
+
* @category constructors
|
|
633
|
+
* @since 4.0.0
|
|
634
|
+
*/
|
|
635
|
+
export type Return<
|
|
636
|
+
Arg extends Iterable<Any> | Record<string, Any>
|
|
637
|
+
> = [Arg] extends [ReadonlyArray<Any>] ? ReturnTuple<Arg>
|
|
638
|
+
: [Arg] extends [Iterable<Any>] ? ReturnIterable<Arg>
|
|
639
|
+
: [Arg] extends [Record<string, Any>] ? ReturnObject<Arg>
|
|
640
|
+
: never
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Runs all the provided prompts in sequence respecting the structure provided
|
|
645
|
+
* in input.
|
|
646
|
+
*
|
|
647
|
+
* **Details**
|
|
648
|
+
*
|
|
649
|
+
* Supports either a tuple / iterable of prompts or a record / struct of prompts
|
|
650
|
+
* as an argument.
|
|
651
|
+
*
|
|
652
|
+
* **Example** (Collecting prompt results)
|
|
653
|
+
*
|
|
654
|
+
* ```ts
|
|
655
|
+
* import { Effect } from "effect"
|
|
656
|
+
* import { Prompt } from "effect/unstable/cli"
|
|
657
|
+
*
|
|
658
|
+
* const username = Prompt.text({
|
|
659
|
+
* message: "Enter your username: "
|
|
660
|
+
* })
|
|
661
|
+
*
|
|
662
|
+
* const password = Prompt.password({
|
|
663
|
+
* message: "Enter your password: ",
|
|
664
|
+
* validate: (value) =>
|
|
665
|
+
* value.length === 0
|
|
666
|
+
* ? Effect.fail("Password cannot be empty")
|
|
667
|
+
* : Effect.succeed(value)
|
|
668
|
+
* })
|
|
669
|
+
*
|
|
670
|
+
* const allWithTuple = Prompt.all([username, password])
|
|
671
|
+
*
|
|
672
|
+
* const allWithRecord = Prompt.all({ username, password })
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* @category collecting & elements
|
|
676
|
+
* @since 4.0.0
|
|
677
|
+
*/
|
|
678
|
+
export const all: <
|
|
679
|
+
const Arg extends Iterable<Prompt<any>> | Record<string, Prompt<any>>
|
|
680
|
+
>(arg: Arg) => All.Return<Arg> = function() {
|
|
681
|
+
if (arguments.length === 1) {
|
|
682
|
+
if (isPrompt(arguments[0])) {
|
|
683
|
+
return map(arguments[0], (x) => [x]) as any
|
|
684
|
+
} else if (Array.isArray(arguments[0])) {
|
|
685
|
+
return allTupled(arguments[0]) as any
|
|
686
|
+
} else {
|
|
687
|
+
const entries = Object.entries(arguments[0] as Readonly<{ [K: string]: Prompt<any> }>)
|
|
688
|
+
let result = map(entries[0][1], (value) => ({ [entries[0][0]]: value }))
|
|
689
|
+
if (entries.length === 1) {
|
|
690
|
+
return result as any
|
|
691
|
+
}
|
|
692
|
+
const rest = entries.slice(1)
|
|
693
|
+
for (const [key, prompt] of rest) {
|
|
694
|
+
result = result.pipe(
|
|
695
|
+
flatMap((record) =>
|
|
696
|
+
prompt.pipe(map((value) => ({
|
|
697
|
+
...record,
|
|
698
|
+
[key]: value
|
|
699
|
+
})))
|
|
700
|
+
)
|
|
701
|
+
)
|
|
702
|
+
}
|
|
703
|
+
return result as any
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
return allTupled(arguments[0]) as any
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const annotateLine = (line: string): string => Ansi.annotate(line, Ansi.bold)
|
|
710
|
+
const annotateErrorLine = (line: string): string => Ansi.annotate(line, Ansi.combine(Ansi.italicized, Ansi.red))
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Creates a confirmation prompt that asks the user to choose a boolean yes/no
|
|
714
|
+
* value.
|
|
715
|
+
*
|
|
716
|
+
* **When to use**
|
|
717
|
+
*
|
|
718
|
+
* Use to ask for a yes/no answer that can be submitted directly.
|
|
719
|
+
*
|
|
720
|
+
* **Details**
|
|
721
|
+
*
|
|
722
|
+
* `initial` defaults to `false`. Enter submits the current default, yes-style
|
|
723
|
+
* input submits `true`, no-style input submits `false`, and other input beeps.
|
|
724
|
+
*
|
|
725
|
+
* @see {@link toggle} for an interactive switch-before-submit boolean prompt
|
|
726
|
+
*
|
|
727
|
+
* @category constructors
|
|
728
|
+
* @since 4.0.0
|
|
729
|
+
*/
|
|
730
|
+
export const confirm = (options: ConfirmOptions): Prompt<boolean> => {
|
|
731
|
+
const opts: Required<ConfirmOptions> = {
|
|
732
|
+
initial: false,
|
|
733
|
+
...options,
|
|
734
|
+
label: {
|
|
735
|
+
confirm: "yes",
|
|
736
|
+
deny: "no",
|
|
737
|
+
...options.label
|
|
738
|
+
},
|
|
739
|
+
placeholder: {
|
|
740
|
+
defaultConfirm: "(Y/n)",
|
|
741
|
+
defaultDeny: "(y/N)",
|
|
742
|
+
...options.placeholder
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
const initialState: ConfirmState = { value: opts.initial }
|
|
746
|
+
return custom(initialState, {
|
|
747
|
+
render: handleConfirmRender(opts),
|
|
748
|
+
process: (input) => handleConfirmProcess(input, opts.initial),
|
|
749
|
+
clear: handleConfirmClear(opts)
|
|
750
|
+
})
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Creates a custom `Prompt` from the specified initial state and handlers.
|
|
755
|
+
*
|
|
756
|
+
* **Details**
|
|
757
|
+
*
|
|
758
|
+
* The initial state can either be a pure value or an `Effect`. This is
|
|
759
|
+
* particularly useful when the initial state of the `Prompt` must be computed
|
|
760
|
+
* by performing an effectful computation, such as reading data from the file
|
|
761
|
+
* system. A `Prompt` runs as a render loop: `render` returns ANSI output for
|
|
762
|
+
* the current frame, the `Terminal` obtains user input, `process` returns the
|
|
763
|
+
* next prompt action, and `clear` returns ANSI output used to clear the previous
|
|
764
|
+
* frame.
|
|
765
|
+
*
|
|
766
|
+
* Optionally, an external `events` dequeue can be provided as the third
|
|
767
|
+
* argument. When present, the render loop will race user input against events
|
|
768
|
+
* from the dequeue, allowing background events to trigger re-renders without
|
|
769
|
+
* waiting for a keypress. When an event is received from the dequeue, the
|
|
770
|
+
* `receive` handler is called instead of `process`.
|
|
771
|
+
*
|
|
772
|
+
* @category constructors
|
|
773
|
+
* @since 4.0.0
|
|
774
|
+
*/
|
|
775
|
+
export const custom: {
|
|
776
|
+
<State, Output>(
|
|
777
|
+
initialState: State | Effect.Effect<State, never, Environment>,
|
|
778
|
+
handlers: Handlers<State, Output>
|
|
779
|
+
): Prompt<Output>
|
|
780
|
+
<State, Output, A>(
|
|
781
|
+
initialState: State | Effect.Effect<State, never, Environment>,
|
|
782
|
+
events: Queue.Dequeue<A, never>,
|
|
783
|
+
handlers: Handlers<State, Output, ProcessInput<A>>
|
|
784
|
+
): Prompt<Output>
|
|
785
|
+
} = <State, Output, A>(
|
|
786
|
+
initialState: State | Effect.Effect<State, never, Environment>,
|
|
787
|
+
...args:
|
|
788
|
+
| [handlers: Handlers<State, Output, Terminal.UserInput>]
|
|
789
|
+
| [events: Queue.Dequeue<A, never>, handlers: Handlers<State, Output, ProcessInput<A>>]
|
|
790
|
+
): Prompt<Output> => {
|
|
791
|
+
const [events, handlers] = args.length === 1
|
|
792
|
+
? [undefined, args[0]] as const
|
|
793
|
+
: [args[0], args[1]] as const
|
|
794
|
+
const op = Object.create(proto)
|
|
795
|
+
op._tag = "Loop"
|
|
796
|
+
op.initialState = initialState
|
|
797
|
+
op.render = handlers.render
|
|
798
|
+
op.process = handlers.process
|
|
799
|
+
op.clear = handlers.clear
|
|
800
|
+
op.events = events
|
|
801
|
+
return op
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Creates a date prompt that lets the user edit a formatted date value and
|
|
806
|
+
* validates the final `Date` before submission.
|
|
807
|
+
*
|
|
808
|
+
* **Details**
|
|
809
|
+
*
|
|
810
|
+
* `initial` defaults to the current `Date`, `dateMask` defaults to
|
|
811
|
+
* `YYYY-MM-DD HH:mm:ss`, mask parsing creates editable date parts plus literal
|
|
812
|
+
* tokens, `locales` customizes month and weekday labels, and `validate` runs on
|
|
813
|
+
* submission.
|
|
814
|
+
*
|
|
815
|
+
* **Gotchas**
|
|
816
|
+
*
|
|
817
|
+
* A supplied `initial` `Date` is edited in place during prompt interaction.
|
|
818
|
+
* Date edits use JavaScript `Date` setters, so out-of-range typed values can
|
|
819
|
+
* normalize before validation. If the prompt is meant to be editable,
|
|
820
|
+
* `dateMask` should contain at least one editable date token.
|
|
821
|
+
*
|
|
822
|
+
* @category constructors
|
|
823
|
+
* @since 4.0.0
|
|
824
|
+
*/
|
|
825
|
+
export const date = (options: DateOptions): Prompt<Date> => {
|
|
826
|
+
const opts: Required<DateOptions> = {
|
|
827
|
+
initial: new Date(),
|
|
828
|
+
dateMask: "YYYY-MM-DD HH:mm:ss",
|
|
829
|
+
validate: Effect.succeed,
|
|
830
|
+
...options,
|
|
831
|
+
locales: {
|
|
832
|
+
...defaultLocales,
|
|
833
|
+
...options.locales
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
const dateParts = makeDateParts(opts.dateMask, opts.initial, opts.locales)
|
|
837
|
+
const initialCursorPosition = dateParts.findIndex((part) => !part.isToken())
|
|
838
|
+
const initialState: DateState = {
|
|
839
|
+
dateParts,
|
|
840
|
+
typed: "",
|
|
841
|
+
cursor: initialCursorPosition,
|
|
842
|
+
value: opts.initial,
|
|
843
|
+
error: Option.none()
|
|
844
|
+
}
|
|
845
|
+
return custom(initialState, {
|
|
846
|
+
render: handleDateRender(opts),
|
|
847
|
+
process: handleDateProcess(opts),
|
|
848
|
+
clear: handleDateClear(opts)
|
|
849
|
+
})
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Creates a file-system selection prompt and returns the selected path.
|
|
854
|
+
*
|
|
855
|
+
* **Details**
|
|
856
|
+
*
|
|
857
|
+
* The prompt can be configured to select files, directories, or either path
|
|
858
|
+
* type.
|
|
859
|
+
*
|
|
860
|
+
* @category constructors
|
|
861
|
+
* @since 4.0.0
|
|
862
|
+
*/
|
|
863
|
+
export const file = (options: FileOptions = {}): Prompt<string> => {
|
|
864
|
+
const opts: FileOptionsReq = {
|
|
865
|
+
type: options.type ?? "file",
|
|
866
|
+
message: options.message ?? `Choose a file`,
|
|
867
|
+
startingPath: Option.fromUndefinedOr(options.startingPath),
|
|
868
|
+
default: Option.fromUndefinedOr(options.default),
|
|
869
|
+
maxPerPage: options.maxPerPage ?? 10,
|
|
870
|
+
filter: options.filter ?? (() => Effect.succeed(true))
|
|
871
|
+
}
|
|
872
|
+
const initialState: Effect.Effect<
|
|
873
|
+
FileState,
|
|
874
|
+
never,
|
|
875
|
+
Environment
|
|
876
|
+
> = Effect.gen(function*() {
|
|
877
|
+
const currentPath = yield* resolveCurrentPath(Option.none(), opts)
|
|
878
|
+
const path = yield* Path.Path
|
|
879
|
+
const defaultPath = Option.map(opts.default, (defaultValue) => path.resolve(currentPath, defaultValue))
|
|
880
|
+
const initialPath = Option.match(defaultPath, {
|
|
881
|
+
onNone: () => currentPath,
|
|
882
|
+
onSome: (defaultPath) => path.dirname(defaultPath)
|
|
883
|
+
})
|
|
884
|
+
const files = yield* getFileList(initialPath, opts)
|
|
885
|
+
const cursor = Option.match(defaultPath, {
|
|
886
|
+
onNone: () => 0,
|
|
887
|
+
onSome: (defaultPath) => {
|
|
888
|
+
const index = files.indexOf(path.basename(defaultPath))
|
|
889
|
+
return index === -1 ? 0 : index
|
|
890
|
+
}
|
|
891
|
+
})
|
|
892
|
+
const confirm = Confirm.Hide()
|
|
893
|
+
return { cursor, files, allFiles: files, query: "", path: Option.map(defaultPath, path.dirname), confirm }
|
|
894
|
+
})
|
|
895
|
+
return custom(initialState, {
|
|
896
|
+
render: handleFileRender(opts),
|
|
897
|
+
process: handleFileProcess(opts),
|
|
898
|
+
clear: handleFileClear(opts)
|
|
899
|
+
})
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Composes prompts by using the output of this prompt to create the next prompt.
|
|
904
|
+
*
|
|
905
|
+
* @category combinators
|
|
906
|
+
* @since 4.0.0
|
|
907
|
+
*/
|
|
908
|
+
export const flatMap: {
|
|
909
|
+
<Output, Output2>(
|
|
910
|
+
f: (output: Output) => Prompt<Output2>
|
|
911
|
+
): (self: Prompt<Output>) => Prompt<Output2>
|
|
912
|
+
<Output, Output2>(
|
|
913
|
+
self: Prompt<Output>,
|
|
914
|
+
f: (output: Output) => Prompt<Output2>
|
|
915
|
+
): Prompt<Output2>
|
|
916
|
+
} = dual(2, <Output, Output2>(
|
|
917
|
+
self: Prompt<Output>,
|
|
918
|
+
f: (output: Output) => Prompt<Output2>
|
|
919
|
+
) => {
|
|
920
|
+
const op = Object.create(proto)
|
|
921
|
+
op._tag = "OnSuccess"
|
|
922
|
+
op.prompt = self
|
|
923
|
+
op.onSuccess = f
|
|
924
|
+
return op
|
|
925
|
+
})
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Creates a floating-point number prompt.
|
|
929
|
+
*
|
|
930
|
+
* **Details**
|
|
931
|
+
*
|
|
932
|
+
* The prompt supports minimum and maximum bounds, keyboard step sizes, display
|
|
933
|
+
* precision, and additional validation before submission.
|
|
934
|
+
*
|
|
935
|
+
* @category constructors
|
|
936
|
+
* @since 4.0.0
|
|
937
|
+
*/
|
|
938
|
+
export const float = (options: FloatOptions): Prompt<number> => {
|
|
939
|
+
const opts: FloatOptionsReq = {
|
|
940
|
+
default: 0,
|
|
941
|
+
min: Number.NEGATIVE_INFINITY,
|
|
942
|
+
max: Number.POSITIVE_INFINITY,
|
|
943
|
+
incrementBy: 1,
|
|
944
|
+
decrementBy: 1,
|
|
945
|
+
precision: 2,
|
|
946
|
+
validate: (n) => {
|
|
947
|
+
if (n < opts.min) {
|
|
948
|
+
return Effect.fail(`${n} must be greater than or equal to ${opts.min}`)
|
|
949
|
+
}
|
|
950
|
+
if (n > opts.max) {
|
|
951
|
+
return Effect.fail(`${n} must be less than or equal to ${opts.max}`)
|
|
952
|
+
}
|
|
953
|
+
return Effect.succeed(n)
|
|
954
|
+
},
|
|
955
|
+
...options
|
|
956
|
+
}
|
|
957
|
+
const initialValue = options.default === undefined ? "" : `${opts.default}`
|
|
958
|
+
const initialState: NumberState = {
|
|
959
|
+
cursor: initialValue.length,
|
|
960
|
+
value: initialValue,
|
|
961
|
+
error: Option.none()
|
|
962
|
+
}
|
|
963
|
+
return custom(initialState, {
|
|
964
|
+
render: handleRenderFloat(opts),
|
|
965
|
+
process: handleProcessFloat(opts),
|
|
966
|
+
clear: handleNumberClear(opts)
|
|
967
|
+
})
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Creates a text prompt that does not echo typed input and returns the
|
|
971
|
+
* submitted value wrapped in `Redacted`.
|
|
972
|
+
*
|
|
973
|
+
* @category constructors
|
|
974
|
+
* @since 4.0.0
|
|
975
|
+
*/
|
|
976
|
+
export const hidden = (
|
|
977
|
+
options: TextOptions
|
|
978
|
+
): Prompt<Redacted.Redacted> => basePrompt(options, "hidden").pipe(map(Redacted.make))
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Creates an integer prompt.
|
|
982
|
+
*
|
|
983
|
+
* **Details**
|
|
984
|
+
*
|
|
985
|
+
* The prompt supports minimum and maximum bounds, keyboard step sizes, and
|
|
986
|
+
* additional validation before submission.
|
|
987
|
+
*
|
|
988
|
+
* @category constructors
|
|
989
|
+
* @since 4.0.0
|
|
990
|
+
*/
|
|
991
|
+
export const integer = (options: IntegerOptions): Prompt<number> => {
|
|
992
|
+
const opts: IntegerOptionsReq = {
|
|
993
|
+
default: 0,
|
|
994
|
+
min: Number.NEGATIVE_INFINITY,
|
|
995
|
+
max: Number.POSITIVE_INFINITY,
|
|
996
|
+
incrementBy: 1,
|
|
997
|
+
decrementBy: 1,
|
|
998
|
+
validate: (n) => {
|
|
999
|
+
if (n < opts.min) {
|
|
1000
|
+
return Effect.fail(`${n} must be greater than or equal to ${opts.min}`)
|
|
1001
|
+
}
|
|
1002
|
+
if (n > opts.max) {
|
|
1003
|
+
return Effect.fail(`${n} must be less than or equal to ${opts.max}`)
|
|
1004
|
+
}
|
|
1005
|
+
return Effect.succeed(n)
|
|
1006
|
+
},
|
|
1007
|
+
...options
|
|
1008
|
+
}
|
|
1009
|
+
const initialValue = options.default === undefined ? "" : `${opts.default}`
|
|
1010
|
+
const initialState: NumberState = {
|
|
1011
|
+
cursor: initialValue.length,
|
|
1012
|
+
value: initialValue,
|
|
1013
|
+
error: Option.none()
|
|
1014
|
+
}
|
|
1015
|
+
return custom(initialState, {
|
|
1016
|
+
render: handleRenderInteger(opts),
|
|
1017
|
+
process: handleProcessInteger(opts),
|
|
1018
|
+
clear: handleNumberClear(opts)
|
|
1019
|
+
})
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Creates a text prompt that returns an array of strings by splitting the
|
|
1024
|
+
* submitted input on the configured delimiter.
|
|
1025
|
+
*
|
|
1026
|
+
* @category constructors
|
|
1027
|
+
* @since 4.0.0
|
|
1028
|
+
*/
|
|
1029
|
+
export const list = (options: ListOptions): Prompt<Array<string>> =>
|
|
1030
|
+
text(options).pipe(
|
|
1031
|
+
map((output) => output.split(options.delimiter || ","))
|
|
1032
|
+
)
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Transforms the output value produced by a prompt.
|
|
1036
|
+
*
|
|
1037
|
+
* @category combinators
|
|
1038
|
+
* @since 4.0.0
|
|
1039
|
+
*/
|
|
1040
|
+
export const map: {
|
|
1041
|
+
<Output, Output2>(
|
|
1042
|
+
f: (output: Output) => Output2
|
|
1043
|
+
): (self: Prompt<Output>) => Prompt<Output2>
|
|
1044
|
+
<Output, Output2>(
|
|
1045
|
+
self: Prompt<Output>,
|
|
1046
|
+
f: (output: Output) => Output2
|
|
1047
|
+
): Prompt<Output2>
|
|
1048
|
+
} = dual(2, <Output, Output2>(
|
|
1049
|
+
self: Prompt<Output>,
|
|
1050
|
+
f: (output: Output) => Output2
|
|
1051
|
+
) => flatMap(self, (a) => succeed(f(a))))
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Creates a password prompt that masks typed input and returns the submitted
|
|
1055
|
+
* value wrapped in `Redacted`.
|
|
1056
|
+
*
|
|
1057
|
+
* @category constructors
|
|
1058
|
+
* @since 4.0.0
|
|
1059
|
+
*/
|
|
1060
|
+
export const password = (
|
|
1061
|
+
options: TextOptions
|
|
1062
|
+
): Prompt<Redacted.Redacted> => basePrompt(options, "password").pipe(map(Redacted.make))
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Runs a prompt by reading terminal input and rendering prompt frames until the
|
|
1066
|
+
* prompt submits a value.
|
|
1067
|
+
*
|
|
1068
|
+
* **Gotchas**
|
|
1069
|
+
*
|
|
1070
|
+
* The returned effect may fail with `Terminal.QuitError` if terminal input ends
|
|
1071
|
+
* or the prompt is quit.
|
|
1072
|
+
*
|
|
1073
|
+
* @category execution
|
|
1074
|
+
* @since 4.0.0
|
|
1075
|
+
*/
|
|
1076
|
+
export const run: <Output>(
|
|
1077
|
+
self: Prompt<Output>
|
|
1078
|
+
) => Effect.Effect<
|
|
1079
|
+
Output,
|
|
1080
|
+
Terminal.QuitError,
|
|
1081
|
+
Environment
|
|
1082
|
+
> = Effect.fnUntraced(
|
|
1083
|
+
function*<Output>(self: Prompt<Output>) {
|
|
1084
|
+
const terminal = yield* Terminal.Terminal
|
|
1085
|
+
const input = yield* terminal.readInput
|
|
1086
|
+
return yield* runWithInput(self, terminal, input)
|
|
1087
|
+
},
|
|
1088
|
+
Effect.mapError(() => new Terminal.QuitError({})),
|
|
1089
|
+
Effect.scoped
|
|
1090
|
+
)
|
|
1091
|
+
|
|
1092
|
+
const getSelectInitialIndex = <A>(choices: ReadonlyArray<SelectChoice<A>>): number => {
|
|
1093
|
+
let initialIndex = 0
|
|
1094
|
+
let seenSelected = -1
|
|
1095
|
+
for (let i = 0; i < choices.length; i++) {
|
|
1096
|
+
const choice = choices[i] as SelectChoice<A>
|
|
1097
|
+
if (choice.selected === true) {
|
|
1098
|
+
if (seenSelected !== -1) {
|
|
1099
|
+
throw new Error("InvalidArgumentException: only a single choice can be selected by default for Prompt.select")
|
|
1100
|
+
}
|
|
1101
|
+
seenSelected = i
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (seenSelected !== -1) {
|
|
1105
|
+
initialIndex = seenSelected
|
|
1106
|
+
}
|
|
1107
|
+
return initialIndex
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Creates a prompt that lets the user select a single value from a list of
|
|
1112
|
+
* choices.
|
|
1113
|
+
*
|
|
1114
|
+
* **Gotchas**
|
|
1115
|
+
*
|
|
1116
|
+
* At most one choice may be marked as selected by default.
|
|
1117
|
+
*
|
|
1118
|
+
* @category constructors
|
|
1119
|
+
* @since 4.0.0
|
|
1120
|
+
*/
|
|
1121
|
+
export const select = <const A>(options: SelectOptions<A>): Prompt<A> => {
|
|
1122
|
+
const opts: SelectOptionsReq<A> = {
|
|
1123
|
+
maxPerPage: 10,
|
|
1124
|
+
...options
|
|
1125
|
+
}
|
|
1126
|
+
const initialIndex = getSelectInitialIndex(opts.choices)
|
|
1127
|
+
return custom(initialIndex, {
|
|
1128
|
+
render: handleSelectRender(opts),
|
|
1129
|
+
process: handleSelectProcess(opts),
|
|
1130
|
+
clear: handleSelectClear(opts)
|
|
1131
|
+
})
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Creates a prompt that lets users filter select choices by typing.
|
|
1136
|
+
*
|
|
1137
|
+
* **Example** (Filtering choices with autocomplete)
|
|
1138
|
+
*
|
|
1139
|
+
* ```ts
|
|
1140
|
+
* import { Prompt } from "effect/unstable/cli"
|
|
1141
|
+
*
|
|
1142
|
+
* const language = Prompt.autoComplete({
|
|
1143
|
+
* message: "Choose a language",
|
|
1144
|
+
* choices: [
|
|
1145
|
+
* { title: "TypeScript", value: "ts" },
|
|
1146
|
+
* { title: "Rust", value: "rs" },
|
|
1147
|
+
* { title: "Kotlin", value: "kt" }
|
|
1148
|
+
* ]
|
|
1149
|
+
* })
|
|
1150
|
+
* ```
|
|
1151
|
+
*
|
|
1152
|
+
* @category constructors
|
|
1153
|
+
* @since 4.0.0
|
|
1154
|
+
*/
|
|
1155
|
+
export const autoComplete = <const A>(options: AutoCompleteOptions<A>): Prompt<A> => {
|
|
1156
|
+
const opts: AutoCompleteOptionsReq<A> = {
|
|
1157
|
+
maxPerPage: 10,
|
|
1158
|
+
filterLabel: "filter",
|
|
1159
|
+
filterPlaceholder: "type to filter",
|
|
1160
|
+
emptyMessage: "No matches",
|
|
1161
|
+
...options
|
|
1162
|
+
}
|
|
1163
|
+
const initialIndex = getSelectInitialIndex(opts.choices)
|
|
1164
|
+
const filtered = filterAutoCompleteChoices(opts.choices, "")
|
|
1165
|
+
const index = filtered.length === 0
|
|
1166
|
+
? 0
|
|
1167
|
+
: filtered.includes(initialIndex)
|
|
1168
|
+
? initialIndex
|
|
1169
|
+
: filtered[0]
|
|
1170
|
+
const initialState: AutoCompleteState = {
|
|
1171
|
+
query: "",
|
|
1172
|
+
index,
|
|
1173
|
+
filtered
|
|
1174
|
+
}
|
|
1175
|
+
return custom(initialState, {
|
|
1176
|
+
render: handleAutoCompleteRender(opts),
|
|
1177
|
+
process: handleAutoCompleteProcess(opts),
|
|
1178
|
+
clear: handleAutoCompleteClear(opts)
|
|
1179
|
+
})
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
/**
|
|
1183
|
+
* Creates a prompt that lets the user select multiple choices and returns their
|
|
1184
|
+
* values as an array.
|
|
1185
|
+
*
|
|
1186
|
+
* **Details**
|
|
1187
|
+
*
|
|
1188
|
+
* The prompt supports default selected choices, bulk-selection commands, and
|
|
1189
|
+
* minimum or maximum selection counts.
|
|
1190
|
+
*
|
|
1191
|
+
* @category constructors
|
|
1192
|
+
* @since 4.0.0
|
|
1193
|
+
*/
|
|
1194
|
+
export const multiSelect = <const A>(
|
|
1195
|
+
options: SelectOptions<A> & MultiSelectOptions
|
|
1196
|
+
): Prompt<Array<A>> => {
|
|
1197
|
+
const opts: SelectOptionsReq<A> & MultiSelectOptionsReq = {
|
|
1198
|
+
maxPerPage: 10,
|
|
1199
|
+
...options
|
|
1200
|
+
}
|
|
1201
|
+
// Seed initial selection from choices marked as selected: true
|
|
1202
|
+
const initialSelected = new Set<number>()
|
|
1203
|
+
for (let i = 0; i < opts.choices.length; i++) {
|
|
1204
|
+
const choice = opts.choices[i] as SelectChoice<A>
|
|
1205
|
+
if (choice.selected === true) {
|
|
1206
|
+
initialSelected.add(i)
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
const initialState: MultiSelectState = { index: 0, selectedIndices: initialSelected, error: Option.none() }
|
|
1210
|
+
return custom(initialState, {
|
|
1211
|
+
render: handleMultiSelectRender(opts),
|
|
1212
|
+
process: handleMultiSelectProcess(opts),
|
|
1213
|
+
clear: handleMultiSelectClear(opts)
|
|
1214
|
+
})
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Creates a `Prompt` which immediately succeeds with the specified value.
|
|
1219
|
+
*
|
|
1220
|
+
* **Details**
|
|
1221
|
+
*
|
|
1222
|
+
* This prompt does not attempt to obtain user input or render anything to the
|
|
1223
|
+
* screen.
|
|
1224
|
+
*
|
|
1225
|
+
* @category constructors
|
|
1226
|
+
* @since 4.0.0
|
|
1227
|
+
*/
|
|
1228
|
+
export const succeed = <A>(value: A): Prompt<A> => {
|
|
1229
|
+
const op = Object.create(proto)
|
|
1230
|
+
op._tag = "Succeed"
|
|
1231
|
+
op.value = value
|
|
1232
|
+
return op
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Creates a text-entry prompt that echoes input and returns the submitted
|
|
1237
|
+
* string after validation.
|
|
1238
|
+
*
|
|
1239
|
+
* @category constructors
|
|
1240
|
+
* @since 4.0.0
|
|
1241
|
+
*/
|
|
1242
|
+
export const text = (
|
|
1243
|
+
options: TextOptions
|
|
1244
|
+
): Prompt<string> => basePrompt(options, "text")
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* Creates a toggle prompt that lets the user switch between active and inactive
|
|
1248
|
+
* states and returns the selected boolean value.
|
|
1249
|
+
*
|
|
1250
|
+
* @category constructors
|
|
1251
|
+
* @since 4.0.0
|
|
1252
|
+
*/
|
|
1253
|
+
export const toggle = (options: ToggleOptions): Prompt<boolean> => {
|
|
1254
|
+
const opts: ToggleOptionsReq = {
|
|
1255
|
+
initial: false,
|
|
1256
|
+
active: "on",
|
|
1257
|
+
inactive: "off",
|
|
1258
|
+
...options
|
|
1259
|
+
}
|
|
1260
|
+
return custom(opts.initial, {
|
|
1261
|
+
render: handleToggleRender(opts),
|
|
1262
|
+
process: handleToggleProcess,
|
|
1263
|
+
clear: () => handleToggleClear(opts)
|
|
1264
|
+
})
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
const proto = {
|
|
1268
|
+
...Effectable.Prototype<Prompt<any>>({
|
|
1269
|
+
label: "Prompt",
|
|
1270
|
+
evaluate() {
|
|
1271
|
+
return run(this)
|
|
1272
|
+
}
|
|
1273
|
+
}),
|
|
1274
|
+
[TypeId]: {
|
|
1275
|
+
_Output: (_: never) => _
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
type Op<Tag extends string, Body = {}> = Prompt<never> & Body & {
|
|
1280
|
+
readonly _tag: Tag
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
type PromptPrimitive = Loop | OnSuccess | Succeed
|
|
1284
|
+
|
|
1285
|
+
interface Loop extends
|
|
1286
|
+
Op<"Loop", {
|
|
1287
|
+
readonly initialState: unknown | Effect.Effect<unknown, never, Environment>
|
|
1288
|
+
readonly render: Handlers<unknown, unknown>["render"]
|
|
1289
|
+
readonly process: (
|
|
1290
|
+
input: unknown,
|
|
1291
|
+
state: unknown
|
|
1292
|
+
) => Effect.Effect<Action<unknown, unknown>, never, Environment>
|
|
1293
|
+
readonly clear: Handlers<unknown, unknown>["clear"]
|
|
1294
|
+
readonly events: Queue.Dequeue<unknown, never> | undefined
|
|
1295
|
+
}>
|
|
1296
|
+
{}
|
|
1297
|
+
|
|
1298
|
+
/** @internal */
|
|
1299
|
+
export interface OnSuccess extends
|
|
1300
|
+
Op<"OnSuccess", {
|
|
1301
|
+
readonly prompt: PromptPrimitive
|
|
1302
|
+
readonly onSuccess: (value: unknown) => Prompt<unknown>
|
|
1303
|
+
}>
|
|
1304
|
+
{}
|
|
1305
|
+
|
|
1306
|
+
interface Succeed extends
|
|
1307
|
+
Op<"Succeed", {
|
|
1308
|
+
readonly value: unknown
|
|
1309
|
+
}>
|
|
1310
|
+
{}
|
|
1311
|
+
|
|
1312
|
+
const allTupled = <const T extends ArrayLike<Prompt<any>>>(arg: T): Prompt<
|
|
1313
|
+
{
|
|
1314
|
+
[K in keyof T]: [T[K]] extends [Prompt<infer A>] ? A : never
|
|
1315
|
+
}
|
|
1316
|
+
> => {
|
|
1317
|
+
if (arg.length === 0) {
|
|
1318
|
+
return succeed([]) as any
|
|
1319
|
+
}
|
|
1320
|
+
if (arg.length === 1) {
|
|
1321
|
+
return map(arg[0], (x) => [x]) as any
|
|
1322
|
+
}
|
|
1323
|
+
let result = map(arg[0], (x) => [x])
|
|
1324
|
+
for (let i = 1; i < arg.length; i++) {
|
|
1325
|
+
const curr = arg[i]
|
|
1326
|
+
result = flatMap(result, (tuple) => map(curr, (a) => [...tuple, a]))
|
|
1327
|
+
}
|
|
1328
|
+
return result as any
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
const runWithInput = <Output>(
|
|
1332
|
+
prompt: Prompt<Output>,
|
|
1333
|
+
terminal: Terminal.Terminal,
|
|
1334
|
+
input: Queue.Dequeue<Terminal.UserInput, Cause.Done>
|
|
1335
|
+
): Effect.Effect<Output, NoSuchElementError, Environment> =>
|
|
1336
|
+
Effect.suspend(() => {
|
|
1337
|
+
const op = prompt as PromptPrimitive
|
|
1338
|
+
switch (op._tag) {
|
|
1339
|
+
case "Loop": {
|
|
1340
|
+
return runLoop(op, terminal, input)
|
|
1341
|
+
}
|
|
1342
|
+
case "OnSuccess": {
|
|
1343
|
+
return Effect.flatMap(
|
|
1344
|
+
runWithInput(op.prompt, terminal, input),
|
|
1345
|
+
(a) => runWithInput(op.onSuccess(a), terminal, input)
|
|
1346
|
+
) as any
|
|
1347
|
+
}
|
|
1348
|
+
case "Succeed": {
|
|
1349
|
+
return Effect.succeed(op.value)
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
})
|
|
1353
|
+
|
|
1354
|
+
const runLoop = Effect.fnUntraced(
|
|
1355
|
+
function*(
|
|
1356
|
+
loop: Loop,
|
|
1357
|
+
terminal: Terminal.Terminal,
|
|
1358
|
+
input: Queue.Dequeue<Terminal.UserInput, Cause.Done>
|
|
1359
|
+
) {
|
|
1360
|
+
let state = Effect.isEffect(loop.initialState) ? yield* loop.initialState : loop.initialState
|
|
1361
|
+
let action: Action<unknown, unknown> = Action.NextFrame({ state })
|
|
1362
|
+
while (true) {
|
|
1363
|
+
const msg = yield* loop.render(state, action)
|
|
1364
|
+
yield* Effect.orDie(terminal.display(msg))
|
|
1365
|
+
if (loop.events) {
|
|
1366
|
+
const takeInput = Queue.take(input).pipe(
|
|
1367
|
+
Effect.map((event) => ({ _tag: "Input" as const, event }))
|
|
1368
|
+
)
|
|
1369
|
+
const result = yield* Effect.raceFirst(
|
|
1370
|
+
takeInput,
|
|
1371
|
+
Queue.take(loop.events).pipe(Effect.map((value) => ({ _tag: "Event" as const, value })))
|
|
1372
|
+
)
|
|
1373
|
+
action = yield* loop.process(result, state)
|
|
1374
|
+
} else {
|
|
1375
|
+
const result = yield* Queue.take(input)
|
|
1376
|
+
action = yield* loop.process(result, state)
|
|
1377
|
+
}
|
|
1378
|
+
switch (action._tag) {
|
|
1379
|
+
case "Beep":
|
|
1380
|
+
continue
|
|
1381
|
+
case "NextFrame": {
|
|
1382
|
+
yield* Effect.orDie(terminal.display(yield* loop.clear(state, action)))
|
|
1383
|
+
state = action.state
|
|
1384
|
+
continue
|
|
1385
|
+
}
|
|
1386
|
+
case "Submit": {
|
|
1387
|
+
yield* Effect.orDie(terminal.display(yield* loop.clear(state, action)))
|
|
1388
|
+
const msg = yield* loop.render(state, action)
|
|
1389
|
+
yield* Effect.orDie(terminal.display(msg))
|
|
1390
|
+
return action.value
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
},
|
|
1395
|
+
(effect, _, terminal) => Effect.ensuring(effect, Effect.orDie(terminal.display(Ansi.cursorShow)))
|
|
1396
|
+
)
|
|
1397
|
+
|
|
1398
|
+
const Action = Data.taggedEnum<ActionDefinition>()
|
|
1399
|
+
|
|
1400
|
+
/**
|
|
1401
|
+
* Clears all lines taken up by the specified `text`.
|
|
1402
|
+
*/
|
|
1403
|
+
const eraseText = (text: string, columns: number): string => {
|
|
1404
|
+
if (columns === 0) {
|
|
1405
|
+
return Ansi.eraseLine + Ansi.cursorTo(0)
|
|
1406
|
+
}
|
|
1407
|
+
let rows = 0
|
|
1408
|
+
const lines = text.split(NEWLINE_REGEXP)
|
|
1409
|
+
for (const line of lines) {
|
|
1410
|
+
rows += 1 + Math.floor(Math.max(line.length - 1, 0) / columns)
|
|
1411
|
+
}
|
|
1412
|
+
return Ansi.eraseLines(rows)
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
const lines = (prompt: string, columns: number): number => {
|
|
1416
|
+
const lines = prompt.split(NEWLINE_REGEXP)
|
|
1417
|
+
return columns === 0
|
|
1418
|
+
? lines.length
|
|
1419
|
+
: pipe(
|
|
1420
|
+
Arr.map(lines, (line) => Math.ceil(line.length / columns)),
|
|
1421
|
+
Arr.reduce(0, (left, right) => left + right)
|
|
1422
|
+
)
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
const clearOutputWithError = (outputText: string, columns: number, errorText?: string): string => {
|
|
1426
|
+
if (errorText !== undefined && errorText.length > 0) {
|
|
1427
|
+
return Ansi.cursorDown(lines(errorText, columns))
|
|
1428
|
+
+ eraseText(`\n${errorText}`, columns)
|
|
1429
|
+
+ eraseText(outputText, columns)
|
|
1430
|
+
}
|
|
1431
|
+
return eraseText(outputText, columns)
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
interface ConfirmOptionsReq extends Required<ConfirmOptions> {}
|
|
1435
|
+
|
|
1436
|
+
interface ConfirmState {
|
|
1437
|
+
readonly value: boolean
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
const renderBeep = Ansi.beep
|
|
1441
|
+
|
|
1442
|
+
const NEWLINE_REGEXP = /\r?\n/
|
|
1443
|
+
|
|
1444
|
+
const handleConfirmClear = (options: ConfirmOptionsReq) => {
|
|
1445
|
+
return Effect.fnUntraced(function*(state: ConfirmState, _: Action<ConfirmState, boolean>) {
|
|
1446
|
+
const terminal = yield* Terminal.Terminal
|
|
1447
|
+
const columns = yield* terminal.columns
|
|
1448
|
+
const figures = yield* platformFigures
|
|
1449
|
+
const confirmMessage = state.value
|
|
1450
|
+
? options.placeholder.defaultConfirm!
|
|
1451
|
+
: options.placeholder.defaultDeny!
|
|
1452
|
+
const promptText = renderConfirmOutput(
|
|
1453
|
+
confirmMessage,
|
|
1454
|
+
"?",
|
|
1455
|
+
figures.pointerSmall,
|
|
1456
|
+
options,
|
|
1457
|
+
{ plain: true }
|
|
1458
|
+
)
|
|
1459
|
+
const clearOutput = eraseText(promptText, columns)
|
|
1460
|
+
const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft
|
|
1461
|
+
return clearOutput + resetCurrentLine
|
|
1462
|
+
})
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
const renderConfirmOutput = (
|
|
1466
|
+
confirm: string,
|
|
1467
|
+
leadingSymbol: string,
|
|
1468
|
+
trailingSymbol: string,
|
|
1469
|
+
options: ConfirmOptionsReq,
|
|
1470
|
+
renderOptions?: RenderOptions | undefined
|
|
1471
|
+
) => renderPrompt(confirm, options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
1472
|
+
|
|
1473
|
+
const renderConfirmNextFrame = Effect.fnUntraced(function*(state: ConfirmState, options: ConfirmOptionsReq) {
|
|
1474
|
+
const figures = yield* platformFigures
|
|
1475
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
1476
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
1477
|
+
// Marking these explicitly as present with `!` because they always will be
|
|
1478
|
+
// and there is really no value in adding a `DeepRequired` type helper just
|
|
1479
|
+
// for these internal cases
|
|
1480
|
+
const confirmMessage = state.value
|
|
1481
|
+
? options.placeholder.defaultConfirm!
|
|
1482
|
+
: options.placeholder.defaultDeny!
|
|
1483
|
+
const confirm = Ansi.annotate(confirmMessage, Ansi.blackBright)
|
|
1484
|
+
const promptMsg = renderConfirmOutput(confirm, leadingSymbol, trailingSymbol, options)
|
|
1485
|
+
return Ansi.cursorHide + promptMsg
|
|
1486
|
+
})
|
|
1487
|
+
|
|
1488
|
+
const renderConfirmSubmission = Effect.fnUntraced(function*(value: boolean, options: ConfirmOptionsReq) {
|
|
1489
|
+
const figures = yield* platformFigures
|
|
1490
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
1491
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
1492
|
+
const confirmMessage = value ? options.label.confirm : options.label.deny
|
|
1493
|
+
const promptMsg = renderConfirmOutput(confirmMessage, leadingSymbol, trailingSymbol, options)
|
|
1494
|
+
return promptMsg + "\n"
|
|
1495
|
+
})
|
|
1496
|
+
|
|
1497
|
+
const handleConfirmRender = (options: ConfirmOptionsReq) => {
|
|
1498
|
+
return (_: ConfirmState, action: Action<ConfirmState, boolean>) => {
|
|
1499
|
+
return Action.$match(action, {
|
|
1500
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
1501
|
+
NextFrame: ({ state }) => renderConfirmNextFrame(state, options),
|
|
1502
|
+
Submit: ({ value }) => renderConfirmSubmission(value, options)
|
|
1503
|
+
})
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
const TRUE_VALUE_REGEXP = /^y|t$/
|
|
1508
|
+
const FALSE_VALUE_REGEXP = /^n|f$/
|
|
1509
|
+
|
|
1510
|
+
const handleConfirmProcess = (input: Terminal.UserInput, defaultValue: boolean) => {
|
|
1511
|
+
const value = Option.getOrElse(input.input, () => "")
|
|
1512
|
+
if (input.key.name === "enter" || input.key.name === "return") {
|
|
1513
|
+
return Effect.succeed(Action.Submit({ value: defaultValue }))
|
|
1514
|
+
}
|
|
1515
|
+
if (TRUE_VALUE_REGEXP.test(value.toLowerCase())) {
|
|
1516
|
+
return Effect.succeed(Action.Submit({ value: true }))
|
|
1517
|
+
}
|
|
1518
|
+
if (FALSE_VALUE_REGEXP.test(value.toLowerCase())) {
|
|
1519
|
+
return Effect.succeed(Action.Submit({ value: false }))
|
|
1520
|
+
}
|
|
1521
|
+
return Effect.succeed(Action.Beep())
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
interface DateOptionsReq extends Required<DateOptions> {}
|
|
1525
|
+
|
|
1526
|
+
interface DateState {
|
|
1527
|
+
readonly typed: string
|
|
1528
|
+
readonly cursor: number
|
|
1529
|
+
readonly value: globalThis.Date
|
|
1530
|
+
readonly dateParts: ReadonlyArray<DatePart>
|
|
1531
|
+
readonly error: Option.Option<string>
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
const handleDateClear = (options: DateOptionsReq) => {
|
|
1535
|
+
return Effect.fnUntraced(function*(state: DateState, _: Action<DateState, globalThis.Date>) {
|
|
1536
|
+
const terminal = yield* Terminal.Terminal
|
|
1537
|
+
const columns = yield* terminal.columns
|
|
1538
|
+
const figures = yield* platformFigures
|
|
1539
|
+
const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft
|
|
1540
|
+
const parts = Arr.reduce(state.dateParts, "", (doc, part) => doc + part.toString())
|
|
1541
|
+
const promptText = renderDateOutput("?", figures.pointerSmall, parts, options, { plain: true })
|
|
1542
|
+
const errorText = Option.isSome(state.error)
|
|
1543
|
+
? Arr.match(state.error.value.split(NEWLINE_REGEXP), {
|
|
1544
|
+
onEmpty: () => "",
|
|
1545
|
+
onNonEmpty: (errorLines) => `${figures.pointerSmall} ${errorLines.join("\n")}`
|
|
1546
|
+
})
|
|
1547
|
+
: ""
|
|
1548
|
+
const clearOutput = clearOutputWithError(promptText, columns, errorText)
|
|
1549
|
+
return clearOutput + resetCurrentLine
|
|
1550
|
+
})
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
const renderDateError = (state: DateState, pointer: string): string => {
|
|
1554
|
+
if (Option.isSome(state.error)) {
|
|
1555
|
+
const errorLines = state.error.value.split(NEWLINE_REGEXP)
|
|
1556
|
+
if (Arr.isReadonlyArrayNonEmpty(errorLines)) {
|
|
1557
|
+
const prefix = Ansi.annotate(pointer, Ansi.red) + " "
|
|
1558
|
+
const lines = Arr.map(errorLines, (str) => annotateErrorLine(str))
|
|
1559
|
+
return Ansi.cursorSavePosition + "\n" + prefix + lines.join("\n") + Ansi.cursorRestorePosition
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
return ""
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
const renderParts = (state: DateState, submitted: boolean = false) => {
|
|
1566
|
+
return Arr.reduce(
|
|
1567
|
+
state.dateParts,
|
|
1568
|
+
"",
|
|
1569
|
+
(doc, part, currentIndex) => {
|
|
1570
|
+
const partDoc = part.toString()
|
|
1571
|
+
if (currentIndex === state.cursor && !submitted) {
|
|
1572
|
+
const annotation = Ansi.combine(Ansi.underlined, Ansi.cyanBright)
|
|
1573
|
+
return doc + Ansi.annotate(partDoc, annotation)
|
|
1574
|
+
}
|
|
1575
|
+
return doc + partDoc
|
|
1576
|
+
}
|
|
1577
|
+
)
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const renderDateOutput = (
|
|
1581
|
+
leadingSymbol: string,
|
|
1582
|
+
trailingSymbol: string,
|
|
1583
|
+
parts: string,
|
|
1584
|
+
options: DateOptionsReq,
|
|
1585
|
+
renderOptions?: RenderOptions | undefined
|
|
1586
|
+
) => renderPrompt(parts, options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
1587
|
+
|
|
1588
|
+
const renderDateNextFrame = Effect.fnUntraced(function*(state: DateState, options: DateOptionsReq) {
|
|
1589
|
+
const figures = yield* platformFigures
|
|
1590
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
1591
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
1592
|
+
const parts = renderParts(state)
|
|
1593
|
+
const promptMsg = renderDateOutput(leadingSymbol, trailingSymbol, parts, options)
|
|
1594
|
+
const errorMsg = renderDateError(state, figures.pointerSmall)
|
|
1595
|
+
return Ansi.cursorHide + promptMsg + errorMsg
|
|
1596
|
+
})
|
|
1597
|
+
|
|
1598
|
+
const renderDateSubmission = Effect.fnUntraced(function*(state: DateState, options: DateOptionsReq) {
|
|
1599
|
+
const figures = yield* platformFigures
|
|
1600
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
1601
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
1602
|
+
const parts = renderParts(state, true)
|
|
1603
|
+
const promptMsg = renderDateOutput(leadingSymbol, trailingSymbol, parts, options)
|
|
1604
|
+
return promptMsg + "\n"
|
|
1605
|
+
})
|
|
1606
|
+
|
|
1607
|
+
const processUp = (state: DateState) => {
|
|
1608
|
+
state.dateParts[state.cursor].increment()
|
|
1609
|
+
return Action.NextFrame({
|
|
1610
|
+
state: { ...state, typed: "" }
|
|
1611
|
+
})
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
const processDown = (state: DateState) => {
|
|
1615
|
+
state.dateParts[state.cursor].decrement()
|
|
1616
|
+
return Action.NextFrame({
|
|
1617
|
+
state: { ...state, typed: "" }
|
|
1618
|
+
})
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
const processDateCursorLeft = (state: DateState) => {
|
|
1622
|
+
const previous = state.dateParts[state.cursor].previousPart()
|
|
1623
|
+
if (Option.isSome(previous)) {
|
|
1624
|
+
return Action.NextFrame({
|
|
1625
|
+
state: {
|
|
1626
|
+
...state,
|
|
1627
|
+
typed: "",
|
|
1628
|
+
cursor: state.dateParts.indexOf(previous.value)
|
|
1629
|
+
}
|
|
1630
|
+
})
|
|
1631
|
+
}
|
|
1632
|
+
return Action.Beep()
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
const processDateCursorRight = (state: DateState) => {
|
|
1636
|
+
const next = state.dateParts[state.cursor].nextPart()
|
|
1637
|
+
if (Option.isSome(next)) {
|
|
1638
|
+
return Action.NextFrame({
|
|
1639
|
+
state: {
|
|
1640
|
+
...state,
|
|
1641
|
+
typed: "",
|
|
1642
|
+
cursor: state.dateParts.indexOf(next.value)
|
|
1643
|
+
}
|
|
1644
|
+
})
|
|
1645
|
+
}
|
|
1646
|
+
return Action.Beep()
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
const processDateNext = (state: DateState) => {
|
|
1650
|
+
const next = state.dateParts[state.cursor].nextPart()
|
|
1651
|
+
const cursor = Option.match(next, {
|
|
1652
|
+
onNone: () => state.dateParts.findIndex((part) => !part.isToken()),
|
|
1653
|
+
onSome: (next) => state.dateParts.indexOf(next)
|
|
1654
|
+
})
|
|
1655
|
+
return Action.NextFrame({
|
|
1656
|
+
state: { ...state, cursor }
|
|
1657
|
+
})
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
const defaultDateProcessor = (value: string, state: DateState) => {
|
|
1661
|
+
if (/\d/.test(value)) {
|
|
1662
|
+
const typed = state.typed + value
|
|
1663
|
+
state.dateParts[state.cursor].setValue(typed)
|
|
1664
|
+
return Action.NextFrame({
|
|
1665
|
+
state: { ...state, typed }
|
|
1666
|
+
})
|
|
1667
|
+
}
|
|
1668
|
+
return Action.Beep()
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
const defaultLocales: DateOptionsReq["locales"] = {
|
|
1672
|
+
months: [
|
|
1673
|
+
"January",
|
|
1674
|
+
"February",
|
|
1675
|
+
"March",
|
|
1676
|
+
"April",
|
|
1677
|
+
"May",
|
|
1678
|
+
"June",
|
|
1679
|
+
"July",
|
|
1680
|
+
"August",
|
|
1681
|
+
"September",
|
|
1682
|
+
"October",
|
|
1683
|
+
"November",
|
|
1684
|
+
"December"
|
|
1685
|
+
],
|
|
1686
|
+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
|
1687
|
+
weekdays: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
|
1688
|
+
weekdaysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
const handleDateRender = (options: DateOptionsReq) => {
|
|
1692
|
+
return (state: DateState, action: Action<DateState, globalThis.Date>) => {
|
|
1693
|
+
return Action.$match(action, {
|
|
1694
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
1695
|
+
NextFrame: ({ state }) => renderDateNextFrame(state, options),
|
|
1696
|
+
Submit: () => renderDateSubmission(state, options)
|
|
1697
|
+
})
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
const handleDateProcess = (options: DateOptionsReq) => {
|
|
1702
|
+
return (input: Terminal.UserInput, state: DateState) => {
|
|
1703
|
+
switch (input.key.name) {
|
|
1704
|
+
case "left": {
|
|
1705
|
+
return Effect.succeed(processDateCursorLeft(state))
|
|
1706
|
+
}
|
|
1707
|
+
case "right": {
|
|
1708
|
+
return Effect.succeed(processDateCursorRight(state))
|
|
1709
|
+
}
|
|
1710
|
+
case "k":
|
|
1711
|
+
case "up": {
|
|
1712
|
+
return Effect.succeed(processUp(state))
|
|
1713
|
+
}
|
|
1714
|
+
case "j":
|
|
1715
|
+
case "down": {
|
|
1716
|
+
return Effect.succeed(processDown(state))
|
|
1717
|
+
}
|
|
1718
|
+
case "tab": {
|
|
1719
|
+
return Effect.succeed(processDateNext(state))
|
|
1720
|
+
}
|
|
1721
|
+
case "enter":
|
|
1722
|
+
case "return": {
|
|
1723
|
+
return Effect.match(options.validate(state.value), {
|
|
1724
|
+
onFailure: (error) =>
|
|
1725
|
+
Action.NextFrame({
|
|
1726
|
+
state: {
|
|
1727
|
+
...state,
|
|
1728
|
+
error: Option.some(error)
|
|
1729
|
+
}
|
|
1730
|
+
}),
|
|
1731
|
+
onSuccess: (value) => Action.Submit({ value })
|
|
1732
|
+
})
|
|
1733
|
+
}
|
|
1734
|
+
default: {
|
|
1735
|
+
return Effect.succeed(defaultDateProcessor(Option.getOrElse(input.input, () => ""), state))
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
const DATE_PART_REGEXP =
|
|
1742
|
+
/\\(.)|"((?:\\["\\]|[^"])+)"|(D[Do]?|d{3,4}|d)|(M{1,4})|(YY(?:YY)?)|([aA])|([Hh]{1,2})|(m{1,2})|(s{1,2})|(S{1,4})|./g
|
|
1743
|
+
|
|
1744
|
+
const regExpGroups: Record<number, (params: DatePartParams) => DatePart> = {
|
|
1745
|
+
1: ({ token, ...opts }) => new Token({ token: token.replace(/\\(.)/g, "$1"), ...opts }),
|
|
1746
|
+
2: (opts) => new Day(opts),
|
|
1747
|
+
3: (opts) => new Month(opts),
|
|
1748
|
+
4: (opts) => new Year(opts),
|
|
1749
|
+
5: (opts) => new Meridiem(opts),
|
|
1750
|
+
6: (opts) => new Hours(opts),
|
|
1751
|
+
7: (opts) => new Minutes(opts),
|
|
1752
|
+
8: (opts) => new Seconds(opts),
|
|
1753
|
+
9: (opts) => new Milliseconds(opts)
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
const makeDateParts = (
|
|
1757
|
+
dateMask: string,
|
|
1758
|
+
date: globalThis.Date,
|
|
1759
|
+
locales: DateOptions["locales"]
|
|
1760
|
+
) => {
|
|
1761
|
+
const parts: Array<DatePart> = []
|
|
1762
|
+
let result: RegExpExecArray | null = null
|
|
1763
|
+
// oxlint-disable-next-line no-cond-assign
|
|
1764
|
+
while (result = DATE_PART_REGEXP.exec(dateMask)) {
|
|
1765
|
+
const match = result.shift()
|
|
1766
|
+
const index = result.findIndex((group) => group !== undefined)
|
|
1767
|
+
if (index in regExpGroups) {
|
|
1768
|
+
const token = (result[index] || match)!
|
|
1769
|
+
parts.push(regExpGroups[index]({ token, date, parts, locales }))
|
|
1770
|
+
} else {
|
|
1771
|
+
parts.push(new Token({ token: (result[index] || match)!, date, parts, locales }))
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
const orderedParts = parts.reduce((array, element) => {
|
|
1775
|
+
const lastElement = array[array.length - 1]
|
|
1776
|
+
if (element.isToken() && lastElement !== undefined && lastElement.isToken()) {
|
|
1777
|
+
lastElement.setValue(element.token)
|
|
1778
|
+
} else {
|
|
1779
|
+
array.push(element)
|
|
1780
|
+
}
|
|
1781
|
+
return array
|
|
1782
|
+
}, Arr.empty<DatePart>())
|
|
1783
|
+
parts.splice(0, parts.length, ...orderedParts)
|
|
1784
|
+
return parts
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
interface DatePartParams {
|
|
1788
|
+
readonly token: string
|
|
1789
|
+
readonly locales: DateOptions["locales"]
|
|
1790
|
+
readonly date?: globalThis.Date
|
|
1791
|
+
readonly parts?: ReadonlyArray<DatePart>
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
abstract class DatePart {
|
|
1795
|
+
token: string
|
|
1796
|
+
readonly date: globalThis.Date
|
|
1797
|
+
readonly parts: ReadonlyArray<DatePart>
|
|
1798
|
+
readonly locales: DateOptions["locales"]
|
|
1799
|
+
|
|
1800
|
+
constructor(params: DatePartParams) {
|
|
1801
|
+
this.token = params.token
|
|
1802
|
+
this.locales = params.locales
|
|
1803
|
+
this.date = params.date || new Date()
|
|
1804
|
+
this.parts = params.parts || [this]
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
/**
|
|
1808
|
+
* Increments this date part.
|
|
1809
|
+
*/
|
|
1810
|
+
abstract increment(): void
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Decrements this date part.
|
|
1814
|
+
*/
|
|
1815
|
+
abstract decrement(): void
|
|
1816
|
+
|
|
1817
|
+
/**
|
|
1818
|
+
* Sets the current value of this date part to the provided value.
|
|
1819
|
+
*/
|
|
1820
|
+
abstract setValue(value: string): void
|
|
1821
|
+
|
|
1822
|
+
/**
|
|
1823
|
+
* Returns `true` if this `DatePart` is a `Token`, `false` otherwise.
|
|
1824
|
+
*/
|
|
1825
|
+
isToken(): this is Token {
|
|
1826
|
+
return false
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* Retrieves the next date part in the list of parts.
|
|
1831
|
+
*/
|
|
1832
|
+
nextPart(): Option.Option<DatePart> {
|
|
1833
|
+
const currentPartIndex = Option.getOrElse(Arr.findFirstIndex(this.parts, (part) => part === this), () => 0)
|
|
1834
|
+
return Arr.findFirst(this.parts.slice(currentPartIndex + 1), (part) => !part.isToken())
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/**
|
|
1838
|
+
* Retrieves the previous date part in the list of parts.
|
|
1839
|
+
*/
|
|
1840
|
+
previousPart(): Option.Option<DatePart> {
|
|
1841
|
+
const currentPartIndex = Arr.findFirstIndex(this.parts, (part) => part === this)
|
|
1842
|
+
if (Option.isSome(currentPartIndex)) {
|
|
1843
|
+
return Arr.findLast(this.parts.slice(0, currentPartIndex.value), (part) => !part.isToken())
|
|
1844
|
+
}
|
|
1845
|
+
return Option.none()
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
toString() {
|
|
1849
|
+
return String(this.date)
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
class Token extends DatePart {
|
|
1854
|
+
increment(): void {}
|
|
1855
|
+
|
|
1856
|
+
decrement(): void {}
|
|
1857
|
+
|
|
1858
|
+
setValue(value: string): void {
|
|
1859
|
+
this.token = this.token + value
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
override isToken(): this is Token {
|
|
1863
|
+
return true
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
override toString() {
|
|
1867
|
+
return this.token
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
class Milliseconds extends DatePart {
|
|
1872
|
+
increment(): void {
|
|
1873
|
+
this.date.setMilliseconds(this.date.getMilliseconds() + 1)
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
decrement(): void {
|
|
1877
|
+
this.date.setMilliseconds(this.date.getMilliseconds() - 1)
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
setValue(value: string): void {
|
|
1881
|
+
this.date.setMilliseconds(Number.parseInt(value.slice(-this.token.length)))
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
override toString() {
|
|
1885
|
+
const millis = `${this.date.getMilliseconds()}`
|
|
1886
|
+
return millis.padStart(4, "0").substring(0, this.token.length)
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
class Seconds extends DatePart {
|
|
1891
|
+
increment(): void {
|
|
1892
|
+
this.date.setSeconds(this.date.getSeconds() + 1)
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
decrement(): void {
|
|
1896
|
+
this.date.setSeconds(this.date.getSeconds() - 1)
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
setValue(value: string): void {
|
|
1900
|
+
this.date.setSeconds(Number.parseInt(value.slice(-2)))
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
override toString() {
|
|
1904
|
+
const seconds = `${this.date.getSeconds()}`
|
|
1905
|
+
return this.token.length > 1
|
|
1906
|
+
? seconds.padStart(2, "0")
|
|
1907
|
+
: seconds
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
class Minutes extends DatePart {
|
|
1912
|
+
increment(): void {
|
|
1913
|
+
this.date.setMinutes(this.date.getMinutes() + 1)
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
decrement(): void {
|
|
1917
|
+
this.date.setMinutes(this.date.getMinutes() - 1)
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
setValue(value: string): void {
|
|
1921
|
+
this.date.setMinutes(Number.parseInt(value.slice(-2)))
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
override toString() {
|
|
1925
|
+
const minutes = `${this.date.getMinutes()}`
|
|
1926
|
+
return this.token.length > 1
|
|
1927
|
+
? minutes.padStart(2, "0") :
|
|
1928
|
+
minutes
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
class Hours extends DatePart {
|
|
1933
|
+
increment(): void {
|
|
1934
|
+
this.date.setHours(this.date.getHours() + 1)
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
decrement(): void {
|
|
1938
|
+
this.date.setHours(this.date.getHours() - 1)
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
setValue(value: string): void {
|
|
1942
|
+
this.date.setHours(Number.parseInt(value.slice(-2)))
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
override toString() {
|
|
1946
|
+
const hours = /h/.test(this.token)
|
|
1947
|
+
? this.date.getHours() % 12 || 12
|
|
1948
|
+
: this.date.getHours()
|
|
1949
|
+
return this.token.length > 1
|
|
1950
|
+
? `${hours}`.padStart(2, "0")
|
|
1951
|
+
: `${hours}`
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
class Day extends DatePart {
|
|
1956
|
+
increment(): void {
|
|
1957
|
+
this.date.setDate(this.date.getDate() + 1)
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
decrement(): void {
|
|
1961
|
+
this.date.setDate(this.date.getDate() - 1)
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
setValue(value: string): void {
|
|
1965
|
+
this.date.setDate(Number.parseInt(value.slice(-2)))
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
override toString() {
|
|
1969
|
+
const date = this.date.getDate()
|
|
1970
|
+
const day = this.date.getDay()
|
|
1971
|
+
switch (this.token) {
|
|
1972
|
+
case "DD":
|
|
1973
|
+
return `${date}`.padStart(2, "0")
|
|
1974
|
+
case "Do":
|
|
1975
|
+
return `${date}${this.ordinalIndicator(date)}`
|
|
1976
|
+
case "d":
|
|
1977
|
+
return `${day + 1}`
|
|
1978
|
+
case "ddd":
|
|
1979
|
+
return this.locales!.weekdaysShort[day]!
|
|
1980
|
+
case "dddd":
|
|
1981
|
+
return this.locales!.weekdays[day]!
|
|
1982
|
+
default:
|
|
1983
|
+
return `${date}`
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
private ordinalIndicator(day: number): string {
|
|
1988
|
+
switch (day % 10) {
|
|
1989
|
+
case 1:
|
|
1990
|
+
return "st"
|
|
1991
|
+
case 2:
|
|
1992
|
+
return "nd"
|
|
1993
|
+
case 3:
|
|
1994
|
+
return "rd"
|
|
1995
|
+
default:
|
|
1996
|
+
return "th"
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
class Month extends DatePart {
|
|
2002
|
+
increment(): void {
|
|
2003
|
+
this.date.setMonth(this.date.getMonth() + 1)
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
decrement(): void {
|
|
2007
|
+
this.date.setMonth(this.date.getMonth() - 1)
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
setValue(value: string): void {
|
|
2011
|
+
const month = Number.parseInt(value.slice(-2)) - 1
|
|
2012
|
+
this.date.setMonth(month < 0 ? 0 : month)
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
override toString() {
|
|
2016
|
+
const month = this.date.getMonth()
|
|
2017
|
+
switch (this.token.length) {
|
|
2018
|
+
case 2:
|
|
2019
|
+
return `${month + 1}`.padStart(2, "0")
|
|
2020
|
+
case 3:
|
|
2021
|
+
return this.locales!.monthsShort[month]!
|
|
2022
|
+
case 4:
|
|
2023
|
+
return this.locales!.months[month]!
|
|
2024
|
+
default:
|
|
2025
|
+
return `${month + 1}`
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
class Year extends DatePart {
|
|
2031
|
+
increment(): void {
|
|
2032
|
+
this.date.setFullYear(this.date.getFullYear() + 1)
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
decrement(): void {
|
|
2036
|
+
this.date.setFullYear(this.date.getFullYear() - 1)
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
setValue(value: string): void {
|
|
2040
|
+
this.date.setFullYear(Number.parseInt(value.slice(-4)))
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
override toString() {
|
|
2044
|
+
const year = `${this.date.getFullYear()}`.padStart(4, "0")
|
|
2045
|
+
return this.token.length === 2
|
|
2046
|
+
? year.substring(-2)
|
|
2047
|
+
: year
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
class Meridiem extends DatePart {
|
|
2052
|
+
increment(): void {
|
|
2053
|
+
this.date.setHours((this.date.getHours() + 12) % 24)
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
decrement(): void {
|
|
2057
|
+
this.increment()
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
setValue(_value: string): void {}
|
|
2061
|
+
|
|
2062
|
+
override toString() {
|
|
2063
|
+
const meridiem = this.date.getHours() > 12 ? "pm" : "am"
|
|
2064
|
+
return /A/.test(this.token)
|
|
2065
|
+
? meridiem.toUpperCase()
|
|
2066
|
+
: meridiem
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
interface FileOptionsReq extends Required<Omit<FileOptions, "startingPath" | "default">> {
|
|
2071
|
+
readonly startingPath: Option.Option<string>
|
|
2072
|
+
readonly default: Option.Option<string>
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
interface FileState {
|
|
2076
|
+
readonly cursor: number
|
|
2077
|
+
readonly files: ReadonlyArray<string>
|
|
2078
|
+
readonly allFiles: ReadonlyArray<string>
|
|
2079
|
+
readonly query: string
|
|
2080
|
+
readonly path: Option.Option<string>
|
|
2081
|
+
readonly confirm: Confirm
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
const CONFIRM_MESSAGE = "The selected directory contains files. Would you like to traverse the selected directory?"
|
|
2085
|
+
const FILE_FILTER_LABEL = "filter"
|
|
2086
|
+
const FILE_FILTER_PLACEHOLDER = "type to filter"
|
|
2087
|
+
const FILE_EMPTY_MESSAGE = "No matches"
|
|
2088
|
+
type Confirm = Data.TaggedEnum<{
|
|
2089
|
+
readonly Show: {}
|
|
2090
|
+
readonly Hide: {}
|
|
2091
|
+
}>
|
|
2092
|
+
const Confirm = Data.taggedEnum<Confirm>()
|
|
2093
|
+
|
|
2094
|
+
const showConfirmation = Confirm.$is("Show")
|
|
2095
|
+
|
|
2096
|
+
const resolveCurrentPath = (
|
|
2097
|
+
path: Option.Option<string>,
|
|
2098
|
+
options: FileOptionsReq
|
|
2099
|
+
): Effect.Effect<string, never, FileSystem.FileSystem> => {
|
|
2100
|
+
if (Option.isSome(path)) {
|
|
2101
|
+
return Effect.succeed(path.value)
|
|
2102
|
+
}
|
|
2103
|
+
if (Option.isSome(options.startingPath)) {
|
|
2104
|
+
const startingPath = options.startingPath.value
|
|
2105
|
+
return Effect.flatMap(FileSystem.FileSystem, (fs) =>
|
|
2106
|
+
// Ensure the user provided starting path exists
|
|
2107
|
+
Effect.orDie(fs.exists(startingPath)).pipe(
|
|
2108
|
+
Effect.flatMap((exists) =>
|
|
2109
|
+
exists ? Effect.void : Effect.die(
|
|
2110
|
+
`The provided starting path '${startingPath}' does not exist`
|
|
2111
|
+
)
|
|
2112
|
+
),
|
|
2113
|
+
Effect.as(startingPath)
|
|
2114
|
+
))
|
|
2115
|
+
}
|
|
2116
|
+
return Effect.sync(() => process.cwd())
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
const getFileList = Effect.fnUntraced(function*(directory: string, options: FileOptionsReq) {
|
|
2120
|
+
const fs = yield* FileSystem.FileSystem
|
|
2121
|
+
const path = yield* Path.Path
|
|
2122
|
+
const files = yield* Effect.orDie(fs.readDirectory(directory)).pipe(
|
|
2123
|
+
// Always prepend the `".."` option to the file list but allow it
|
|
2124
|
+
// to be filtered out if the user so desires
|
|
2125
|
+
Effect.map((files) => ["..", ...files])
|
|
2126
|
+
)
|
|
2127
|
+
return yield* Effect.filter(files, (file) => {
|
|
2128
|
+
const result = options.filter(file)
|
|
2129
|
+
const userDefinedFilter = Effect.isEffect(result)
|
|
2130
|
+
? result
|
|
2131
|
+
: Effect.succeed(result)
|
|
2132
|
+
const directoryFilter = options.type === "directory"
|
|
2133
|
+
? Effect.map(
|
|
2134
|
+
Effect.orDie(fs.stat(path.join(directory, file))),
|
|
2135
|
+
(info) => info.type === "Directory"
|
|
2136
|
+
)
|
|
2137
|
+
: Effect.succeed(true)
|
|
2138
|
+
return Effect.zipWith(userDefinedFilter, directoryFilter, (a, b) => a && b)
|
|
2139
|
+
}, { concurrency: files.length })
|
|
2140
|
+
})
|
|
2141
|
+
|
|
2142
|
+
const filterFiles = (files: ReadonlyArray<string>, query: string) => {
|
|
2143
|
+
if (query.length === 0) {
|
|
2144
|
+
return files
|
|
2145
|
+
}
|
|
2146
|
+
const normalizedQuery = query.toLowerCase()
|
|
2147
|
+
const filtered: Array<string> = []
|
|
2148
|
+
for (let index = 0; index < files.length; index++) {
|
|
2149
|
+
if (files[index].toLowerCase().includes(normalizedQuery)) {
|
|
2150
|
+
filtered.push(files[index])
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
return filtered
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
const updateFileState = (
|
|
2157
|
+
state: FileState,
|
|
2158
|
+
query: string,
|
|
2159
|
+
allFiles: ReadonlyArray<string> = state.allFiles
|
|
2160
|
+
): FileState => {
|
|
2161
|
+
const files = filterFiles(allFiles, query)
|
|
2162
|
+
if (files.length === 0) {
|
|
2163
|
+
return { ...state, query, allFiles, files, cursor: 0 }
|
|
2164
|
+
}
|
|
2165
|
+
const selected = state.files[state.cursor]
|
|
2166
|
+
const cursor = selected === undefined ? 0 : files.indexOf(selected)
|
|
2167
|
+
return {
|
|
2168
|
+
...state,
|
|
2169
|
+
query,
|
|
2170
|
+
allFiles,
|
|
2171
|
+
files,
|
|
2172
|
+
cursor: cursor === -1 ? 0 : cursor
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
const handleFileClear = (options: FileOptionsReq) => {
|
|
2177
|
+
return Effect.fnUntraced(function*(state: FileState, _: Action<FileState, string>) {
|
|
2178
|
+
const terminal = yield* Terminal.Terminal
|
|
2179
|
+
const columns = yield* terminal.columns
|
|
2180
|
+
const path = yield* Path.Path
|
|
2181
|
+
const figures = yield* platformFigures
|
|
2182
|
+
const currentPath = yield* resolveCurrentPath(state.path, options)
|
|
2183
|
+
const selectedPath = state.files[state.cursor]
|
|
2184
|
+
const resolvedPath = selectedPath === undefined ? currentPath : path.resolve(currentPath, selectedPath)
|
|
2185
|
+
const resolvedPathText = `${figures.pointerSmall} ${resolvedPath}`
|
|
2186
|
+
const isConfirming = showConfirmation(state.confirm)
|
|
2187
|
+
const promptText = isConfirming
|
|
2188
|
+
? renderPrompt("(Y/n)", CONFIRM_MESSAGE, "?", figures.pointerSmall, { plain: true })
|
|
2189
|
+
: renderPrompt(renderFileFilter(state, { plain: true }), options.message, figures.tick, figures.ellipsis, {
|
|
2190
|
+
plain: true
|
|
2191
|
+
})
|
|
2192
|
+
const filesText = isConfirming
|
|
2193
|
+
? ""
|
|
2194
|
+
: renderFiles(state, state.files, figures, options, { plain: true })
|
|
2195
|
+
const outputText = isConfirming
|
|
2196
|
+
? `${promptText}\n${resolvedPathText}`
|
|
2197
|
+
: `${promptText}\n${resolvedPathText}\n${filesText}`
|
|
2198
|
+
const clearOutput = eraseText(outputText, columns)
|
|
2199
|
+
const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft
|
|
2200
|
+
return clearOutput + resetCurrentLine
|
|
2201
|
+
})
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
type RenderOptions = {
|
|
2205
|
+
readonly plain?: boolean
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
const renderPrompt = (
|
|
2209
|
+
confirm: string,
|
|
2210
|
+
message: string,
|
|
2211
|
+
leadingSymbol: string,
|
|
2212
|
+
trailingSymbol: string,
|
|
2213
|
+
options?: RenderOptions | undefined
|
|
2214
|
+
) => {
|
|
2215
|
+
const prefix = leadingSymbol + " "
|
|
2216
|
+
const annotate = options?.plain === true
|
|
2217
|
+
? (line: string) => line
|
|
2218
|
+
: annotateLine
|
|
2219
|
+
return Arr.match(message.split(NEWLINE_REGEXP), {
|
|
2220
|
+
onEmpty: () => prefix + " " + trailingSymbol + " " + confirm,
|
|
2221
|
+
onNonEmpty: (promptLines) => {
|
|
2222
|
+
const lines = Arr.map(promptLines, (line) => annotate(line))
|
|
2223
|
+
return prefix + lines.join("\n") + " " + trailingSymbol + " " + confirm
|
|
2224
|
+
}
|
|
2225
|
+
})
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
const renderPrefix = (
|
|
2229
|
+
state: FileState,
|
|
2230
|
+
toDisplay: { readonly startIndex: number; readonly endIndex: number },
|
|
2231
|
+
currentIndex: number,
|
|
2232
|
+
length: number,
|
|
2233
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
2234
|
+
renderOptions?: RenderOptions | undefined
|
|
2235
|
+
) => {
|
|
2236
|
+
let prefix = " "
|
|
2237
|
+
if (currentIndex === toDisplay.startIndex && toDisplay.startIndex > 0) {
|
|
2238
|
+
prefix = figures.arrowUp
|
|
2239
|
+
} else if (currentIndex === toDisplay.endIndex - 1 && toDisplay.endIndex < length) {
|
|
2240
|
+
prefix = figures.arrowDown
|
|
2241
|
+
}
|
|
2242
|
+
if (state.cursor === currentIndex) {
|
|
2243
|
+
return renderOptions?.plain === true
|
|
2244
|
+
? figures.pointer + prefix
|
|
2245
|
+
: Ansi.annotate(figures.pointer, Ansi.cyanBright) + prefix
|
|
2246
|
+
}
|
|
2247
|
+
return prefix + " "
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
const renderFileName = (file: string, isSelected: boolean, renderOptions?: RenderOptions | undefined) => {
|
|
2251
|
+
if (renderOptions?.plain === true) {
|
|
2252
|
+
return file
|
|
2253
|
+
}
|
|
2254
|
+
return isSelected
|
|
2255
|
+
? Ansi.annotate(file, Ansi.combine(Ansi.underlined, Ansi.cyanBright))
|
|
2256
|
+
: file
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
const renderFileFilter = (state: FileState, renderOptions?: RenderOptions | undefined) => {
|
|
2260
|
+
const filterValue = state.query.length === 0
|
|
2261
|
+
? renderOptions?.plain === true
|
|
2262
|
+
? FILE_FILTER_PLACEHOLDER
|
|
2263
|
+
: Ansi.annotate(FILE_FILTER_PLACEHOLDER, Ansi.blackBright)
|
|
2264
|
+
: renderOptions?.plain === true
|
|
2265
|
+
? state.query
|
|
2266
|
+
: Ansi.annotate(state.query, Ansi.combine(Ansi.underlined, Ansi.cyanBright))
|
|
2267
|
+
return `[${FILE_FILTER_LABEL}: ${filterValue}]`
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
const renderFiles = (
|
|
2271
|
+
state: FileState,
|
|
2272
|
+
files: ReadonlyArray<string>,
|
|
2273
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
2274
|
+
options: FileOptionsReq,
|
|
2275
|
+
renderOptions?: RenderOptions | undefined
|
|
2276
|
+
) => {
|
|
2277
|
+
const length = files.length
|
|
2278
|
+
if (length === 0) {
|
|
2279
|
+
return renderOptions?.plain === true
|
|
2280
|
+
? FILE_EMPTY_MESSAGE
|
|
2281
|
+
: Ansi.annotate(FILE_EMPTY_MESSAGE, Ansi.blackBright)
|
|
2282
|
+
}
|
|
2283
|
+
const toDisplay = entriesToDisplay(state.cursor, length, options.maxPerPage)
|
|
2284
|
+
const documents: Array<string> = []
|
|
2285
|
+
for (let index = toDisplay.startIndex; index < toDisplay.endIndex; index++) {
|
|
2286
|
+
const isSelected = state.cursor === index
|
|
2287
|
+
const prefix = renderPrefix(state, toDisplay, index, length, figures, renderOptions)
|
|
2288
|
+
const fileName = renderFileName(files[index], isSelected, renderOptions)
|
|
2289
|
+
documents.push(prefix + fileName)
|
|
2290
|
+
}
|
|
2291
|
+
return documents.join("\n")
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
const renderFileNextFrame = Effect.fnUntraced(function*(state: FileState, options: FileOptionsReq) {
|
|
2295
|
+
const path = yield* Path.Path
|
|
2296
|
+
const figures = yield* platformFigures
|
|
2297
|
+
const currentPath = yield* resolveCurrentPath(state.path, options)
|
|
2298
|
+
const selectedPath = state.files[state.cursor]
|
|
2299
|
+
const resolvedPath = selectedPath === undefined ? currentPath : path.resolve(currentPath, selectedPath)
|
|
2300
|
+
const resolvedPathMsg = Ansi.annotate(figures.pointerSmall + " " + resolvedPath, Ansi.blackBright)
|
|
2301
|
+
|
|
2302
|
+
if (showConfirmation(state.confirm)) {
|
|
2303
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
2304
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
2305
|
+
const confirm = Ansi.annotate("(Y/n)", Ansi.blackBright)
|
|
2306
|
+
const promptMsg = renderPrompt(confirm, CONFIRM_MESSAGE, leadingSymbol, trailingSymbol)
|
|
2307
|
+
return Ansi.cursorHide + promptMsg + "\n" + resolvedPathMsg
|
|
2308
|
+
}
|
|
2309
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
2310
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
2311
|
+
const promptMsg = renderPrompt(renderFileFilter(state), options.message, leadingSymbol, trailingSymbol)
|
|
2312
|
+
const files = renderFiles(state, state.files, figures, options)
|
|
2313
|
+
return Ansi.cursorHide + promptMsg + "\n" + resolvedPathMsg + "\n" + files
|
|
2314
|
+
})
|
|
2315
|
+
|
|
2316
|
+
const renderFileSubmission = Effect.fnUntraced(function*(state: FileState, value: string, options: FileOptionsReq) {
|
|
2317
|
+
const figures = yield* platformFigures
|
|
2318
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
2319
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
2320
|
+
const promptMsg = renderPrompt(renderFileFilter(state), options.message, leadingSymbol, trailingSymbol)
|
|
2321
|
+
return promptMsg + " " + Ansi.annotate(value, Ansi.white) + "\n"
|
|
2322
|
+
})
|
|
2323
|
+
|
|
2324
|
+
const handleFileRender = (options: FileOptionsReq) => {
|
|
2325
|
+
return (
|
|
2326
|
+
state: FileState,
|
|
2327
|
+
action: Action<FileState, string>
|
|
2328
|
+
): Effect.Effect<string, never, Path.Path | FileSystem.FileSystem> => {
|
|
2329
|
+
return Action.$match(action, {
|
|
2330
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
2331
|
+
NextFrame: ({ state }) => renderFileNextFrame(state, options),
|
|
2332
|
+
Submit: ({ value }) => renderFileSubmission(state, value, options)
|
|
2333
|
+
})
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
const processFileCursorUp = (state: FileState) => {
|
|
2338
|
+
if (state.files.length === 0) {
|
|
2339
|
+
return Effect.succeed(Action.Beep())
|
|
2340
|
+
}
|
|
2341
|
+
const cursor = state.cursor - 1
|
|
2342
|
+
return Effect.succeed(Action.NextFrame({
|
|
2343
|
+
state: { ...state, cursor: cursor < 0 ? state.files.length - 1 : cursor }
|
|
2344
|
+
}))
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
const processFileCursorDown = (state: FileState) => {
|
|
2348
|
+
if (state.files.length === 0) {
|
|
2349
|
+
return Effect.succeed(Action.Beep())
|
|
2350
|
+
}
|
|
2351
|
+
return Effect.succeed(Action.NextFrame({
|
|
2352
|
+
state: { ...state, cursor: (state.cursor + 1) % state.files.length }
|
|
2353
|
+
}))
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
const processFileBackspace = (state: FileState) => {
|
|
2357
|
+
if (state.query.length === 0) {
|
|
2358
|
+
return Effect.succeed(Action.Beep())
|
|
2359
|
+
}
|
|
2360
|
+
const query = state.query.slice(0, state.query.length - 1)
|
|
2361
|
+
return Effect.succeed(Action.NextFrame({ state: updateFileState(state, query) }))
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
const processFileClear = (state: FileState) => Effect.succeed(Action.NextFrame({ state: updateFileState(state, "") }))
|
|
2365
|
+
|
|
2366
|
+
const processFileInput = (input: string, state: FileState) => {
|
|
2367
|
+
if (input.length === 0) {
|
|
2368
|
+
return Effect.succeed(Action.Beep())
|
|
2369
|
+
}
|
|
2370
|
+
const query = state.query + input
|
|
2371
|
+
return Effect.succeed(Action.NextFrame({ state: updateFileState(state, query) }))
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
const processSelection = Effect.fnUntraced(function*(state: FileState, options: FileOptionsReq) {
|
|
2375
|
+
if (state.files.length === 0) {
|
|
2376
|
+
return Action.Beep()
|
|
2377
|
+
}
|
|
2378
|
+
const fs = yield* FileSystem.FileSystem
|
|
2379
|
+
const path = yield* Path.Path
|
|
2380
|
+
const currentPath = yield* resolveCurrentPath(state.path, options)
|
|
2381
|
+
const selectedPath = state.files[state.cursor]
|
|
2382
|
+
const resolvedPath = path.resolve(currentPath, selectedPath)
|
|
2383
|
+
const info = yield* Effect.orDie(fs.stat(resolvedPath))
|
|
2384
|
+
if (info.type === "Directory") {
|
|
2385
|
+
const files = yield* getFileList(resolvedPath, options)
|
|
2386
|
+
const filesWithoutParent = files.filter((file) => file !== "..")
|
|
2387
|
+
// If the user selected a directory AND the prompt type can result with
|
|
2388
|
+
// a directory, we must confirm:
|
|
2389
|
+
// - If the selected directory has any files
|
|
2390
|
+
// - Confirm whether or not the user wants to traverse those files
|
|
2391
|
+
if (options.type === "directory" || options.type === "either") {
|
|
2392
|
+
return filesWithoutParent.length === 0
|
|
2393
|
+
// Directory is empty so it's safe to select it
|
|
2394
|
+
? Action.Submit({ value: resolvedPath })
|
|
2395
|
+
// Directory has contents - show confirmation to user
|
|
2396
|
+
: Action.NextFrame({
|
|
2397
|
+
state: { ...state, confirm: Confirm.Show() }
|
|
2398
|
+
})
|
|
2399
|
+
}
|
|
2400
|
+
return Action.NextFrame({
|
|
2401
|
+
state: {
|
|
2402
|
+
cursor: 0,
|
|
2403
|
+
files,
|
|
2404
|
+
allFiles: files,
|
|
2405
|
+
query: "",
|
|
2406
|
+
path: Option.some(resolvedPath),
|
|
2407
|
+
confirm: Confirm.Hide()
|
|
2408
|
+
}
|
|
2409
|
+
})
|
|
2410
|
+
}
|
|
2411
|
+
return Action.Submit({ value: resolvedPath })
|
|
2412
|
+
})
|
|
2413
|
+
|
|
2414
|
+
const handleFileProcess = (options: FileOptionsReq) => {
|
|
2415
|
+
return Effect.fnUntraced(function*(input: Terminal.UserInput, state: FileState) {
|
|
2416
|
+
if (input.key.ctrl) {
|
|
2417
|
+
if (input.key.name === "u") {
|
|
2418
|
+
if (showConfirmation(state.confirm)) {
|
|
2419
|
+
return Action.Beep()
|
|
2420
|
+
}
|
|
2421
|
+
return yield* processFileClear(state)
|
|
2422
|
+
}
|
|
2423
|
+
return Action.Beep()
|
|
2424
|
+
}
|
|
2425
|
+
switch (input.key.name) {
|
|
2426
|
+
case "k":
|
|
2427
|
+
case "up": {
|
|
2428
|
+
return yield* processFileCursorUp(state)
|
|
2429
|
+
}
|
|
2430
|
+
case "j":
|
|
2431
|
+
case "down":
|
|
2432
|
+
case "tab": {
|
|
2433
|
+
return yield* processFileCursorDown(state)
|
|
2434
|
+
}
|
|
2435
|
+
case "backspace": {
|
|
2436
|
+
if (showConfirmation(state.confirm)) {
|
|
2437
|
+
return Action.Beep()
|
|
2438
|
+
}
|
|
2439
|
+
return yield* processFileBackspace(state)
|
|
2440
|
+
}
|
|
2441
|
+
case "enter":
|
|
2442
|
+
case "return": {
|
|
2443
|
+
return yield* processSelection(state, options)
|
|
2444
|
+
}
|
|
2445
|
+
case "y":
|
|
2446
|
+
case "t": {
|
|
2447
|
+
if (showConfirmation(state.confirm)) {
|
|
2448
|
+
const path = yield* Path.Path
|
|
2449
|
+
const currentPath = yield* resolveCurrentPath(state.path, options)
|
|
2450
|
+
const selectedPath = state.files[state.cursor]
|
|
2451
|
+
const resolvedPath = path.resolve(currentPath, selectedPath)
|
|
2452
|
+
const files = yield* getFileList(resolvedPath, options)
|
|
2453
|
+
return Action.NextFrame({
|
|
2454
|
+
state: {
|
|
2455
|
+
cursor: 0,
|
|
2456
|
+
files,
|
|
2457
|
+
allFiles: files,
|
|
2458
|
+
query: "",
|
|
2459
|
+
path: Option.some(resolvedPath),
|
|
2460
|
+
confirm: Confirm.Hide()
|
|
2461
|
+
}
|
|
2462
|
+
})
|
|
2463
|
+
}
|
|
2464
|
+
return yield* processFileInput(Option.getOrElse(input.input, () => ""), state)
|
|
2465
|
+
}
|
|
2466
|
+
case "n":
|
|
2467
|
+
case "f": {
|
|
2468
|
+
if (showConfirmation(state.confirm)) {
|
|
2469
|
+
const path = yield* Path.Path
|
|
2470
|
+
const currentPath = yield* resolveCurrentPath(state.path, options)
|
|
2471
|
+
const selectedPath = state.files[state.cursor]
|
|
2472
|
+
const resolvedPath = path.resolve(currentPath, selectedPath)
|
|
2473
|
+
return Action.Submit({ value: resolvedPath })
|
|
2474
|
+
}
|
|
2475
|
+
return yield* processFileInput(Option.getOrElse(input.input, () => ""), state)
|
|
2476
|
+
}
|
|
2477
|
+
default: {
|
|
2478
|
+
if (showConfirmation(state.confirm)) {
|
|
2479
|
+
return Action.Beep()
|
|
2480
|
+
}
|
|
2481
|
+
return yield* processFileInput(Option.getOrElse(input.input, () => ""), state)
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
})
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
interface SelectOptionsReq<A> extends Required<SelectOptions<A>> {}
|
|
2488
|
+
interface MultiSelectOptionsReq extends MultiSelectOptions {}
|
|
2489
|
+
|
|
2490
|
+
type MultiSelectState = {
|
|
2491
|
+
index: number
|
|
2492
|
+
selectedIndices: Set<number>
|
|
2493
|
+
error: Option.Option<string>
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
const renderMultiSelectError = (
|
|
2497
|
+
state: MultiSelectState,
|
|
2498
|
+
pointer: string,
|
|
2499
|
+
renderOptions?: RenderOptions | undefined
|
|
2500
|
+
): string => {
|
|
2501
|
+
if (Option.isSome(state.error)) {
|
|
2502
|
+
return Arr.match(state.error.value.split(NEWLINE_REGEXP), {
|
|
2503
|
+
onEmpty: () => "",
|
|
2504
|
+
onNonEmpty: (errorLines) => {
|
|
2505
|
+
if (renderOptions?.plain === true) {
|
|
2506
|
+
return `${pointer} ${errorLines.join("\n")}`
|
|
2507
|
+
}
|
|
2508
|
+
const prefix = Ansi.annotate(pointer, Ansi.red) + " "
|
|
2509
|
+
const lines = Arr.map(errorLines, (str) => annotateErrorLine(str))
|
|
2510
|
+
return Ansi.cursorSavePosition + "\n" + prefix + lines.join("\n") + Ansi.cursorRestorePosition
|
|
2511
|
+
}
|
|
2512
|
+
})
|
|
2513
|
+
}
|
|
2514
|
+
return ""
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
const renderChoiceDescription = <A>(
|
|
2518
|
+
choice: SelectChoice<A>,
|
|
2519
|
+
isActive: boolean,
|
|
2520
|
+
renderOptions?: RenderOptions | undefined
|
|
2521
|
+
) => {
|
|
2522
|
+
if (!choice.disabled && choice.description && isActive) {
|
|
2523
|
+
return renderOptions?.plain === true
|
|
2524
|
+
? "- " + choice.description
|
|
2525
|
+
: Ansi.annotate("- " + choice.description, Ansi.blackBright)
|
|
2526
|
+
}
|
|
2527
|
+
return ""
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
const metaOptionsCount = 2
|
|
2531
|
+
|
|
2532
|
+
const renderMultiSelectTitle = (
|
|
2533
|
+
title: string,
|
|
2534
|
+
isHighlighted: boolean,
|
|
2535
|
+
renderOptions?: RenderOptions | undefined
|
|
2536
|
+
) => {
|
|
2537
|
+
if (renderOptions?.plain === true || !isHighlighted) {
|
|
2538
|
+
return title
|
|
2539
|
+
}
|
|
2540
|
+
return Ansi.annotate(title, Ansi.combine(Ansi.underlined, Ansi.cyanBright))
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
const renderMultiSelectChoices = <A>(
|
|
2544
|
+
state: MultiSelectState,
|
|
2545
|
+
options: SelectOptionsReq<A> & MultiSelectOptionsReq,
|
|
2546
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
2547
|
+
renderOptions?: RenderOptions | undefined
|
|
2548
|
+
) => {
|
|
2549
|
+
const choices = options.choices
|
|
2550
|
+
const totalChoices = choices.length
|
|
2551
|
+
const selectedCount = state.selectedIndices.size
|
|
2552
|
+
const allSelected = selectedCount === totalChoices
|
|
2553
|
+
|
|
2554
|
+
const selectAllText = allSelected
|
|
2555
|
+
? options?.selectNone ?? "Select None"
|
|
2556
|
+
: options?.selectAll ?? "Select All"
|
|
2557
|
+
|
|
2558
|
+
const inverseSelectionText = options?.inverseSelection ?? "Inverse Selection"
|
|
2559
|
+
|
|
2560
|
+
const metaOptions = [
|
|
2561
|
+
{ title: selectAllText },
|
|
2562
|
+
{ title: inverseSelectionText }
|
|
2563
|
+
]
|
|
2564
|
+
const allChoices = [...metaOptions, ...choices]
|
|
2565
|
+
const toDisplay = entriesToDisplay(state.index, allChoices.length, options.maxPerPage)
|
|
2566
|
+
const documents: Array<string> = []
|
|
2567
|
+
for (let index = toDisplay.startIndex; index < toDisplay.endIndex; index++) {
|
|
2568
|
+
const choice = allChoices[index]
|
|
2569
|
+
const isHighlighted = state.index === index
|
|
2570
|
+
let prefix = " "
|
|
2571
|
+
if (index === toDisplay.startIndex && toDisplay.startIndex > 0) {
|
|
2572
|
+
prefix = figures.arrowUp
|
|
2573
|
+
} else if (index === toDisplay.endIndex - 1 && toDisplay.endIndex < allChoices.length) {
|
|
2574
|
+
prefix = figures.arrowDown
|
|
2575
|
+
}
|
|
2576
|
+
if (index < metaOptions.length) {
|
|
2577
|
+
// Meta options
|
|
2578
|
+
const title = renderMultiSelectTitle(choice.title, isHighlighted, renderOptions)
|
|
2579
|
+
documents.push(prefix + " " + title)
|
|
2580
|
+
} else {
|
|
2581
|
+
// Regular choices
|
|
2582
|
+
const choiceIndex = index - metaOptions.length
|
|
2583
|
+
const isSelected = state.selectedIndices.has(choiceIndex)
|
|
2584
|
+
const checkbox = isSelected ? figures.checkboxOn : figures.checkboxOff
|
|
2585
|
+
const annotatedCheckbox = isHighlighted && renderOptions?.plain !== true
|
|
2586
|
+
? Ansi.annotate(checkbox, Ansi.cyanBright)
|
|
2587
|
+
: checkbox
|
|
2588
|
+
const title = renderMultiSelectTitle(choice.title, isHighlighted, renderOptions)
|
|
2589
|
+
const description = renderChoiceDescription(choice as SelectChoice<A>, isHighlighted, renderOptions)
|
|
2590
|
+
documents.push(prefix + " " + annotatedCheckbox + " " + title + " " + description)
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
return documents.join("\n")
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
const renderMultiSelectNextFrame = Effect.fnUntraced(
|
|
2597
|
+
function*<A>(state: MultiSelectState, options: SelectOptionsReq<A>) {
|
|
2598
|
+
const figures = yield* platformFigures
|
|
2599
|
+
const choices = renderMultiSelectChoices(state, options, figures)
|
|
2600
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
2601
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
2602
|
+
const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options)
|
|
2603
|
+
const error = renderMultiSelectError(state, figures.pointer)
|
|
2604
|
+
return Ansi.cursorHide + promptMsg + "\n" + choices + error
|
|
2605
|
+
}
|
|
2606
|
+
)
|
|
2607
|
+
|
|
2608
|
+
const renderMultiSelectSubmission = Effect.fnUntraced(
|
|
2609
|
+
function*<A>(state: MultiSelectState, options: SelectOptionsReq<A>) {
|
|
2610
|
+
const figures = yield* platformFigures
|
|
2611
|
+
const selectedChoices = Array.from(state.selectedIndices).sort(EffectNumber.Order).map((index) =>
|
|
2612
|
+
options.choices[index].title
|
|
2613
|
+
)
|
|
2614
|
+
const selectedText = selectedChoices.join(", ")
|
|
2615
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
2616
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
2617
|
+
const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options)
|
|
2618
|
+
return promptMsg + " " + Ansi.annotate(selectedText, Ansi.white) + "\n"
|
|
2619
|
+
}
|
|
2620
|
+
)
|
|
2621
|
+
|
|
2622
|
+
const processMultiSelectCursorUp = (state: MultiSelectState, totalChoices: number) => {
|
|
2623
|
+
const newIndex = state.index === 0 ? totalChoices - 1 : state.index - 1
|
|
2624
|
+
return Effect.succeed(Action.NextFrame({ state: { ...state, index: newIndex } }))
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
const processMultiSelectCursorDown = (state: MultiSelectState, totalChoices: number) => {
|
|
2628
|
+
const newIndex = (state.index + 1) % totalChoices
|
|
2629
|
+
return Effect.succeed(Action.NextFrame({ state: { ...state, index: newIndex } }))
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
const processSpace = <A>(
|
|
2633
|
+
state: MultiSelectState,
|
|
2634
|
+
options: SelectOptionsReq<A>
|
|
2635
|
+
) => {
|
|
2636
|
+
const selectedIndices = new Set(state.selectedIndices)
|
|
2637
|
+
if (state.index === 0) {
|
|
2638
|
+
if (state.selectedIndices.size === options.choices.length) {
|
|
2639
|
+
selectedIndices.clear()
|
|
2640
|
+
} else {
|
|
2641
|
+
for (let i = 0; i < options.choices.length; i++) {
|
|
2642
|
+
selectedIndices.add(i)
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
} else if (state.index === 1) {
|
|
2646
|
+
for (let i = 0; i < options.choices.length; i++) {
|
|
2647
|
+
if (state.selectedIndices.has(i)) {
|
|
2648
|
+
selectedIndices.delete(i)
|
|
2649
|
+
} else {
|
|
2650
|
+
selectedIndices.add(i)
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
} else {
|
|
2654
|
+
const choiceIndex = state.index - metaOptionsCount
|
|
2655
|
+
if (selectedIndices.has(choiceIndex)) {
|
|
2656
|
+
selectedIndices.delete(choiceIndex)
|
|
2657
|
+
} else {
|
|
2658
|
+
selectedIndices.add(choiceIndex)
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
return Effect.succeed(Action.NextFrame({ state: { ...state, selectedIndices } }))
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
const handleMultiSelectClear = <A>(options: SelectOptionsReq<A>) =>
|
|
2665
|
+
Effect.fnUntraced(function*(state: MultiSelectState, _: Action<MultiSelectState, Array<A>>) {
|
|
2666
|
+
const terminal = yield* Terminal.Terminal
|
|
2667
|
+
const columns = yield* terminal.columns
|
|
2668
|
+
const figures = yield* platformFigures
|
|
2669
|
+
const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft
|
|
2670
|
+
const promptText = renderSelectOutput("?", figures.pointerSmall, options, { plain: true })
|
|
2671
|
+
const choicesText = renderMultiSelectChoices(state, options, figures, { plain: true })
|
|
2672
|
+
const errorText = renderMultiSelectError(state, figures.pointer, { plain: true })
|
|
2673
|
+
const clearOutput = clearOutputWithError(`${promptText}\n${choicesText}`, columns, errorText)
|
|
2674
|
+
return clearOutput + clearPrompt
|
|
2675
|
+
})
|
|
2676
|
+
|
|
2677
|
+
const handleMultiSelectProcess = <A>(options: SelectOptionsReq<A> & MultiSelectOptionsReq) => {
|
|
2678
|
+
return (input: Terminal.UserInput, state: MultiSelectState) => {
|
|
2679
|
+
const totalChoices = options.choices.length + metaOptionsCount
|
|
2680
|
+
switch (input.key.name) {
|
|
2681
|
+
case "k":
|
|
2682
|
+
case "up": {
|
|
2683
|
+
return processMultiSelectCursorUp({ ...state, error: Option.none() }, totalChoices)
|
|
2684
|
+
}
|
|
2685
|
+
case "j":
|
|
2686
|
+
case "down":
|
|
2687
|
+
case "tab": {
|
|
2688
|
+
return processMultiSelectCursorDown({ ...state, error: Option.none() }, totalChoices)
|
|
2689
|
+
}
|
|
2690
|
+
case "space": {
|
|
2691
|
+
return processSpace(state, options)
|
|
2692
|
+
}
|
|
2693
|
+
case "enter":
|
|
2694
|
+
case "return": {
|
|
2695
|
+
const selectedCount = state.selectedIndices.size
|
|
2696
|
+
if (options.min !== undefined && selectedCount < options.min) {
|
|
2697
|
+
return Effect.succeed(
|
|
2698
|
+
Action.NextFrame({ state: { ...state, error: Option.some(`At least ${options.min} are required`) } })
|
|
2699
|
+
)
|
|
2700
|
+
}
|
|
2701
|
+
if (options.max !== undefined && selectedCount > options.max) {
|
|
2702
|
+
return Effect.succeed(
|
|
2703
|
+
Action.NextFrame({ state: { ...state, error: Option.some(`At most ${options.max} choices are allowed`) } })
|
|
2704
|
+
)
|
|
2705
|
+
}
|
|
2706
|
+
const selectedValues = Array.from(state.selectedIndices).sort(EffectNumber.Order).map((index) =>
|
|
2707
|
+
options.choices[index].value
|
|
2708
|
+
)
|
|
2709
|
+
return Effect.succeed(Action.Submit({ value: selectedValues }))
|
|
2710
|
+
}
|
|
2711
|
+
default: {
|
|
2712
|
+
return Effect.succeed(Action.Beep())
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2718
|
+
const handleMultiSelectRender = <A>(options: SelectOptionsReq<A>) => {
|
|
2719
|
+
return (state: MultiSelectState, action: Action<MultiSelectState, Array<A>>) => {
|
|
2720
|
+
return Action.$match(action, {
|
|
2721
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
2722
|
+
NextFrame: ({ state }) => renderMultiSelectNextFrame(state, options),
|
|
2723
|
+
Submit: () => renderMultiSelectSubmission(state, options)
|
|
2724
|
+
})
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
interface IntegerOptionsReq extends Required<IntegerOptions> {}
|
|
2729
|
+
interface FloatOptionsReq extends Required<FloatOptions> {}
|
|
2730
|
+
|
|
2731
|
+
interface NumberState {
|
|
2732
|
+
readonly cursor: number
|
|
2733
|
+
readonly value: string
|
|
2734
|
+
readonly error: Option.Option<string>
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
const handleNumberClear = (options: IntegerOptionsReq) => {
|
|
2738
|
+
return Effect.fnUntraced(function*(state: NumberState, _: Action<NumberState, number>) {
|
|
2739
|
+
const terminal = yield* Terminal.Terminal
|
|
2740
|
+
const columns = yield* terminal.columns
|
|
2741
|
+
const figures = yield* platformFigures
|
|
2742
|
+
const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft
|
|
2743
|
+
const errorText = renderNumberError(state, figures.pointerSmall, { plain: true })
|
|
2744
|
+
const promptText = renderNumberOutput(state, "?", figures.pointerSmall, options, { plain: true })
|
|
2745
|
+
const clearOutput = clearOutputWithError(promptText, columns, errorText)
|
|
2746
|
+
return clearOutput + resetCurrentLine
|
|
2747
|
+
})
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
const renderNumberInput = (
|
|
2751
|
+
state: NumberState,
|
|
2752
|
+
submitted: boolean,
|
|
2753
|
+
renderOptions?: RenderOptions | undefined
|
|
2754
|
+
): string => {
|
|
2755
|
+
const value = state.value === "" ? "" : `${state.value}`
|
|
2756
|
+
if (submitted || renderOptions?.plain === true) {
|
|
2757
|
+
return value
|
|
2758
|
+
}
|
|
2759
|
+
const annotation = Option.isSome(state.error) ?
|
|
2760
|
+
Ansi.red :
|
|
2761
|
+
Ansi.combine(Ansi.underlined, Ansi.cyanBright)
|
|
2762
|
+
return Ansi.annotate(value, annotation)
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
const renderNumberError = (
|
|
2766
|
+
state: NumberState,
|
|
2767
|
+
pointer: string,
|
|
2768
|
+
renderOptions?: RenderOptions | undefined
|
|
2769
|
+
) => {
|
|
2770
|
+
if (Option.isSome(state.error)) {
|
|
2771
|
+
return Arr.match(state.error.value.split(NEWLINE_REGEXP), {
|
|
2772
|
+
onEmpty: () => "",
|
|
2773
|
+
onNonEmpty: (errorLines) => {
|
|
2774
|
+
if (renderOptions?.plain === true) {
|
|
2775
|
+
return `${pointer} ${errorLines.join("\n")}`
|
|
2776
|
+
}
|
|
2777
|
+
const prefix = Ansi.annotate(pointer, Ansi.red) + " "
|
|
2778
|
+
const lines = Arr.map(errorLines, (str) => annotateErrorLine(str))
|
|
2779
|
+
return Ansi.cursorSavePosition + "\n" + prefix + lines.join("\n") + Ansi.cursorRestorePosition
|
|
2780
|
+
}
|
|
2781
|
+
})
|
|
2782
|
+
}
|
|
2783
|
+
return ""
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
const renderNumberOutput = (
|
|
2787
|
+
state: NumberState,
|
|
2788
|
+
leadingSymbol: string,
|
|
2789
|
+
trailingSymbol: string,
|
|
2790
|
+
options: IntegerOptionsReq,
|
|
2791
|
+
renderOptions?: RenderOptions | undefined,
|
|
2792
|
+
submitted: boolean = false
|
|
2793
|
+
) => {
|
|
2794
|
+
const value = renderNumberInput(state, submitted, renderOptions)
|
|
2795
|
+
return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
const renderNumberNextFrame = Effect.fnUntraced(function*(state: NumberState, options: IntegerOptionsReq) {
|
|
2799
|
+
const figures = yield* platformFigures
|
|
2800
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
2801
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
2802
|
+
const errorMsg = renderNumberError(state, figures.pointerSmall)
|
|
2803
|
+
const promptMsg = renderNumberOutput(state, leadingSymbol, trailingSymbol, options)
|
|
2804
|
+
return promptMsg + errorMsg
|
|
2805
|
+
})
|
|
2806
|
+
|
|
2807
|
+
const renderNumberSubmission = Effect.fnUntraced(function*(nextState: NumberState, options: IntegerOptionsReq) {
|
|
2808
|
+
const figures = yield* platformFigures
|
|
2809
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
2810
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
2811
|
+
const promptMsg = renderNumberOutput(nextState, leadingSymbol, trailingSymbol, options, undefined, true)
|
|
2812
|
+
return promptMsg + "\n"
|
|
2813
|
+
})
|
|
2814
|
+
|
|
2815
|
+
const processNumberBackspace = (state: NumberState) => {
|
|
2816
|
+
if (state.value.length <= 0) {
|
|
2817
|
+
return Effect.succeed(Action.Beep())
|
|
2818
|
+
}
|
|
2819
|
+
const value = state.value.slice(0, state.value.length - 1)
|
|
2820
|
+
return Effect.succeed(Action.NextFrame({
|
|
2821
|
+
state: { ...state, value, error: Option.none() }
|
|
2822
|
+
}))
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
const processNumberClear = (state: NumberState) =>
|
|
2826
|
+
Effect.succeed(Action.NextFrame({
|
|
2827
|
+
state: { ...state, cursor: 0, value: "", error: Option.none() }
|
|
2828
|
+
}))
|
|
2829
|
+
|
|
2830
|
+
const defaultIntProcessor = (input: string, state: NumberState) => {
|
|
2831
|
+
if (state.value.length === 0 && input === "-") {
|
|
2832
|
+
return Effect.succeed(Action.NextFrame({
|
|
2833
|
+
state: { ...state, value: "-", error: Option.none() }
|
|
2834
|
+
}))
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
const parsed = Number.parseInt(state.value + input)
|
|
2838
|
+
if (Number.isNaN(parsed)) {
|
|
2839
|
+
return Effect.succeed(Action.Beep())
|
|
2840
|
+
} else {
|
|
2841
|
+
return Effect.succeed(Action.NextFrame({
|
|
2842
|
+
state: { ...state, value: `${parsed}`, error: Option.none() }
|
|
2843
|
+
}))
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
const defaultFloatProcessor = (input: string, state: NumberState) => {
|
|
2848
|
+
if (input === "." && state.value.includes(".")) {
|
|
2849
|
+
return Effect.succeed(Action.Beep())
|
|
2850
|
+
}
|
|
2851
|
+
if (state.value.length === 0 && input === "-") {
|
|
2852
|
+
return Effect.succeed(Action.NextFrame({
|
|
2853
|
+
state: { ...state, value: "-", error: Option.none() }
|
|
2854
|
+
}))
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
const parsed = Number.parseFloat(state.value + input)
|
|
2858
|
+
if (Number.isNaN(parsed)) {
|
|
2859
|
+
return Effect.succeed(Action.Beep())
|
|
2860
|
+
} else {
|
|
2861
|
+
return Effect.succeed(Action.NextFrame({
|
|
2862
|
+
state: {
|
|
2863
|
+
...state,
|
|
2864
|
+
value: input === "." ? `${parsed}.` : `${parsed}`,
|
|
2865
|
+
error: Option.none()
|
|
2866
|
+
}
|
|
2867
|
+
}))
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
const handleRenderInteger = (options: IntegerOptionsReq) => {
|
|
2872
|
+
return (state: NumberState, action: Action<NumberState, number>) => {
|
|
2873
|
+
return Action.$match(action, {
|
|
2874
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
2875
|
+
NextFrame: ({ state }) => renderNumberNextFrame(state, options),
|
|
2876
|
+
Submit: () => renderNumberSubmission(state, options)
|
|
2877
|
+
})
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
const handleProcessInteger = (options: IntegerOptionsReq) => {
|
|
2882
|
+
return (input: Terminal.UserInput, state: NumberState) => {
|
|
2883
|
+
if (input.key.ctrl && input.key.name === "u") {
|
|
2884
|
+
return processNumberClear(state)
|
|
2885
|
+
}
|
|
2886
|
+
switch (input.key.name) {
|
|
2887
|
+
case "backspace": {
|
|
2888
|
+
return processNumberBackspace(state)
|
|
2889
|
+
}
|
|
2890
|
+
case "k":
|
|
2891
|
+
case "up": {
|
|
2892
|
+
return Effect.succeed(Action.NextFrame({
|
|
2893
|
+
state: {
|
|
2894
|
+
...state,
|
|
2895
|
+
value: state.value === "" || state.value === "-"
|
|
2896
|
+
? `${options.incrementBy}`
|
|
2897
|
+
: `${Number.parseInt(state.value) + options.incrementBy}`,
|
|
2898
|
+
error: Option.none()
|
|
2899
|
+
}
|
|
2900
|
+
}))
|
|
2901
|
+
}
|
|
2902
|
+
case "j":
|
|
2903
|
+
case "down": {
|
|
2904
|
+
return Effect.succeed(Action.NextFrame({
|
|
2905
|
+
state: {
|
|
2906
|
+
...state,
|
|
2907
|
+
value: state.value === "" || state.value === "-"
|
|
2908
|
+
? `-${options.decrementBy}`
|
|
2909
|
+
: `${Number.parseInt(state.value) - options.decrementBy}`,
|
|
2910
|
+
error: Option.none()
|
|
2911
|
+
}
|
|
2912
|
+
}))
|
|
2913
|
+
}
|
|
2914
|
+
case "enter":
|
|
2915
|
+
case "return": {
|
|
2916
|
+
const parsed = Number.parseInt(state.value)
|
|
2917
|
+
if (Number.isNaN(parsed)) {
|
|
2918
|
+
return Effect.succeed(Action.NextFrame({
|
|
2919
|
+
state: {
|
|
2920
|
+
...state,
|
|
2921
|
+
error: Option.some("Must provide an integer value")
|
|
2922
|
+
}
|
|
2923
|
+
}))
|
|
2924
|
+
} else {
|
|
2925
|
+
return Effect.match(options.validate(parsed), {
|
|
2926
|
+
onFailure: (error) =>
|
|
2927
|
+
Action.NextFrame({
|
|
2928
|
+
state: {
|
|
2929
|
+
...state,
|
|
2930
|
+
error: Option.some(error)
|
|
2931
|
+
}
|
|
2932
|
+
}),
|
|
2933
|
+
onSuccess: (value) => Action.Submit({ value })
|
|
2934
|
+
})
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
default: {
|
|
2938
|
+
return defaultIntProcessor(Option.getOrElse(input.input, () => ""), state)
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
const handleRenderFloat = (options: FloatOptionsReq) => {
|
|
2945
|
+
return (state: NumberState, action: Action<NumberState, number>) => {
|
|
2946
|
+
return Action.$match(action, {
|
|
2947
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
2948
|
+
NextFrame: ({ state }) => renderNumberNextFrame(state, options),
|
|
2949
|
+
Submit: () => renderNumberSubmission(state, options)
|
|
2950
|
+
})
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
const handleProcessFloat = (options: FloatOptionsReq) => {
|
|
2955
|
+
return (input: Terminal.UserInput, state: NumberState) => {
|
|
2956
|
+
if (input.key.ctrl && input.key.name === "u") {
|
|
2957
|
+
return processNumberClear(state)
|
|
2958
|
+
}
|
|
2959
|
+
switch (input.key.name) {
|
|
2960
|
+
case "backspace": {
|
|
2961
|
+
return processNumberBackspace(state)
|
|
2962
|
+
}
|
|
2963
|
+
case "k":
|
|
2964
|
+
case "up": {
|
|
2965
|
+
return Effect.succeed(Action.NextFrame({
|
|
2966
|
+
state: {
|
|
2967
|
+
...state,
|
|
2968
|
+
value: state.value === "" || state.value === "-"
|
|
2969
|
+
? `${options.incrementBy}`
|
|
2970
|
+
: `${Number.parseFloat(state.value) + options.incrementBy}`,
|
|
2971
|
+
error: Option.none()
|
|
2972
|
+
}
|
|
2973
|
+
}))
|
|
2974
|
+
}
|
|
2975
|
+
case "j":
|
|
2976
|
+
case "down": {
|
|
2977
|
+
return Effect.succeed(Action.NextFrame({
|
|
2978
|
+
state: {
|
|
2979
|
+
...state,
|
|
2980
|
+
value: state.value === "" || state.value === "-"
|
|
2981
|
+
? `-${options.decrementBy}`
|
|
2982
|
+
: `${Number.parseFloat(state.value) - options.decrementBy}`,
|
|
2983
|
+
error: Option.none()
|
|
2984
|
+
}
|
|
2985
|
+
}))
|
|
2986
|
+
}
|
|
2987
|
+
case "enter":
|
|
2988
|
+
case "return": {
|
|
2989
|
+
const parsed = Number.parseFloat(state.value)
|
|
2990
|
+
if (Number.isNaN(parsed)) {
|
|
2991
|
+
return Effect.succeed(Action.NextFrame({
|
|
2992
|
+
state: {
|
|
2993
|
+
...state,
|
|
2994
|
+
error: Option.some("Must provide a floating point value")
|
|
2995
|
+
}
|
|
2996
|
+
}))
|
|
2997
|
+
} else {
|
|
2998
|
+
return Effect.flatMap(
|
|
2999
|
+
Effect.sync(() => EffectNumber.round(parsed, options.precision)),
|
|
3000
|
+
(rounded) =>
|
|
3001
|
+
Effect.match(options.validate(rounded), {
|
|
3002
|
+
onFailure: (error) =>
|
|
3003
|
+
Action.NextFrame({
|
|
3004
|
+
state: {
|
|
3005
|
+
...state,
|
|
3006
|
+
error: Option.some(error)
|
|
3007
|
+
}
|
|
3008
|
+
}),
|
|
3009
|
+
onSuccess: (value) => Action.Submit({ value })
|
|
3010
|
+
})
|
|
3011
|
+
)
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
default: {
|
|
3015
|
+
return defaultFloatProcessor(Option.getOrElse(input.input, () => ""), state)
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
type SelectState = number
|
|
3022
|
+
|
|
3023
|
+
type AutoCompleteState = {
|
|
3024
|
+
readonly query: string
|
|
3025
|
+
readonly index: number
|
|
3026
|
+
readonly filtered: ReadonlyArray<number>
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
interface SelectOptionsReq<A> extends Required<SelectOptions<A>> {}
|
|
3030
|
+
interface AutoCompleteOptionsReq<A> extends Required<AutoCompleteOptions<A>> {}
|
|
3031
|
+
|
|
3032
|
+
const filterAutoCompleteChoices = <A>(choices: ReadonlyArray<SelectChoice<A>>, query: string) => {
|
|
3033
|
+
const normalizedQuery = query.toLowerCase()
|
|
3034
|
+
const indices: Array<number> = []
|
|
3035
|
+
for (let i = 0; i < choices.length; i++) {
|
|
3036
|
+
if (choices[i].title.toLowerCase().includes(normalizedQuery)) {
|
|
3037
|
+
indices.push(i)
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
return indices
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
const updateAutoCompleteState = <A>(
|
|
3044
|
+
state: AutoCompleteState,
|
|
3045
|
+
options: AutoCompleteOptionsReq<A>,
|
|
3046
|
+
query: string
|
|
3047
|
+
): AutoCompleteState => {
|
|
3048
|
+
const filtered = filterAutoCompleteChoices(options.choices, query)
|
|
3049
|
+
if (filtered.length === 0) {
|
|
3050
|
+
return { ...state, query, filtered, index: 0 }
|
|
3051
|
+
}
|
|
3052
|
+
if (filtered.includes(state.index)) {
|
|
3053
|
+
return { ...state, query, filtered }
|
|
3054
|
+
}
|
|
3055
|
+
return { ...state, query, filtered, index: filtered[0] }
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
const autoCompleteCursor = (state: AutoCompleteState) =>
|
|
3059
|
+
Option.getOrElse(Arr.findFirstIndex(state.filtered, (index) => index === state.index), () => 0)
|
|
3060
|
+
|
|
3061
|
+
const renderSelectOutput = <A>(
|
|
3062
|
+
leadingSymbol: string,
|
|
3063
|
+
trailingSymbol: string,
|
|
3064
|
+
options: SelectOptionsReq<A>,
|
|
3065
|
+
renderOptions?: RenderOptions | undefined
|
|
3066
|
+
) => renderPrompt("", options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
3067
|
+
|
|
3068
|
+
const renderAutoCompleteFilter = <A>(
|
|
3069
|
+
state: AutoCompleteState,
|
|
3070
|
+
options: AutoCompleteOptionsReq<A>,
|
|
3071
|
+
renderOptions?: RenderOptions | undefined
|
|
3072
|
+
) => {
|
|
3073
|
+
const filterValue = state.query.length === 0
|
|
3074
|
+
? renderOptions?.plain === true
|
|
3075
|
+
? options.filterPlaceholder
|
|
3076
|
+
: Ansi.annotate(options.filterPlaceholder, Ansi.blackBright)
|
|
3077
|
+
: renderOptions?.plain === true
|
|
3078
|
+
? state.query
|
|
3079
|
+
: Ansi.annotate(state.query, Ansi.combine(Ansi.underlined, Ansi.cyanBright))
|
|
3080
|
+
return `[${options.filterLabel}: ${filterValue}]`
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
const renderAutoCompleteOutput = <A>(
|
|
3084
|
+
state: AutoCompleteState,
|
|
3085
|
+
leadingSymbol: string,
|
|
3086
|
+
trailingSymbol: string,
|
|
3087
|
+
options: AutoCompleteOptionsReq<A>,
|
|
3088
|
+
renderOptions?: RenderOptions | undefined
|
|
3089
|
+
) => {
|
|
3090
|
+
const filter = renderAutoCompleteFilter(state, options, renderOptions)
|
|
3091
|
+
return renderPrompt(filter, options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
3092
|
+
}
|
|
3093
|
+
|
|
3094
|
+
const renderChoicePrefix = <A>(
|
|
3095
|
+
state: SelectState,
|
|
3096
|
+
choices: SelectOptionsReq<A>["choices"],
|
|
3097
|
+
toDisplay: { readonly startIndex: number; readonly endIndex: number },
|
|
3098
|
+
currentIndex: number,
|
|
3099
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
3100
|
+
renderOptions?: RenderOptions | undefined
|
|
3101
|
+
) => {
|
|
3102
|
+
let prefix = " "
|
|
3103
|
+
if (currentIndex === toDisplay.startIndex && toDisplay.startIndex > 0) {
|
|
3104
|
+
prefix = figures.arrowUp
|
|
3105
|
+
} else if (currentIndex === toDisplay.endIndex - 1 && toDisplay.endIndex < choices.length) {
|
|
3106
|
+
prefix = figures.arrowDown
|
|
3107
|
+
}
|
|
3108
|
+
if (renderOptions?.plain === true) {
|
|
3109
|
+
return state === currentIndex
|
|
3110
|
+
? figures.pointer + prefix
|
|
3111
|
+
: prefix + " "
|
|
3112
|
+
}
|
|
3113
|
+
if (choices[currentIndex].disabled) {
|
|
3114
|
+
const annotation = Ansi.combine(Ansi.bold, Ansi.blackBright)
|
|
3115
|
+
return state === currentIndex
|
|
3116
|
+
? Ansi.annotate(figures.pointer, annotation) + prefix
|
|
3117
|
+
: prefix + " "
|
|
3118
|
+
}
|
|
3119
|
+
return state === currentIndex
|
|
3120
|
+
? Ansi.annotate(figures.pointer, Ansi.cyanBright) + prefix
|
|
3121
|
+
: prefix + " "
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
const renderAutoCompleteChoicePrefix = <A>(
|
|
3125
|
+
state: AutoCompleteState,
|
|
3126
|
+
options: AutoCompleteOptionsReq<A>,
|
|
3127
|
+
toDisplay: { readonly startIndex: number; readonly endIndex: number },
|
|
3128
|
+
currentIndex: number,
|
|
3129
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
3130
|
+
renderOptions?: RenderOptions | undefined
|
|
3131
|
+
) => {
|
|
3132
|
+
let prefix = " "
|
|
3133
|
+
if (currentIndex === toDisplay.startIndex && toDisplay.startIndex > 0) {
|
|
3134
|
+
prefix = figures.arrowUp
|
|
3135
|
+
} else if (currentIndex === toDisplay.endIndex - 1 && toDisplay.endIndex < state.filtered.length) {
|
|
3136
|
+
prefix = figures.arrowDown
|
|
3137
|
+
}
|
|
3138
|
+
const choiceIndex = state.filtered[currentIndex]
|
|
3139
|
+
if (renderOptions?.plain === true) {
|
|
3140
|
+
return state.index === choiceIndex
|
|
3141
|
+
? figures.pointer + prefix
|
|
3142
|
+
: prefix + " "
|
|
3143
|
+
}
|
|
3144
|
+
const choice = options.choices[choiceIndex]
|
|
3145
|
+
if (choice.disabled) {
|
|
3146
|
+
const annotation = Ansi.combine(Ansi.bold, Ansi.blackBright)
|
|
3147
|
+
return state.index === choiceIndex
|
|
3148
|
+
? Ansi.annotate(figures.pointer, annotation) + prefix
|
|
3149
|
+
: prefix + " "
|
|
3150
|
+
}
|
|
3151
|
+
return state.index === choiceIndex
|
|
3152
|
+
? Ansi.annotate(figures.pointer, Ansi.cyanBright) + prefix
|
|
3153
|
+
: prefix + " "
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
const renderChoiceTitle = <A>(
|
|
3157
|
+
choice: SelectChoice<A>,
|
|
3158
|
+
isSelected: boolean,
|
|
3159
|
+
renderOptions?: RenderOptions | undefined
|
|
3160
|
+
) => {
|
|
3161
|
+
if (renderOptions?.plain === true) {
|
|
3162
|
+
return choice.title
|
|
3163
|
+
}
|
|
3164
|
+
const title = choice.title
|
|
3165
|
+
if (isSelected) {
|
|
3166
|
+
return choice.disabled
|
|
3167
|
+
? Ansi.annotate(title, Ansi.combine(Ansi.underlined, Ansi.blackBright))
|
|
3168
|
+
: Ansi.annotate(title, Ansi.combine(Ansi.underlined, Ansi.cyanBright))
|
|
3169
|
+
}
|
|
3170
|
+
return choice.disabled
|
|
3171
|
+
? Ansi.annotate(title, Ansi.combine(Ansi.strikethrough, Ansi.blackBright))
|
|
3172
|
+
: title
|
|
3173
|
+
}
|
|
3174
|
+
|
|
3175
|
+
const renderSelectChoices = <A>(
|
|
3176
|
+
state: SelectState,
|
|
3177
|
+
options: SelectOptionsReq<A>,
|
|
3178
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
3179
|
+
renderOptions?: RenderOptions | undefined
|
|
3180
|
+
) => {
|
|
3181
|
+
const choices = options.choices
|
|
3182
|
+
const toDisplay = entriesToDisplay(state, choices.length, options.maxPerPage)
|
|
3183
|
+
const documents: Array<string> = []
|
|
3184
|
+
for (let index = toDisplay.startIndex; index < toDisplay.endIndex; index++) {
|
|
3185
|
+
const choice = choices[index]
|
|
3186
|
+
const isSelected = state === index
|
|
3187
|
+
const prefix = renderChoicePrefix(state, choices, toDisplay, index, figures, renderOptions)
|
|
3188
|
+
const title = renderChoiceTitle(choice, isSelected, renderOptions)
|
|
3189
|
+
const description = renderChoiceDescription(choice, isSelected, renderOptions)
|
|
3190
|
+
documents.push(prefix + title + " " + description)
|
|
3191
|
+
}
|
|
3192
|
+
return documents.join("\n")
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
const renderAutoCompleteChoices = <A>(
|
|
3196
|
+
state: AutoCompleteState,
|
|
3197
|
+
options: AutoCompleteOptionsReq<A>,
|
|
3198
|
+
figures: Effect.Success<typeof platformFigures>,
|
|
3199
|
+
renderOptions?: RenderOptions | undefined
|
|
3200
|
+
) => {
|
|
3201
|
+
if (state.filtered.length === 0) {
|
|
3202
|
+
return renderOptions?.plain === true
|
|
3203
|
+
? options.emptyMessage
|
|
3204
|
+
: Ansi.annotate(options.emptyMessage, Ansi.blackBright)
|
|
3205
|
+
}
|
|
3206
|
+
const cursor = autoCompleteCursor(state)
|
|
3207
|
+
const toDisplay = entriesToDisplay(cursor, state.filtered.length, options.maxPerPage)
|
|
3208
|
+
const documents: Array<string> = []
|
|
3209
|
+
for (let index = toDisplay.startIndex; index < toDisplay.endIndex; index++) {
|
|
3210
|
+
const choiceIndex = state.filtered[index]
|
|
3211
|
+
const choice = options.choices[choiceIndex]
|
|
3212
|
+
const isSelected = state.index === choiceIndex
|
|
3213
|
+
const prefix = renderAutoCompleteChoicePrefix(state, options, toDisplay, index, figures, renderOptions)
|
|
3214
|
+
const title = renderChoiceTitle(choice, isSelected, renderOptions)
|
|
3215
|
+
const description = renderChoiceDescription(choice, isSelected, renderOptions)
|
|
3216
|
+
documents.push(prefix + title + " " + description)
|
|
3217
|
+
}
|
|
3218
|
+
return documents.join("\n")
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
const renderSelectNextFrame = Effect.fnUntraced(function*<A>(state: SelectState, options: SelectOptionsReq<A>) {
|
|
3222
|
+
const figures = yield* platformFigures
|
|
3223
|
+
const choices = renderSelectChoices(state, options, figures)
|
|
3224
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
3225
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
3226
|
+
const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options)
|
|
3227
|
+
return Ansi.cursorHide + promptMsg + "\n" + choices
|
|
3228
|
+
})
|
|
3229
|
+
|
|
3230
|
+
const renderAutoCompleteNextFrame = Effect.fnUntraced(function*<A>(
|
|
3231
|
+
state: AutoCompleteState,
|
|
3232
|
+
options: AutoCompleteOptionsReq<A>
|
|
3233
|
+
) {
|
|
3234
|
+
const figures = yield* platformFigures
|
|
3235
|
+
const choices = renderAutoCompleteChoices(state, options, figures)
|
|
3236
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
3237
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
3238
|
+
const promptMsg = renderAutoCompleteOutput(state, leadingSymbol, trailingSymbol, options)
|
|
3239
|
+
return Ansi.cursorHide + promptMsg + "\n" + choices
|
|
3240
|
+
})
|
|
3241
|
+
|
|
3242
|
+
const renderSelectSubmission = Effect.fnUntraced(function*<A>(state: SelectState, options: SelectOptionsReq<A>) {
|
|
3243
|
+
const figures = yield* platformFigures
|
|
3244
|
+
const selected = options.choices[state].title
|
|
3245
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
3246
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
3247
|
+
const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options)
|
|
3248
|
+
return promptMsg + " " + Ansi.annotate(selected, Ansi.white) + "\n"
|
|
3249
|
+
})
|
|
3250
|
+
|
|
3251
|
+
const renderAutoCompleteSubmission = Effect.fnUntraced(function*<A>(
|
|
3252
|
+
state: AutoCompleteState,
|
|
3253
|
+
options: AutoCompleteOptionsReq<A>
|
|
3254
|
+
) {
|
|
3255
|
+
const figures = yield* platformFigures
|
|
3256
|
+
const selected = options.choices[state.index].title
|
|
3257
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
3258
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
3259
|
+
const promptMsg = renderAutoCompleteOutput(state, leadingSymbol, trailingSymbol, options)
|
|
3260
|
+
return promptMsg + " " + Ansi.annotate(selected, Ansi.white) + "\n"
|
|
3261
|
+
})
|
|
3262
|
+
|
|
3263
|
+
const processSelectCursorUp = <A>(state: SelectState, choices: SelectOptionsReq<A>["choices"]) => {
|
|
3264
|
+
if (state === 0) {
|
|
3265
|
+
return Effect.succeed(Action.NextFrame({ state: choices.length - 1 }))
|
|
3266
|
+
}
|
|
3267
|
+
return Effect.succeed(Action.NextFrame({ state: state - 1 }))
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
const processSelectCursorDown = <A>(state: SelectState, choices: SelectOptionsReq<A>["choices"]) => {
|
|
3271
|
+
if (state === choices.length - 1) {
|
|
3272
|
+
return Effect.succeed(Action.NextFrame({ state: 0 }))
|
|
3273
|
+
}
|
|
3274
|
+
return Effect.succeed(Action.NextFrame({ state: state + 1 }))
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
const processSelectNext = <A>(state: SelectState, choices: SelectOptionsReq<A>["choices"]) => {
|
|
3278
|
+
return Effect.succeed(Action.NextFrame({ state: (state + 1) % choices.length }))
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
const processAutoCompleteCursorUp = (state: AutoCompleteState) => {
|
|
3282
|
+
if (state.filtered.length === 0) {
|
|
3283
|
+
return Effect.succeed(Action.Beep())
|
|
3284
|
+
}
|
|
3285
|
+
const cursor = autoCompleteCursor(state)
|
|
3286
|
+
const nextCursor = cursor === 0 ? state.filtered.length - 1 : cursor - 1
|
|
3287
|
+
return Effect.succeed(Action.NextFrame({ state: { ...state, index: state.filtered[nextCursor] } }))
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
const processAutoCompleteCursorDown = (state: AutoCompleteState) => {
|
|
3291
|
+
if (state.filtered.length === 0) {
|
|
3292
|
+
return Effect.succeed(Action.Beep())
|
|
3293
|
+
}
|
|
3294
|
+
const cursor = autoCompleteCursor(state)
|
|
3295
|
+
const nextCursor = (cursor + 1) % state.filtered.length
|
|
3296
|
+
return Effect.succeed(Action.NextFrame({ state: { ...state, index: state.filtered[nextCursor] } }))
|
|
3297
|
+
}
|
|
3298
|
+
|
|
3299
|
+
const processAutoCompleteNext = (state: AutoCompleteState) => processAutoCompleteCursorDown(state)
|
|
3300
|
+
|
|
3301
|
+
const processAutoCompleteBackspace = <A>(state: AutoCompleteState, options: AutoCompleteOptionsReq<A>) => {
|
|
3302
|
+
if (state.query.length === 0) {
|
|
3303
|
+
return Effect.succeed(Action.Beep())
|
|
3304
|
+
}
|
|
3305
|
+
const query = state.query.slice(0, state.query.length - 1)
|
|
3306
|
+
return Effect.succeed(Action.NextFrame({ state: updateAutoCompleteState(state, options, query) }))
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
const processAutoCompleteClear = <A>(state: AutoCompleteState, options: AutoCompleteOptionsReq<A>) =>
|
|
3310
|
+
Effect.succeed(Action.NextFrame({ state: updateAutoCompleteState(state, options, "") }))
|
|
3311
|
+
|
|
3312
|
+
const processAutoCompleteInput = <A>(input: string, state: AutoCompleteState, options: AutoCompleteOptionsReq<A>) => {
|
|
3313
|
+
if (input.length === 0) {
|
|
3314
|
+
return Effect.succeed(Action.Beep())
|
|
3315
|
+
}
|
|
3316
|
+
const query = state.query + input
|
|
3317
|
+
return Effect.succeed(Action.NextFrame({ state: updateAutoCompleteState(state, options, query) }))
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
const handleSelectRender = <A>(options: SelectOptionsReq<A>) => {
|
|
3321
|
+
return (state: SelectState, action: Action<SelectState, A>) => {
|
|
3322
|
+
return Action.$match(action, {
|
|
3323
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
3324
|
+
NextFrame: ({ state }) => renderSelectNextFrame(state, options),
|
|
3325
|
+
Submit: () => renderSelectSubmission(state, options)
|
|
3326
|
+
})
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
const handleAutoCompleteRender = <A>(options: AutoCompleteOptionsReq<A>) => {
|
|
3331
|
+
return (state: AutoCompleteState, action: Action<AutoCompleteState, A>) => {
|
|
3332
|
+
return Action.$match(action, {
|
|
3333
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
3334
|
+
NextFrame: ({ state }) => renderAutoCompleteNextFrame(state, options),
|
|
3335
|
+
Submit: () => renderAutoCompleteSubmission(state, options)
|
|
3336
|
+
})
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
const handleSelectClear = <A>(options: SelectOptionsReq<A>) =>
|
|
3341
|
+
Effect.fnUntraced(function*(state: SelectState, _: Action<SelectState, A>) {
|
|
3342
|
+
const terminal = yield* Terminal.Terminal
|
|
3343
|
+
const columns = yield* terminal.columns
|
|
3344
|
+
const figures = yield* platformFigures
|
|
3345
|
+
const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft
|
|
3346
|
+
const promptText = renderSelectOutput("?", figures.pointerSmall, options, { plain: true })
|
|
3347
|
+
const choicesText = renderSelectChoices(state, options, figures, { plain: true })
|
|
3348
|
+
const clearOutput = eraseText(`${promptText}\n${choicesText}`, columns)
|
|
3349
|
+
return clearOutput + clearPrompt
|
|
3350
|
+
})
|
|
3351
|
+
|
|
3352
|
+
const handleAutoCompleteClear = <A>(options: AutoCompleteOptionsReq<A>) =>
|
|
3353
|
+
Effect.fnUntraced(function*(state: AutoCompleteState, _: Action<AutoCompleteState, A>) {
|
|
3354
|
+
const terminal = yield* Terminal.Terminal
|
|
3355
|
+
const columns = yield* terminal.columns
|
|
3356
|
+
const figures = yield* platformFigures
|
|
3357
|
+
const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft
|
|
3358
|
+
const promptText = renderAutoCompleteOutput(state, "?", figures.pointerSmall, options, { plain: true })
|
|
3359
|
+
const choicesText = renderAutoCompleteChoices(state, options, figures, { plain: true })
|
|
3360
|
+
const clearOutput = eraseText(`${promptText}\n${choicesText}`, columns)
|
|
3361
|
+
return clearOutput + clearPrompt
|
|
3362
|
+
})
|
|
3363
|
+
|
|
3364
|
+
const handleSelectProcess = <A>(options: SelectOptionsReq<A>) => {
|
|
3365
|
+
return (input: Terminal.UserInput, state: SelectState) => {
|
|
3366
|
+
switch (input.key.name) {
|
|
3367
|
+
case "k":
|
|
3368
|
+
case "up": {
|
|
3369
|
+
return processSelectCursorUp(state, options.choices)
|
|
3370
|
+
}
|
|
3371
|
+
case "j":
|
|
3372
|
+
case "down": {
|
|
3373
|
+
return processSelectCursorDown(state, options.choices)
|
|
3374
|
+
}
|
|
3375
|
+
case "tab": {
|
|
3376
|
+
return processSelectNext(state, options.choices)
|
|
3377
|
+
}
|
|
3378
|
+
case "enter":
|
|
3379
|
+
case "return": {
|
|
3380
|
+
const selected = options.choices[state]
|
|
3381
|
+
if (selected.disabled) {
|
|
3382
|
+
return Effect.succeed(Action.Beep())
|
|
3383
|
+
}
|
|
3384
|
+
return Effect.succeed(Action.Submit({ value: selected.value }))
|
|
3385
|
+
}
|
|
3386
|
+
default: {
|
|
3387
|
+
return Effect.succeed(Action.Beep())
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
const handleAutoCompleteProcess = <A>(options: AutoCompleteOptionsReq<A>) => {
|
|
3394
|
+
return (input: Terminal.UserInput, state: AutoCompleteState) => {
|
|
3395
|
+
if (input.key.ctrl) {
|
|
3396
|
+
if (input.key.name === "u") {
|
|
3397
|
+
return processAutoCompleteClear(state, options)
|
|
3398
|
+
}
|
|
3399
|
+
return Effect.succeed(Action.Beep())
|
|
3400
|
+
}
|
|
3401
|
+
switch (input.key.name) {
|
|
3402
|
+
case "k":
|
|
3403
|
+
case "up": {
|
|
3404
|
+
return processAutoCompleteCursorUp(state)
|
|
3405
|
+
}
|
|
3406
|
+
case "j":
|
|
3407
|
+
case "down": {
|
|
3408
|
+
return processAutoCompleteCursorDown(state)
|
|
3409
|
+
}
|
|
3410
|
+
case "tab": {
|
|
3411
|
+
return processAutoCompleteNext(state)
|
|
3412
|
+
}
|
|
3413
|
+
case "backspace": {
|
|
3414
|
+
return processAutoCompleteBackspace(state, options)
|
|
3415
|
+
}
|
|
3416
|
+
case "enter":
|
|
3417
|
+
case "return": {
|
|
3418
|
+
if (state.filtered.length === 0) {
|
|
3419
|
+
return Effect.succeed(Action.Beep())
|
|
3420
|
+
}
|
|
3421
|
+
const selected = options.choices[state.index]
|
|
3422
|
+
if (selected.disabled) {
|
|
3423
|
+
return Effect.succeed(Action.Beep())
|
|
3424
|
+
}
|
|
3425
|
+
return Effect.succeed(Action.Submit({ value: selected.value }))
|
|
3426
|
+
}
|
|
3427
|
+
default: {
|
|
3428
|
+
return processAutoCompleteInput(Option.getOrElse(input.input, () => ""), state, options)
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
interface TextOptionsReq extends Required<TextOptions> {
|
|
3435
|
+
/**
|
|
3436
|
+
* The type of the text option.
|
|
3437
|
+
*/
|
|
3438
|
+
readonly type: "hidden" | "password" | "text"
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3441
|
+
interface TextState {
|
|
3442
|
+
readonly cursor: number
|
|
3443
|
+
readonly value: string
|
|
3444
|
+
readonly error: Option.Option<string>
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
const renderClearScreen = Effect.fnUntraced(function*(state: TextState, options: TextOptionsReq) {
|
|
3448
|
+
const terminal = yield* Terminal.Terminal
|
|
3449
|
+
const columns = yield* terminal.columns
|
|
3450
|
+
const figures = yield* platformFigures
|
|
3451
|
+
const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft
|
|
3452
|
+
const errorText = renderTextError(state, figures.pointerSmall, { plain: true })
|
|
3453
|
+
const clearOutput = clearOutputWithError(
|
|
3454
|
+
renderTextOutput(state, "?", figures.pointerSmall, options, { plain: true }),
|
|
3455
|
+
columns,
|
|
3456
|
+
errorText
|
|
3457
|
+
)
|
|
3458
|
+
return clearOutput + resetCurrentLine
|
|
3459
|
+
})
|
|
3460
|
+
|
|
3461
|
+
const renderTextInput = (
|
|
3462
|
+
nextState: TextState,
|
|
3463
|
+
options: TextOptionsReq,
|
|
3464
|
+
submitted: boolean,
|
|
3465
|
+
renderOptions?: RenderOptions | undefined
|
|
3466
|
+
) => {
|
|
3467
|
+
const text = nextState.value
|
|
3468
|
+
if (renderOptions?.plain === true) {
|
|
3469
|
+
switch (options.type) {
|
|
3470
|
+
case "hidden": {
|
|
3471
|
+
return ""
|
|
3472
|
+
}
|
|
3473
|
+
case "password": {
|
|
3474
|
+
return "*".repeat(text.length)
|
|
3475
|
+
}
|
|
3476
|
+
case "text": {
|
|
3477
|
+
return text
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
const annotation = Option.isSome(nextState.error) ?
|
|
3483
|
+
Ansi.red
|
|
3484
|
+
: submitted ?
|
|
3485
|
+
Ansi.white
|
|
3486
|
+
: nextState.value.length === 0 ?
|
|
3487
|
+
Ansi.blackBright
|
|
3488
|
+
: Ansi.combine(Ansi.underlined, Ansi.cyanBright)
|
|
3489
|
+
|
|
3490
|
+
switch (options.type) {
|
|
3491
|
+
case "hidden": {
|
|
3492
|
+
return ""
|
|
3493
|
+
}
|
|
3494
|
+
case "password": {
|
|
3495
|
+
return Ansi.annotate("*".repeat(text.length), annotation)
|
|
3496
|
+
}
|
|
3497
|
+
case "text": {
|
|
3498
|
+
return Ansi.annotate(text, annotation)
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
const renderTextError = (
|
|
3504
|
+
nextState: TextState,
|
|
3505
|
+
pointer: string,
|
|
3506
|
+
renderOptions?: RenderOptions | undefined
|
|
3507
|
+
): string => {
|
|
3508
|
+
if (Option.isSome(nextState.error)) {
|
|
3509
|
+
return Arr.match(nextState.error.value.split(NEWLINE_REGEXP), {
|
|
3510
|
+
onEmpty: () => "",
|
|
3511
|
+
onNonEmpty: (errorLines) => {
|
|
3512
|
+
if (renderOptions?.plain === true) {
|
|
3513
|
+
return `${pointer} ${errorLines.join("\n")}`
|
|
3514
|
+
}
|
|
3515
|
+
const prefix = Ansi.annotate(pointer, Ansi.red) + " "
|
|
3516
|
+
const lines = Arr.map(errorLines, (str) => annotateErrorLine(str))
|
|
3517
|
+
return Ansi.cursorSavePosition + "\n" + prefix + lines.join("\n") + Ansi.cursorRestorePosition
|
|
3518
|
+
}
|
|
3519
|
+
})
|
|
3520
|
+
}
|
|
3521
|
+
return ""
|
|
3522
|
+
}
|
|
3523
|
+
|
|
3524
|
+
const renderTextOutput = (
|
|
3525
|
+
nextState: TextState,
|
|
3526
|
+
leadingSymbol: string,
|
|
3527
|
+
trailingSymbol: string,
|
|
3528
|
+
options: TextOptionsReq,
|
|
3529
|
+
renderOptions?: RenderOptions | undefined,
|
|
3530
|
+
submitted: boolean = false
|
|
3531
|
+
) => {
|
|
3532
|
+
const value = renderTextInput(nextState, options, submitted, renderOptions)
|
|
3533
|
+
return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, renderOptions)
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
const renderTextNextFrame = Effect.fnUntraced(function*(state: TextState, options: TextOptionsReq) {
|
|
3537
|
+
const figures = yield* platformFigures
|
|
3538
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
3539
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
3540
|
+
const promptMsg = renderTextOutput(state, leadingSymbol, trailingSymbol, options)
|
|
3541
|
+
const errorMsg = renderTextError(state, figures.pointerSmall)
|
|
3542
|
+
const offset = state.cursor - state.value.length
|
|
3543
|
+
return promptMsg + errorMsg + Ansi.cursorMove(offset)
|
|
3544
|
+
})
|
|
3545
|
+
|
|
3546
|
+
const renderTextSubmission = Effect.fnUntraced(function*(state: TextState, options: TextOptionsReq) {
|
|
3547
|
+
const figures = yield* platformFigures
|
|
3548
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
3549
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
3550
|
+
const promptMsg = renderTextOutput(state, leadingSymbol, trailingSymbol, options, undefined, true)
|
|
3551
|
+
return promptMsg + "\n"
|
|
3552
|
+
})
|
|
3553
|
+
|
|
3554
|
+
const processTextBackspace = (state: TextState) => {
|
|
3555
|
+
if (state.cursor <= 0) {
|
|
3556
|
+
return Effect.succeed(Action.Beep())
|
|
3557
|
+
}
|
|
3558
|
+
const beforeCursor = state.value.slice(0, state.cursor - 1)
|
|
3559
|
+
const afterCursor = state.value.slice(state.cursor)
|
|
3560
|
+
const cursor = state.cursor - 1
|
|
3561
|
+
const value = `${beforeCursor}${afterCursor}`
|
|
3562
|
+
return Effect.succeed(
|
|
3563
|
+
Action.NextFrame({
|
|
3564
|
+
state: { ...state, cursor, value, error: Option.none() }
|
|
3565
|
+
})
|
|
3566
|
+
)
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
const processTextClear = (state: TextState) =>
|
|
3570
|
+
Effect.succeed(
|
|
3571
|
+
Action.NextFrame({
|
|
3572
|
+
state: { ...state, cursor: 0, value: "", error: Option.none() }
|
|
3573
|
+
})
|
|
3574
|
+
)
|
|
3575
|
+
|
|
3576
|
+
const processTextCursorLeft = (state: TextState) => {
|
|
3577
|
+
if (state.cursor <= 0) {
|
|
3578
|
+
return Effect.succeed(Action.Beep())
|
|
3579
|
+
}
|
|
3580
|
+
const cursor = state.cursor - 1
|
|
3581
|
+
return Effect.succeed(
|
|
3582
|
+
Action.NextFrame({
|
|
3583
|
+
state: { ...state, cursor, error: Option.none() }
|
|
3584
|
+
})
|
|
3585
|
+
)
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3588
|
+
const processTextCursorRight = (state: TextState) => {
|
|
3589
|
+
if (state.cursor >= state.value.length) {
|
|
3590
|
+
return Effect.succeed(Action.Beep())
|
|
3591
|
+
}
|
|
3592
|
+
const cursor = Math.min(state.cursor + 1, state.value.length)
|
|
3593
|
+
return Effect.succeed(
|
|
3594
|
+
Action.NextFrame({
|
|
3595
|
+
state: { ...state, cursor, error: Option.none() }
|
|
3596
|
+
})
|
|
3597
|
+
)
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
const processTextCursorStart = (state: TextState) =>
|
|
3601
|
+
Effect.succeed(
|
|
3602
|
+
Action.NextFrame({
|
|
3603
|
+
state: { ...state, cursor: 0, error: Option.none() }
|
|
3604
|
+
})
|
|
3605
|
+
)
|
|
3606
|
+
|
|
3607
|
+
const processTextCursorEnd = (state: TextState) =>
|
|
3608
|
+
Effect.succeed(
|
|
3609
|
+
Action.NextFrame({
|
|
3610
|
+
state: { ...state, cursor: state.value.length, error: Option.none() }
|
|
3611
|
+
})
|
|
3612
|
+
)
|
|
3613
|
+
|
|
3614
|
+
const processTab = (state: TextState, options: TextOptionsReq) => {
|
|
3615
|
+
if (state.value === options.default) {
|
|
3616
|
+
return Effect.succeed(Action.Beep())
|
|
3617
|
+
}
|
|
3618
|
+
const value = state.value.length === 0 ? options.default : state.value
|
|
3619
|
+
return Effect.succeed(
|
|
3620
|
+
Action.NextFrame({
|
|
3621
|
+
state: { ...state, value, cursor: value.length, error: Option.none() }
|
|
3622
|
+
})
|
|
3623
|
+
)
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
const defaultTextProcessor = (input: string, state: TextState) => {
|
|
3627
|
+
const beforeCursor = state.value.slice(0, state.cursor)
|
|
3628
|
+
const afterCursor = state.value.slice(state.cursor)
|
|
3629
|
+
const value = `${beforeCursor}${input}${afterCursor}`
|
|
3630
|
+
const cursor = state.cursor + input.length
|
|
3631
|
+
return Effect.succeed(
|
|
3632
|
+
Action.NextFrame({
|
|
3633
|
+
state: { ...state, cursor, value, error: Option.none() }
|
|
3634
|
+
})
|
|
3635
|
+
)
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
const handleTextRender = (options: TextOptionsReq) => {
|
|
3639
|
+
return (state: TextState, action: Action<TextState, string>) => {
|
|
3640
|
+
return Action.$match(action, {
|
|
3641
|
+
Beep: () => Effect.succeed(renderBeep),
|
|
3642
|
+
NextFrame: ({ state }) => renderTextNextFrame(state, options),
|
|
3643
|
+
Submit: () => renderTextSubmission(state, options)
|
|
3644
|
+
})
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
const handleTextProcess = (options: TextOptionsReq) => {
|
|
3649
|
+
return (input: Terminal.UserInput, state: TextState) => {
|
|
3650
|
+
if (input.key.ctrl) {
|
|
3651
|
+
switch (input.key.name) {
|
|
3652
|
+
case "u": {
|
|
3653
|
+
return processTextClear(state)
|
|
3654
|
+
}
|
|
3655
|
+
case "a": {
|
|
3656
|
+
return processTextCursorStart(state)
|
|
3657
|
+
}
|
|
3658
|
+
case "e": {
|
|
3659
|
+
return processTextCursorEnd(state)
|
|
3660
|
+
}
|
|
3661
|
+
default: {
|
|
3662
|
+
return Effect.succeed(Action.Beep())
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
switch (input.key.name) {
|
|
3667
|
+
case "backspace": {
|
|
3668
|
+
return processTextBackspace(state)
|
|
3669
|
+
}
|
|
3670
|
+
case "left": {
|
|
3671
|
+
return processTextCursorLeft(state)
|
|
3672
|
+
}
|
|
3673
|
+
case "right": {
|
|
3674
|
+
return processTextCursorRight(state)
|
|
3675
|
+
}
|
|
3676
|
+
case "home": {
|
|
3677
|
+
return processTextCursorStart(state)
|
|
3678
|
+
}
|
|
3679
|
+
case "end": {
|
|
3680
|
+
return processTextCursorEnd(state)
|
|
3681
|
+
}
|
|
3682
|
+
case "enter":
|
|
3683
|
+
case "return": {
|
|
3684
|
+
const value = state.value
|
|
3685
|
+
return Effect.match(options.validate(value), {
|
|
3686
|
+
onFailure: (error) =>
|
|
3687
|
+
Action.NextFrame({
|
|
3688
|
+
state: { ...state, value, error: Option.some(error) }
|
|
3689
|
+
}),
|
|
3690
|
+
onSuccess: (value) => Action.Submit({ value })
|
|
3691
|
+
})
|
|
3692
|
+
}
|
|
3693
|
+
case "tab": {
|
|
3694
|
+
return processTab(state, options)
|
|
3695
|
+
}
|
|
3696
|
+
default: {
|
|
3697
|
+
return defaultTextProcessor(Option.getOrElse(input.input, () => ""), state)
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
const handleTextClear = (options: TextOptionsReq) => {
|
|
3704
|
+
return (state: TextState, _: Action<TextState, string>) => {
|
|
3705
|
+
return renderClearScreen(state, options)
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
|
|
3709
|
+
const basePrompt = (
|
|
3710
|
+
options: TextOptions,
|
|
3711
|
+
type: TextOptionsReq["type"]
|
|
3712
|
+
): Prompt<string> => {
|
|
3713
|
+
const opts: TextOptionsReq = {
|
|
3714
|
+
default: "",
|
|
3715
|
+
type,
|
|
3716
|
+
validate: Effect.succeed,
|
|
3717
|
+
...options
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
const initialState: TextState = {
|
|
3721
|
+
cursor: opts.default.length,
|
|
3722
|
+
value: opts.default,
|
|
3723
|
+
error: Option.none()
|
|
3724
|
+
}
|
|
3725
|
+
return custom(initialState, {
|
|
3726
|
+
render: handleTextRender(opts),
|
|
3727
|
+
process: handleTextProcess(opts),
|
|
3728
|
+
clear: handleTextClear(opts)
|
|
3729
|
+
})
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3732
|
+
interface ToggleOptionsReq extends Required<ToggleOptions> {}
|
|
3733
|
+
|
|
3734
|
+
type ToggleState = boolean
|
|
3735
|
+
|
|
3736
|
+
const handleToggleClear = Effect.fnUntraced(function*(options: ToggleOptionsReq) {
|
|
3737
|
+
const terminal = yield* Terminal.Terminal
|
|
3738
|
+
const columns = yield* terminal.columns
|
|
3739
|
+
const figures = yield* platformFigures
|
|
3740
|
+
const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft
|
|
3741
|
+
const toggleText = `${options.active} / ${options.inactive}`
|
|
3742
|
+
const promptText = renderPrompt(toggleText, options.message, "?", figures.pointerSmall, { plain: true })
|
|
3743
|
+
const clearOutput = eraseText(promptText, columns)
|
|
3744
|
+
return clearOutput + clearPrompt
|
|
3745
|
+
})
|
|
3746
|
+
|
|
3747
|
+
const renderToggle = (
|
|
3748
|
+
value: boolean,
|
|
3749
|
+
options: ToggleOptionsReq,
|
|
3750
|
+
submitted: boolean = false
|
|
3751
|
+
) => {
|
|
3752
|
+
const separator = Ansi.annotate("/", Ansi.blackBright)
|
|
3753
|
+
const selectedAnnotation = Ansi.combine(Ansi.underlined, submitted ? Ansi.white : Ansi.cyanBright)
|
|
3754
|
+
const inactive = value
|
|
3755
|
+
? options.inactive
|
|
3756
|
+
: Ansi.annotate(options.inactive, selectedAnnotation)
|
|
3757
|
+
const active = value
|
|
3758
|
+
? Ansi.annotate(options.active, selectedAnnotation)
|
|
3759
|
+
: options.active
|
|
3760
|
+
return active + " " + separator + " " + inactive
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3763
|
+
const renderToggleOutput = (
|
|
3764
|
+
toggle: string,
|
|
3765
|
+
leadingSymbol: string,
|
|
3766
|
+
trailingSymbol: string,
|
|
3767
|
+
options: ToggleOptionsReq
|
|
3768
|
+
) => {
|
|
3769
|
+
const promptLines = options.message.split(NEWLINE_REGEXP)
|
|
3770
|
+
const prefix = leadingSymbol + " "
|
|
3771
|
+
if (Arr.isReadonlyArrayNonEmpty(promptLines)) {
|
|
3772
|
+
const lines = Arr.map(promptLines, (line) => annotateLine(line))
|
|
3773
|
+
return prefix + lines.join("\n") + " " + trailingSymbol + " " + toggle
|
|
3774
|
+
}
|
|
3775
|
+
return prefix + " " + trailingSymbol + " " + toggle
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
const renderToggleNextFrame = Effect.fnUntraced(function*(state: ToggleState, options: ToggleOptionsReq) {
|
|
3779
|
+
const figures = yield* platformFigures
|
|
3780
|
+
const leadingSymbol = Ansi.annotate("?", Ansi.cyanBright)
|
|
3781
|
+
const trailingSymbol = Ansi.annotate(figures.pointerSmall, Ansi.blackBright)
|
|
3782
|
+
const toggle = renderToggle(state, options)
|
|
3783
|
+
const promptMsg = renderToggleOutput(toggle, leadingSymbol, trailingSymbol, options)
|
|
3784
|
+
return Ansi.cursorHide + promptMsg
|
|
3785
|
+
})
|
|
3786
|
+
|
|
3787
|
+
const renderToggleSubmission = Effect.fnUntraced(function*(value: boolean, options: ToggleOptionsReq) {
|
|
3788
|
+
const figures = yield* platformFigures
|
|
3789
|
+
const leadingSymbol = Ansi.annotate(figures.tick, Ansi.green)
|
|
3790
|
+
const trailingSymbol = Ansi.annotate(figures.ellipsis, Ansi.blackBright)
|
|
3791
|
+
const toggle = renderToggle(value, options, true)
|
|
3792
|
+
const promptMsg = renderToggleOutput(toggle, leadingSymbol, trailingSymbol, options)
|
|
3793
|
+
return promptMsg + "\n"
|
|
3794
|
+
})
|
|
3795
|
+
|
|
3796
|
+
const activate = Effect.succeed(Action.NextFrame({ state: true }))
|
|
3797
|
+
const deactivate = Effect.succeed(Action.NextFrame({ state: false }))
|
|
3798
|
+
|
|
3799
|
+
const handleToggleRender = (options: ToggleOptionsReq) => {
|
|
3800
|
+
return (state: ToggleState, action: Action<ToggleState, boolean>) => {
|
|
3801
|
+
switch (action._tag) {
|
|
3802
|
+
case "Beep": {
|
|
3803
|
+
return Effect.succeed(renderBeep)
|
|
3804
|
+
}
|
|
3805
|
+
case "NextFrame": {
|
|
3806
|
+
return renderToggleNextFrame(state, options)
|
|
3807
|
+
}
|
|
3808
|
+
case "Submit": {
|
|
3809
|
+
return renderToggleSubmission(state, options)
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3815
|
+
const handleToggleProcess = (input: Terminal.UserInput, state: ToggleState) => {
|
|
3816
|
+
switch (input.key.name) {
|
|
3817
|
+
case "0":
|
|
3818
|
+
case "j":
|
|
3819
|
+
case "delete":
|
|
3820
|
+
case "right":
|
|
3821
|
+
case "down": {
|
|
3822
|
+
return deactivate
|
|
3823
|
+
}
|
|
3824
|
+
case "1":
|
|
3825
|
+
case "k":
|
|
3826
|
+
case "left":
|
|
3827
|
+
case "up": {
|
|
3828
|
+
return activate
|
|
3829
|
+
}
|
|
3830
|
+
case " ":
|
|
3831
|
+
case "tab": {
|
|
3832
|
+
return state ? deactivate : activate
|
|
3833
|
+
}
|
|
3834
|
+
case "enter":
|
|
3835
|
+
case "return": {
|
|
3836
|
+
return Effect.succeed(Action.Submit({ value: state }))
|
|
3837
|
+
}
|
|
3838
|
+
default: {
|
|
3839
|
+
return Effect.succeed(Action.Beep())
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
const entriesToDisplay = (cursor: number, total: number, maxVisible?: number) => {
|
|
3845
|
+
const max = maxVisible === undefined ? total : maxVisible
|
|
3846
|
+
let startIndex = Math.min(total - max, cursor - Math.floor(max / 2))
|
|
3847
|
+
if (startIndex < 0) {
|
|
3848
|
+
startIndex = 0
|
|
3849
|
+
}
|
|
3850
|
+
const endIndex = Math.min(startIndex + max, total)
|
|
3851
|
+
return { startIndex, endIndex }
|
|
3852
|
+
}
|