@mannyc1/ts-release 0.0.6 → 0.2.2
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/ARCHITECTURE.md +124 -87
- package/CHANGELOG.md +115 -0
- package/LICENSE +21 -0
- package/README.md +272 -540
- package/SPEC.md +206 -305
- package/apps/release-ts/README.md +32 -0
- package/apps/release-ts/src/cli/command.ts +164 -0
- package/apps/release-ts/src/cli/commands.ts +351 -0
- package/apps/release-ts/src/cli/main.ts +43 -0
- package/apps/release-ts/src/cli/node-main.ts +49 -0
- package/apps/ts-release-agents/LICENSE +21 -0
- package/apps/ts-release-agents/README.md +21 -0
- package/apps/ts-release-agents/evals/cases.json +11 -0
- package/apps/ts-release-agents/manifests/claude.json +5 -0
- package/apps/ts-release-agents/manifests/codex.json +5 -0
- package/apps/ts-release-agents/package.json +11 -0
- package/apps/ts-release-agents/skills/release/SKILL.md +48 -0
- package/apps/ts-release-agents/skills/release/references/configuration.md +18 -0
- package/apps/ts-release-agents/skills/release/references/recovery.md +10 -0
- package/apps/ts-release-agents/skills/release/references/staged-workflow.md +12 -0
- package/apps/ts-release-agents/skills/release/references/target-selection.md +13 -0
- package/apps/ts-release-agents/skills/release/references/verification.md +14 -0
- package/apps/ts-release-agents/src/build.ts +105 -0
- package/apps/ts-release-agents/src/check.ts +117 -0
- package/apps/ts-release-agents/src/install.ts +121 -0
- package/apps/ts-release-agents/test/contract.test.ts +56 -0
- package/apps/ts-release-agents/tsconfig.json +5 -0
- package/dist/api/api.d.ts +15 -0
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +244 -0
- package/dist/api/api.js.map +1 -0
- package/dist/api/errors.d.ts +39 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +32 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/input.d.ts +10 -0
- package/dist/api/input.d.ts.map +1 -0
- package/dist/api/input.js +73 -0
- package/dist/api/input.js.map +1 -0
- package/dist/api/runtime.d.ts +18 -0
- package/dist/api/runtime.d.ts.map +1 -0
- package/dist/api/runtime.js +7 -0
- package/dist/api/runtime.js.map +1 -0
- package/dist/api/types.d.ts +76 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +17 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/ts-release.js +39239 -0
- package/dist/capabilities/bun-targets.d.ts +3 -0
- package/dist/capabilities/bun-targets.d.ts.map +1 -0
- package/dist/capabilities/bun-targets.js +3 -0
- package/dist/capabilities/bun-targets.js.map +1 -0
- package/dist/capabilities/field-ownership.d.ts +17 -0
- package/dist/capabilities/field-ownership.d.ts.map +1 -0
- package/dist/capabilities/field-ownership.js +40 -0
- package/dist/capabilities/field-ownership.js.map +1 -0
- package/dist/capabilities/module.d.ts +91 -0
- package/dist/capabilities/module.d.ts.map +1 -0
- package/dist/capabilities/module.js +2 -0
- package/dist/capabilities/module.js.map +1 -0
- package/dist/capabilities/registry.d.ts +829 -0
- package/dist/capabilities/registry.d.ts.map +1 -0
- package/dist/capabilities/registry.js +291 -0
- package/dist/capabilities/registry.js.map +1 -0
- package/dist/config/config.d.ts +6 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +42 -0
- package/dist/config/config.js.map +1 -0
- package/dist/correction/coordinator.d.ts +248 -0
- package/dist/correction/coordinator.d.ts.map +1 -0
- package/dist/correction/coordinator.js +274 -0
- package/dist/correction/coordinator.js.map +1 -0
- package/dist/correction/index.d.ts +3 -0
- package/dist/correction/index.d.ts.map +1 -0
- package/dist/correction/index.js +3 -0
- package/dist/correction/index.js.map +1 -0
- package/dist/correction/intent.d.ts +111 -0
- package/dist/correction/intent.d.ts.map +1 -0
- package/dist/correction/intent.js +146 -0
- package/dist/correction/intent.js.map +1 -0
- package/dist/drivers/archive.d.ts +8 -0
- package/dist/drivers/archive.d.ts.map +1 -0
- package/dist/drivers/archive.js +101 -0
- package/dist/drivers/archive.js.map +1 -0
- package/dist/drivers/contain.d.ts +6 -0
- package/dist/drivers/contain.d.ts.map +1 -0
- package/dist/drivers/contain.js +17 -0
- package/dist/drivers/contain.js.map +1 -0
- package/dist/drivers/environment.d.ts +4 -0
- package/dist/drivers/environment.d.ts.map +1 -0
- package/dist/drivers/environment.js +18 -0
- package/dist/drivers/environment.js.map +1 -0
- package/dist/drivers/errors.d.ts +9 -0
- package/dist/drivers/errors.d.ts.map +1 -0
- package/dist/drivers/errors.js +6 -0
- package/dist/drivers/errors.js.map +1 -0
- package/dist/drivers/glob.d.ts +2 -0
- package/dist/drivers/glob.d.ts.map +1 -0
- package/dist/drivers/glob.js +162 -0
- package/dist/drivers/glob.js.map +1 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.d.ts.map +1 -0
- package/dist/drivers/process.js +257 -0
- package/dist/drivers/process.js.map +1 -0
- package/dist/drivers/redact.d.ts +4 -0
- package/dist/drivers/redact.d.ts.map +1 -0
- package/dist/drivers/redact.js +24 -0
- package/dist/drivers/redact.js.map +1 -0
- package/dist/drivers/seccomp-helper-source.d.ts +7 -0
- package/dist/drivers/seccomp-helper-source.d.ts.map +1 -0
- package/dist/drivers/seccomp-helper-source.js +121 -0
- package/dist/drivers/seccomp-helper-source.js.map +1 -0
- package/dist/drivers/utils.d.ts +4 -0
- package/dist/drivers/utils.d.ts.map +1 -0
- package/dist/drivers/utils.js +5 -0
- package/dist/drivers/utils.js.map +1 -0
- package/dist/drivers/workspace.d.ts +6 -0
- package/dist/drivers/workspace.d.ts.map +1 -0
- package/dist/drivers/workspace.js +49 -0
- package/dist/drivers/workspace.js.map +1 -0
- package/dist/extensions/provider-adapter.d.ts +48 -0
- package/dist/extensions/provider-adapter.d.ts.map +1 -0
- package/dist/extensions/provider-adapter.js +64 -0
- package/dist/extensions/provider-adapter.js.map +1 -0
- package/dist/host.d.ts +33 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +20 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/model/artifact-collection.d.ts +84 -0
- package/dist/model/artifact-collection.d.ts.map +1 -0
- package/dist/model/artifact-collection.js +185 -0
- package/dist/model/artifact-collection.js.map +1 -0
- package/dist/model/authority.d.ts +89 -0
- package/dist/model/authority.d.ts.map +1 -0
- package/dist/model/authority.js +80 -0
- package/dist/model/authority.js.map +1 -0
- package/dist/model/bun-targets.d.ts +34 -0
- package/dist/model/bun-targets.d.ts.map +1 -0
- package/dist/model/bun-targets.js +17 -0
- package/dist/model/bun-targets.js.map +1 -0
- package/dist/model/canonical.d.ts +8 -0
- package/dist/model/canonical.d.ts.map +1 -0
- package/dist/model/canonical.js +205 -0
- package/dist/model/canonical.js.map +1 -0
- package/dist/model/catalog.d.ts +76 -0
- package/dist/model/catalog.d.ts.map +1 -0
- package/dist/model/catalog.js +174 -0
- package/dist/model/catalog.js.map +1 -0
- package/dist/model/digest.d.ts +53 -0
- package/dist/model/digest.d.ts.map +1 -0
- package/dist/model/digest.js +127 -0
- package/dist/model/digest.js.map +1 -0
- package/dist/model/errors.d.ts +14 -0
- package/dist/model/errors.d.ts.map +1 -0
- package/dist/model/errors.js +8 -0
- package/dist/model/errors.js.map +1 -0
- package/dist/model/primitives.d.ts +19 -0
- package/dist/model/primitives.d.ts.map +1 -0
- package/dist/model/primitives.js +18 -0
- package/dist/model/primitives.js.map +1 -0
- package/dist/model/pypi.d.ts +12 -0
- package/dist/model/pypi.d.ts.map +1 -0
- package/dist/model/pypi.js +20 -0
- package/dist/model/pypi.js.map +1 -0
- package/dist/model/python-distribution.d.ts +33 -0
- package/dist/model/python-distribution.d.ts.map +1 -0
- package/dist/model/python-distribution.js +367 -0
- package/dist/model/python-distribution.js.map +1 -0
- package/dist/model/secret-patterns.d.ts +2 -0
- package/dist/model/secret-patterns.d.ts.map +1 -0
- package/dist/model/secret-patterns.js +12 -0
- package/dist/model/secret-patterns.js.map +1 -0
- package/dist/platform/bun.d.ts +7 -0
- package/dist/platform/bun.d.ts.map +1 -0
- package/dist/platform/bun.js +15 -0
- package/dist/platform/bun.js.map +1 -0
- package/dist/platform/credentials.d.ts +32 -0
- package/dist/platform/credentials.d.ts.map +1 -0
- package/dist/platform/credentials.js +772 -0
- package/dist/platform/credentials.js.map +1 -0
- package/dist/platform/host-support.d.ts +2 -0
- package/dist/platform/host-support.d.ts.map +1 -0
- package/dist/platform/host-support.js +4 -0
- package/dist/platform/host-support.js.map +1 -0
- package/dist/platform/node.d.ts +7 -0
- package/dist/platform/node.d.ts.map +1 -0
- package/dist/platform/node.js +15 -0
- package/dist/platform/node.js.map +1 -0
- package/dist/platform/release-runtime.d.ts +11 -0
- package/dist/platform/release-runtime.d.ts.map +1 -0
- package/dist/platform/release-runtime.js +34 -0
- package/dist/platform/release-runtime.js.map +1 -0
- package/dist/platform/services.d.ts +15 -0
- package/dist/platform/services.d.ts.map +1 -0
- package/dist/platform/services.js +30 -0
- package/dist/platform/services.js.map +1 -0
- package/dist/platform/source-observer.d.ts +5 -0
- package/dist/platform/source-observer.d.ts.map +1 -0
- package/dist/platform/source-observer.js +159 -0
- package/dist/platform/source-observer.js.map +1 -0
- package/dist/provider-sdk.d.ts +14 -0
- package/dist/provider-sdk.d.ts.map +1 -0
- package/dist/provider-sdk.js +10 -0
- package/dist/provider-sdk.js.map +1 -0
- package/dist/publication/adapter.d.ts +212 -0
- package/dist/publication/adapter.d.ts.map +1 -0
- package/dist/publication/adapter.js +83 -0
- package/dist/publication/adapter.js.map +1 -0
- package/dist/publication/authority.d.ts +137 -0
- package/dist/publication/authority.d.ts.map +1 -0
- package/dist/publication/authority.js +233 -0
- package/dist/publication/authority.js.map +1 -0
- package/dist/publication/catalog-git.d.ts +37 -0
- package/dist/publication/catalog-git.d.ts.map +1 -0
- package/dist/publication/catalog-git.js +451 -0
- package/dist/publication/catalog-git.js.map +1 -0
- package/dist/publication/claim.d.ts +39 -0
- package/dist/publication/claim.d.ts.map +1 -0
- package/dist/publication/claim.js +31 -0
- package/dist/publication/claim.js.map +1 -0
- package/dist/publication/coordinator.d.ts +246 -0
- package/dist/publication/coordinator.d.ts.map +1 -0
- package/dist/publication/coordinator.js +370 -0
- package/dist/publication/coordinator.js.map +1 -0
- package/dist/publication/github.d.ts +36 -0
- package/dist/publication/github.d.ts.map +1 -0
- package/dist/publication/github.js +644 -0
- package/dist/publication/github.js.map +1 -0
- package/dist/publication/http.d.ts +69 -0
- package/dist/publication/http.d.ts.map +1 -0
- package/dist/publication/http.js +29 -0
- package/dist/publication/http.js.map +1 -0
- package/dist/publication/index.d.ts +5 -0
- package/dist/publication/index.d.ts.map +1 -0
- package/dist/publication/index.js +5 -0
- package/dist/publication/index.js.map +1 -0
- package/dist/publication/npm.d.ts +40 -0
- package/dist/publication/npm.d.ts.map +1 -0
- package/dist/publication/npm.js +359 -0
- package/dist/publication/npm.js.map +1 -0
- package/dist/publication/profiles.d.ts +136 -0
- package/dist/publication/profiles.d.ts.map +1 -0
- package/dist/publication/profiles.js +90 -0
- package/dist/publication/profiles.js.map +1 -0
- package/dist/publication/publisher.d.ts +82 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/publisher.js +53 -0
- package/dist/publication/publisher.js.map +1 -0
- package/dist/publication/pypi.d.ts +45 -0
- package/dist/publication/pypi.d.ts.map +1 -0
- package/dist/publication/pypi.js +369 -0
- package/dist/publication/pypi.js.map +1 -0
- package/dist/publication/recovery.d.ts +663 -0
- package/dist/publication/recovery.d.ts.map +1 -0
- package/dist/publication/recovery.js +252 -0
- package/dist/publication/recovery.js.map +1 -0
- package/dist/publication/report.d.ts +1061 -0
- package/dist/publication/report.d.ts.map +1 -0
- package/dist/publication/report.js +441 -0
- package/dist/publication/report.js.map +1 -0
- package/dist/recipes/config.d.ts +296 -0
- package/dist/recipes/config.d.ts.map +1 -0
- package/dist/recipes/config.js +325 -0
- package/dist/recipes/config.js.map +1 -0
- package/dist/release/capabilities.d.ts +12 -0
- package/dist/release/capabilities.d.ts.map +1 -0
- package/dist/release/capabilities.js +395 -0
- package/dist/release/capabilities.js.map +1 -0
- package/dist/release/compiler.d.ts +5 -0
- package/dist/release/compiler.d.ts.map +1 -0
- package/dist/release/compiler.js +19 -0
- package/dist/release/compiler.js.map +1 -0
- package/dist/release/config.d.ts +5 -0
- package/dist/release/config.d.ts.map +1 -0
- package/dist/release/config.js +10 -0
- package/dist/release/config.js.map +1 -0
- package/dist/release/context.d.ts +96 -0
- package/dist/release/context.d.ts.map +1 -0
- package/dist/release/context.js +168 -0
- package/dist/release/context.js.map +1 -0
- package/dist/release/graph.d.ts +271 -0
- package/dist/release/graph.d.ts.map +1 -0
- package/dist/release/graph.js +766 -0
- package/dist/release/graph.js.map +1 -0
- package/dist/release/inspect.d.ts +88 -0
- package/dist/release/inspect.d.ts.map +1 -0
- package/dist/release/inspect.js +75 -0
- package/dist/release/inspect.js.map +1 -0
- package/dist/release/prepare.d.ts +24 -0
- package/dist/release/prepare.d.ts.map +1 -0
- package/dist/release/prepare.js +1116 -0
- package/dist/release/prepare.js.map +1 -0
- package/dist/release/prepared-ref.d.ts +60 -0
- package/dist/release/prepared-ref.d.ts.map +1 -0
- package/dist/release/prepared-ref.js +131 -0
- package/dist/release/prepared-ref.js.map +1 -0
- package/dist/release/prepared-store.d.ts +90 -0
- package/dist/release/prepared-store.d.ts.map +1 -0
- package/dist/release/prepared-store.js +337 -0
- package/dist/release/prepared-store.js.map +1 -0
- package/dist/release/prepared.d.ts +172 -0
- package/dist/release/prepared.d.ts.map +1 -0
- package/dist/release/prepared.js +268 -0
- package/dist/release/prepared.js.map +1 -0
- package/dist/release/staging.d.ts +31 -0
- package/dist/release/staging.d.ts.map +1 -0
- package/dist/release/staging.js +218 -0
- package/dist/release/staging.js.map +1 -0
- package/dist/resolve/authored.d.ts +53 -0
- package/dist/resolve/authored.d.ts.map +1 -0
- package/dist/resolve/authored.js +55 -0
- package/dist/resolve/authored.js.map +1 -0
- package/dist/resolve/encode.d.ts +3 -0
- package/dist/resolve/encode.d.ts.map +1 -0
- package/dist/resolve/encode.js +21 -0
- package/dist/resolve/encode.js.map +1 -0
- package/dist/resolve/errors.d.ts +7 -0
- package/dist/resolve/errors.d.ts.map +1 -0
- package/dist/resolve/errors.js +17 -0
- package/dist/resolve/errors.js.map +1 -0
- package/dist/resolve/facts.d.ts +12 -0
- package/dist/resolve/facts.d.ts.map +1 -0
- package/dist/resolve/facts.js +18 -0
- package/dist/resolve/facts.js.map +1 -0
- package/dist/resolve/resolve.d.ts +10 -0
- package/dist/resolve/resolve.d.ts.map +1 -0
- package/dist/resolve/resolve.js +242 -0
- package/dist/resolve/resolve.js.map +1 -0
- package/dist/store.d.ts +11 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +9 -0
- package/dist/store.js.map +1 -0
- package/examples/README.md +20 -30
- package/examples/github-release/release.config.json +11 -18
- package/examples/homebrew-tap/README.md +11 -0
- package/examples/homebrew-tap/release.config.json +40 -28
- package/examples/multi-target/release.config.json +28 -53
- package/examples/npm-first-publish/release.config.json +23 -25
- package/examples/npm-only/release.config.json +22 -30
- package/examples/portable-cli/README.md +17 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-arm64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-x64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-arm64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-x64 +1 -0
- package/examples/portable-cli/artifacts/portable-example-0.1.0-windows-x64.exe +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_10_15_x86_64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_11_0_arm64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_aarch64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_x86_64.whl +1 -0
- package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-win_amd64.whl +1 -0
- package/examples/portable-cli/package.json +9 -0
- package/examples/portable-cli/release.config.json +53 -0
- package/examples/portable-cli/src/cli.ts +3 -0
- package/examples/pypi-registry/README.md +8 -0
- package/examples/scoop-bucket/README.md +10 -0
- package/examples/scoop-bucket/release.config.json +40 -30
- package/package.json +61 -154
- package/src/api/api.ts +365 -0
- package/src/api/errors.ts +36 -0
- package/src/api/input.ts +92 -0
- package/src/api/runtime.ts +14 -0
- package/src/api/types.ts +103 -0
- package/src/capabilities/bun-targets.ts +2 -0
- package/src/capabilities/field-ownership.ts +60 -0
- package/src/capabilities/module.ts +158 -0
- package/src/capabilities/registry.ts +333 -0
- package/src/config/config.ts +48 -0
- package/src/correction/coordinator.ts +336 -0
- package/src/correction/index.ts +2 -0
- package/src/correction/intent.ts +172 -0
- package/src/drivers/archive.ts +102 -0
- package/src/drivers/contain.ts +20 -0
- package/src/drivers/environment.ts +28 -0
- package/src/drivers/errors.ts +6 -0
- package/src/drivers/glob.ts +137 -0
- package/src/drivers/process.ts +340 -0
- package/src/drivers/redact.ts +31 -0
- package/src/drivers/seccomp-helper-source.ts +121 -0
- package/src/drivers/utils.ts +10 -0
- package/src/drivers/workspace.ts +40 -0
- package/src/extensions/provider-adapter.ts +99 -0
- package/src/host.ts +140 -0
- package/src/index.ts +64 -0
- package/src/model/artifact-collection.ts +237 -0
- package/src/model/authority.ts +116 -0
- package/src/model/bun-targets.ts +34 -0
- package/src/model/canonical.ts +205 -0
- package/src/model/catalog.ts +220 -0
- package/src/model/digest.ts +172 -0
- package/src/model/errors.ts +6 -0
- package/src/model/primitives.ts +37 -0
- package/src/model/pypi.ts +30 -0
- package/src/model/python-distribution.ts +360 -0
- package/src/model/secret-patterns.ts +11 -0
- package/src/platform/bun.ts +38 -0
- package/src/platform/credentials.ts +1083 -0
- package/src/platform/host-support.ts +4 -0
- package/src/platform/node.ts +38 -0
- package/src/platform/release-runtime.ts +47 -0
- package/src/platform/services.ts +57 -0
- package/src/platform/source-observer.ts +193 -0
- package/src/provider-sdk.ts +48 -0
- package/src/publication/adapter.ts +132 -0
- package/src/publication/authority.ts +397 -0
- package/src/publication/catalog-git.ts +603 -0
- package/src/publication/claim.ts +51 -0
- package/src/publication/coordinator.ts +578 -0
- package/src/publication/github.ts +954 -0
- package/src/publication/http.ts +101 -0
- package/src/publication/index.ts +4 -0
- package/src/publication/npm.ts +525 -0
- package/src/publication/profiles.ts +94 -0
- package/src/publication/publisher.ts +130 -0
- package/src/publication/pypi.ts +463 -0
- package/src/publication/recovery.ts +349 -0
- package/src/publication/report.ts +628 -0
- package/src/recipes/config.ts +395 -0
- package/src/release/capabilities.ts +459 -0
- package/src/release/compiler.ts +28 -0
- package/src/release/config.ts +12 -0
- package/src/release/context.ts +223 -0
- package/src/release/graph.ts +866 -0
- package/src/release/inspect.ts +83 -0
- package/src/release/prepare.ts +1331 -0
- package/src/release/prepared-ref.ts +193 -0
- package/src/release/prepared-store.ts +377 -0
- package/src/release/prepared.ts +299 -0
- package/src/release/staging.ts +257 -0
- package/src/resolve/authored.ts +64 -0
- package/src/resolve/encode.ts +22 -0
- package/src/resolve/errors.ts +15 -0
- package/src/resolve/facts.ts +18 -0
- package/src/resolve/resolve.ts +328 -0
- package/src/store.ts +28 -0
- package/templates/README.md +55 -59
- package/templates/bun-cli-github/README.md +12 -0
- package/templates/bun-cli-github/release.config.json +51 -0
- package/templates/github-actions/release.yml +57 -0
- package/templates/github-actions/reviewed-release.yml +80 -0
- package/templates/multi-target-homebrew/README.md +10 -0
- package/templates/multi-target-homebrew/release.config.json +43 -60
- package/templates/multi-target-scoop/README.md +10 -0
- package/templates/multi-target-scoop/release.config.json +43 -62
- package/templates/npm-github/release.config.json +25 -38
- package/templates/npm-github/reviewed-release.config.json +37 -0
- package/templates/npm-only/README.md +10 -0
- package/templates/npm-only/release.config.json +15 -30
- package/templates/portable-cli/README.md +13 -0
- package/templates/portable-cli/release.config.json +53 -0
- package/dist/config/errors.d.ts +0 -24
- package/dist/config/errors.d.ts.map +0 -1
- package/dist/config/errors.js +0 -19
- package/dist/config/errors.js.map +0 -1
- package/dist/config/load.d.ts +0 -9
- package/dist/config/load.d.ts.map +0 -1
- package/dist/config/load.js +0 -29
- package/dist/config/load.js.map +0 -1
- package/dist/config/schema.d.ts +0 -12
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/config/schema.js +0 -19
- package/dist/config/schema.js.map +0 -1
- package/dist/domain/artifact.d.ts +0 -36
- package/dist/domain/artifact.d.ts.map +0 -1
- package/dist/domain/artifact.js +0 -29
- package/dist/domain/artifact.js.map +0 -1
- package/dist/domain/evidence.d.ts +0 -108
- package/dist/domain/evidence.d.ts.map +0 -1
- package/dist/domain/evidence.js +0 -96
- package/dist/domain/evidence.js.map +0 -1
- package/dist/domain/operation.d.ts +0 -153
- package/dist/domain/operation.d.ts.map +0 -1
- package/dist/domain/operation.js +0 -320
- package/dist/domain/operation.js.map +0 -1
- package/dist/domain/release.d.ts +0 -141
- package/dist/domain/release.d.ts.map +0 -1
- package/dist/domain/release.js +0 -127
- package/dist/domain/release.js.map +0 -1
- package/dist/domain/remote-state.d.ts +0 -85
- package/dist/domain/remote-state.d.ts.map +0 -1
- package/dist/domain/remote-state.js +0 -77
- package/dist/domain/remote-state.js.map +0 -1
- package/dist/domain/status.d.ts +0 -43
- package/dist/domain/status.d.ts.map +0 -1
- package/dist/domain/status.js +0 -51
- package/dist/domain/status.js.map +0 -1
- package/dist/domain/target.d.ts +0 -135
- package/dist/domain/target.d.ts.map +0 -1
- package/dist/domain/target.js +0 -137
- package/dist/domain/target.js.map +0 -1
- package/dist/host/host.d.ts +0 -32
- package/dist/host/host.d.ts.map +0 -1
- package/dist/host/host.js +0 -24
- package/dist/host/host.js.map +0 -1
- package/dist/host/http-live.d.ts +0 -6
- package/dist/host/http-live.d.ts.map +0 -1
- package/dist/host/http-live.js +0 -86
- package/dist/host/http-live.js.map +0 -1
- package/dist/host/http.d.ts +0 -43
- package/dist/host/http.d.ts.map +0 -1
- package/dist/host/http.js +0 -59
- package/dist/host/http.js.map +0 -1
- package/dist/host/platform.d.ts +0 -10
- package/dist/host/platform.d.ts.map +0 -1
- package/dist/host/platform.js +0 -114
- package/dist/host/platform.js.map +0 -1
- package/dist/host/test.d.ts +0 -23
- package/dist/host/test.d.ts.map +0 -1
- package/dist/host/test.js +0 -222
- package/dist/host/test.js.map +0 -1
- package/dist/internal/workflow-phases.d.ts +0 -3
- package/dist/internal/workflow-phases.d.ts.map +0 -1
- package/dist/internal/workflow-phases.js +0 -2
- package/dist/internal/workflow-phases.js.map +0 -1
- package/dist/internal/workspace-path.d.ts +0 -15
- package/dist/internal/workspace-path.d.ts.map +0 -1
- package/dist/internal/workspace-path.js +0 -36
- package/dist/internal/workspace-path.js.map +0 -1
- package/dist/planner/artifact-inventory.d.ts +0 -9
- package/dist/planner/artifact-inventory.d.ts.map +0 -1
- package/dist/planner/artifact-inventory.js +0 -84
- package/dist/planner/artifact-inventory.js.map +0 -1
- package/dist/planner/create-release-plan.d.ts +0 -5
- package/dist/planner/create-release-plan.d.ts.map +0 -1
- package/dist/planner/create-release-plan.js +0 -25
- package/dist/planner/create-release-plan.js.map +0 -1
- package/dist/planner/errors.d.ts +0 -81
- package/dist/planner/errors.d.ts.map +0 -1
- package/dist/planner/errors.js +0 -70
- package/dist/planner/errors.js.map +0 -1
- package/dist/planner/evidence-recorder.d.ts +0 -26
- package/dist/planner/evidence-recorder.d.ts.map +0 -1
- package/dist/planner/evidence-recorder.js +0 -330
- package/dist/planner/evidence-recorder.js.map +0 -1
- package/dist/planner/executor.d.ts +0 -58
- package/dist/planner/executor.d.ts.map +0 -1
- package/dist/planner/executor.js +0 -159
- package/dist/planner/executor.js.map +0 -1
- package/dist/planner/normalize-release.d.ts +0 -16
- package/dist/planner/normalize-release.d.ts.map +0 -1
- package/dist/planner/normalize-release.js +0 -218
- package/dist/planner/normalize-release.js.map +0 -1
- package/dist/planner/reconcile.d.ts +0 -17
- package/dist/planner/reconcile.d.ts.map +0 -1
- package/dist/planner/reconcile.js +0 -261
- package/dist/planner/reconcile.js.map +0 -1
- package/dist/planner/release-eligibility.d.ts +0 -39
- package/dist/planner/release-eligibility.d.ts.map +0 -1
- package/dist/planner/release-eligibility.js +0 -578
- package/dist/planner/release-eligibility.js.map +0 -1
- package/dist/planner/render-plan.d.ts +0 -15
- package/dist/planner/render-plan.d.ts.map +0 -1
- package/dist/planner/render-plan.js +0 -238
- package/dist/planner/render-plan.js.map +0 -1
- package/dist/planner/status.d.ts +0 -40
- package/dist/planner/status.d.ts.map +0 -1
- package/dist/planner/status.js +0 -313
- package/dist/planner/status.js.map +0 -1
- package/dist/targets/adapter-helpers.d.ts +0 -64
- package/dist/targets/adapter-helpers.d.ts.map +0 -1
- package/dist/targets/adapter-helpers.js +0 -124
- package/dist/targets/adapter-helpers.js.map +0 -1
- package/dist/targets/adapter.d.ts +0 -17
- package/dist/targets/adapter.d.ts.map +0 -1
- package/dist/targets/adapter.js +0 -2
- package/dist/targets/adapter.js.map +0 -1
- package/dist/targets/github-release.d.ts +0 -25
- package/dist/targets/github-release.d.ts.map +0 -1
- package/dist/targets/github-release.js +0 -82
- package/dist/targets/github-release.js.map +0 -1
- package/dist/targets/github.d.ts +0 -11
- package/dist/targets/github.d.ts.map +0 -1
- package/dist/targets/github.js +0 -125
- package/dist/targets/github.js.map +0 -1
- package/dist/targets/homebrew.d.ts +0 -11
- package/dist/targets/homebrew.d.ts.map +0 -1
- package/dist/targets/homebrew.js +0 -97
- package/dist/targets/homebrew.js.map +0 -1
- package/dist/targets/live.d.ts +0 -5
- package/dist/targets/live.d.ts.map +0 -1
- package/dist/targets/live.js +0 -50
- package/dist/targets/live.js.map +0 -1
- package/dist/targets/npm.d.ts +0 -10
- package/dist/targets/npm.d.ts.map +0 -1
- package/dist/targets/npm.js +0 -118
- package/dist/targets/npm.js.map +0 -1
- package/dist/targets/pypi.d.ts +0 -11
- package/dist/targets/pypi.d.ts.map +0 -1
- package/dist/targets/pypi.js +0 -103
- package/dist/targets/pypi.js.map +0 -1
- package/dist/targets/registry.d.ts +0 -25
- package/dist/targets/registry.d.ts.map +0 -1
- package/dist/targets/registry.js +0 -34
- package/dist/targets/registry.js.map +0 -1
- package/dist/targets/scoop.d.ts +0 -11
- package/dist/targets/scoop.d.ts.map +0 -1
- package/dist/targets/scoop.js +0 -78
- package/dist/targets/scoop.js.map +0 -1
- package/dist/types/effect-internal.d.ts +0 -5
- package/dist/types/effect-internal.d.ts.map +0 -1
- package/dist/types/effect-internal.js +0 -2
- package/dist/types/effect-internal.js.map +0 -1
- package/dist/workflows/config.d.ts +0 -252
- package/dist/workflows/config.d.ts.map +0 -1
- package/dist/workflows/config.js +0 -465
- package/dist/workflows/config.js.map +0 -1
- package/dist/workflows/diagnostics.d.ts +0 -62
- package/dist/workflows/diagnostics.d.ts.map +0 -1
- package/dist/workflows/diagnostics.js +0 -527
- package/dist/workflows/diagnostics.js.map +0 -1
- package/dist/workflows/evidence.d.ts +0 -26
- package/dist/workflows/evidence.d.ts.map +0 -1
- package/dist/workflows/evidence.js +0 -44
- package/dist/workflows/evidence.js.map +0 -1
- package/dist/workflows/index.d.ts +0 -7
- package/dist/workflows/index.d.ts.map +0 -1
- package/dist/workflows/index.js +0 -6
- package/dist/workflows/index.js.map +0 -1
- package/dist/workflows/init.d.ts +0 -84
- package/dist/workflows/init.d.ts.map +0 -1
- package/dist/workflows/init.js +0 -441
- package/dist/workflows/init.js.map +0 -1
- package/dist/workflows/live.d.ts +0 -9
- package/dist/workflows/live.d.ts.map +0 -1
- package/dist/workflows/live.js +0 -7
- package/dist/workflows/live.js.map +0 -1
- package/dist/workflows/options.d.ts +0 -30
- package/dist/workflows/options.d.ts.map +0 -1
- package/dist/workflows/options.js +0 -16
- package/dist/workflows/options.js.map +0 -1
- package/examples/non-strict-skips/artifacts/release-example-skips-0.1.0.tgz +0 -1
- package/examples/non-strict-skips/release.config.json +0 -31
- package/examples/pypi-registry/release.config.json +0 -31
- package/templates/github-actions/plan-and-approved-execute.yml +0 -58
- package/templates/github-actions/plan-only.yml +0 -33
- package/templates/github-actions/trusted-publishing.yml +0 -61
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createHash } from "node:crypto"
|
|
2
|
+
|
|
3
|
+
export type Json =
|
|
4
|
+
| boolean
|
|
5
|
+
| null
|
|
6
|
+
| number
|
|
7
|
+
| string
|
|
8
|
+
| ReadonlyArray<Json>
|
|
9
|
+
| { readonly [key: string]: Json }
|
|
10
|
+
|
|
11
|
+
class StrictJsonParser {
|
|
12
|
+
private index = 0
|
|
13
|
+
constructor(private readonly text: string) {}
|
|
14
|
+
|
|
15
|
+
parse(): Json {
|
|
16
|
+
this.space()
|
|
17
|
+
const value = this.value()
|
|
18
|
+
this.space()
|
|
19
|
+
if (this.index !== this.text.length) this.fail("trailing input")
|
|
20
|
+
return value
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private fail(reason: string): never {
|
|
24
|
+
throw new Error(`Invalid strict JSON at ${this.index}: ${reason}`)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private space(): void {
|
|
28
|
+
while (/[\t\n\r ]/u.test(this.text[this.index] ?? "")) this.index += 1
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private take(expected: string): void {
|
|
32
|
+
if (!this.text.startsWith(expected, this.index)) this.fail(`expected ${expected}`)
|
|
33
|
+
this.index += expected.length
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private value(): Json {
|
|
37
|
+
const token = this.text[this.index]
|
|
38
|
+
if (token === "{") return this.object()
|
|
39
|
+
if (token === "[") return this.array()
|
|
40
|
+
if (token === '"') return this.string()
|
|
41
|
+
if (token === "t") {
|
|
42
|
+
this.take("true")
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
if (token === "f") {
|
|
46
|
+
this.take("false")
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
if (token === "n") {
|
|
50
|
+
this.take("null")
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
if (token === "-" || token !== undefined && /[0-9]/u.test(token)) return this.number()
|
|
54
|
+
return this.fail("expected value")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private string(): string {
|
|
58
|
+
const start = this.index
|
|
59
|
+
this.index += 1
|
|
60
|
+
let escaped = false
|
|
61
|
+
while (this.index < this.text.length) {
|
|
62
|
+
const character = this.text[this.index]!
|
|
63
|
+
if (!escaped && character === '"') {
|
|
64
|
+
this.index += 1
|
|
65
|
+
const value = JSON.parse(this.text.slice(start, this.index)) as string
|
|
66
|
+
if (value !== value.normalize("NFC")) this.fail("non-NFC string")
|
|
67
|
+
return value
|
|
68
|
+
}
|
|
69
|
+
if (!escaped && character.codePointAt(0)! < 0x20) this.fail("control character")
|
|
70
|
+
escaped = !escaped && character === "\\"
|
|
71
|
+
this.index += 1
|
|
72
|
+
}
|
|
73
|
+
return this.fail("unterminated string")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private number(): number {
|
|
77
|
+
const match = /^-?(?:0|[1-9][0-9]*)/u.exec(this.text.slice(this.index))
|
|
78
|
+
if (match === null) return this.fail("invalid number")
|
|
79
|
+
const token = match[0]
|
|
80
|
+
const next = this.text[this.index + token.length]
|
|
81
|
+
if (next === "." || next === "e" || next === "E") this.fail("float")
|
|
82
|
+
this.index += token.length
|
|
83
|
+
const value = Number(token)
|
|
84
|
+
if (!Number.isSafeInteger(value) || Object.is(value, -0)) this.fail("unsafe integer")
|
|
85
|
+
return value
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private array(): ReadonlyArray<Json> {
|
|
89
|
+
this.index += 1
|
|
90
|
+
this.space()
|
|
91
|
+
const result: Array<Json> = []
|
|
92
|
+
if (this.text[this.index] === "]") {
|
|
93
|
+
this.index += 1
|
|
94
|
+
return result
|
|
95
|
+
}
|
|
96
|
+
while (true) {
|
|
97
|
+
result.push(this.value())
|
|
98
|
+
this.space()
|
|
99
|
+
if (this.text[this.index] === "]") {
|
|
100
|
+
this.index += 1
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
103
|
+
this.take(",")
|
|
104
|
+
this.space()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private object(): { readonly [key: string]: Json } {
|
|
109
|
+
this.index += 1
|
|
110
|
+
this.space()
|
|
111
|
+
const result: Record<string, Json> = {}
|
|
112
|
+
if (this.text[this.index] === "}") {
|
|
113
|
+
this.index += 1
|
|
114
|
+
return result
|
|
115
|
+
}
|
|
116
|
+
while (true) {
|
|
117
|
+
if (this.text[this.index] !== '"') this.fail("expected object key")
|
|
118
|
+
const key = this.string()
|
|
119
|
+
if (Object.hasOwn(result, key)) this.fail(`duplicate key ${key}`)
|
|
120
|
+
this.space()
|
|
121
|
+
this.take(":")
|
|
122
|
+
this.space()
|
|
123
|
+
result[key] = this.value()
|
|
124
|
+
this.space()
|
|
125
|
+
if (this.text[this.index] === "}") {
|
|
126
|
+
this.index += 1
|
|
127
|
+
return result
|
|
128
|
+
}
|
|
129
|
+
this.take(",")
|
|
130
|
+
this.space()
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const codePointOrder = (left: string, right: string): number => {
|
|
136
|
+
const a = [...left]
|
|
137
|
+
const b = [...right]
|
|
138
|
+
let index = 0
|
|
139
|
+
while (index < Math.min(a.length, b.length)) {
|
|
140
|
+
const difference = a[index]!.codePointAt(0)! - b[index]!.codePointAt(0)!
|
|
141
|
+
if (difference !== 0) return difference
|
|
142
|
+
index += 1
|
|
143
|
+
}
|
|
144
|
+
return a.length - b.length
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const canonicalArray = (value: ReadonlyArray<unknown>, parents: Set<object>): string => {
|
|
148
|
+
let index = 0
|
|
149
|
+
while (index < value.length) {
|
|
150
|
+
if (!Object.hasOwn(value, index)) throw new Error("sparse array")
|
|
151
|
+
index += 1
|
|
152
|
+
}
|
|
153
|
+
return `[${value.map((item) => canonical(item, parents)).join(",")}]`
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const canonicalObject = (value: object, parents: Set<object>): string => {
|
|
157
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) throw new Error("non-plain object")
|
|
158
|
+
const entries = Object.entries(value).map(([key, item]) => [key.normalize("NFC"), item] as const)
|
|
159
|
+
if (new Set(entries.map(([key]) => key)).size !== entries.length) {
|
|
160
|
+
throw new Error("normalized key collision")
|
|
161
|
+
}
|
|
162
|
+
entries.sort(([left], [right]) => codePointOrder(left, right))
|
|
163
|
+
return `{${entries.map(([key, item]) =>
|
|
164
|
+
`${JSON.stringify(key)}:${canonical(item, parents)}`).join(",")}}`
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const canonical = (value: unknown, parents: Set<object>): string => {
|
|
168
|
+
if (value === null || typeof value === "boolean") return JSON.stringify(value)
|
|
169
|
+
if (typeof value === "string") return JSON.stringify(value.normalize("NFC"))
|
|
170
|
+
if (typeof value === "number") {
|
|
171
|
+
if (!Number.isSafeInteger(value) || Object.is(value, -0)) throw new Error("unsafe number")
|
|
172
|
+
return String(value)
|
|
173
|
+
}
|
|
174
|
+
if (typeof value !== "object") throw new Error("non-JSON value")
|
|
175
|
+
if (parents.has(value)) throw new Error("cyclic value")
|
|
176
|
+
parents.add(value)
|
|
177
|
+
try {
|
|
178
|
+
return Array.isArray(value)
|
|
179
|
+
? canonicalArray(value, parents)
|
|
180
|
+
: canonicalObject(value, parents)
|
|
181
|
+
} finally {
|
|
182
|
+
parents.delete(value)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const frame = (value: Uint8Array): Uint8Array => {
|
|
187
|
+
const result = new Uint8Array(value.length + 4)
|
|
188
|
+
new DataView(result.buffer).setUint32(0, value.length, false)
|
|
189
|
+
result.set(value, 4)
|
|
190
|
+
return result
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export const parseStrictJson = (text: string): Json => new StrictJsonParser(text).parse()
|
|
194
|
+
export const encodeCanonicalJson = (value: unknown): string =>
|
|
195
|
+
`${canonical(value, new Set())}\n`
|
|
196
|
+
export const hashFramed = (domain: string, parts: ReadonlyArray<Uint8Array>): string => {
|
|
197
|
+
const hash = createHash("sha256")
|
|
198
|
+
hash.update(frame(new TextEncoder().encode(domain.normalize("NFC"))))
|
|
199
|
+
parts.forEach((part) => {
|
|
200
|
+
hash.update(frame(part))
|
|
201
|
+
})
|
|
202
|
+
return hash.digest("hex")
|
|
203
|
+
}
|
|
204
|
+
export const hashCanonical = (domain: string, value: unknown): string =>
|
|
205
|
+
hashFramed(domain, [new TextEncoder().encode(encodeCanonicalJson(value))])
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
import * as Semver from "semver"
|
|
3
|
+
import { encodeCanonicalJson, parseStrictJson } from "./canonical.js"
|
|
4
|
+
import { Sha256Digest } from "./digest.js"
|
|
5
|
+
import { NonEmptyName, OutputId, SafeRelativePath, Version } from "./primitives.js"
|
|
6
|
+
|
|
7
|
+
const optional = Schema.optionalKey
|
|
8
|
+
|
|
9
|
+
export const GitHubRepositoryCoordinate = Schema.NonEmptyString.check(Schema.makeFilter(
|
|
10
|
+
(value: string) => /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/u.test(value)
|
|
11
|
+
? undefined
|
|
12
|
+
: "Catalog repository must be an owner/repository coordinate."
|
|
13
|
+
)).pipe(Schema.brand("GitHubRepositoryCoordinate"))
|
|
14
|
+
export type GitHubRepositoryCoordinate = typeof GitHubRepositoryCoordinate.Type
|
|
15
|
+
|
|
16
|
+
export const GitBranchName = Schema.NonEmptyString.check(Schema.makeFilter((value: string) =>
|
|
17
|
+
!value.startsWith("-") && !value.startsWith("/") && !value.endsWith("/") && !value.endsWith(".") &&
|
|
18
|
+
!value.endsWith(".lock") && !value.includes("..") && !value.includes("//") && !value.includes("@{") &&
|
|
19
|
+
!/[~^:?*[\\\u0000-\u001f\u007f]/u.test(value)
|
|
20
|
+
? undefined
|
|
21
|
+
: "Catalog branch must be one canonical Git branch name."))
|
|
22
|
+
.pipe(Schema.brand("GitBranchName"))
|
|
23
|
+
export type GitBranchName = typeof GitBranchName.Type
|
|
24
|
+
|
|
25
|
+
export const CatalogRepositoryPath = SafeRelativePath.check(Schema.makeFilter((value) =>
|
|
26
|
+
value.toString() !== "." ? undefined : "Catalog repository paths must identify files."))
|
|
27
|
+
.pipe(Schema.brand("CatalogRepositoryPath"))
|
|
28
|
+
export type CatalogRepositoryPath = typeof CatalogRepositoryPath.Type
|
|
29
|
+
|
|
30
|
+
export const CatalogArchitecture = Schema.Literals(["x64", "arm64"])
|
|
31
|
+
export type CatalogArchitecture = typeof CatalogArchitecture.Type
|
|
32
|
+
|
|
33
|
+
export class CatalogRenderSource extends Schema.Class<CatalogRenderSource>("CatalogRenderSource")({
|
|
34
|
+
artifactId: OutputId,
|
|
35
|
+
architecture: CatalogArchitecture,
|
|
36
|
+
url: Schema.NonEmptyString,
|
|
37
|
+
filename: NonEmptyName
|
|
38
|
+
}) {}
|
|
39
|
+
|
|
40
|
+
export class PreparedCatalogDownload extends Schema.Class<PreparedCatalogDownload>("PreparedCatalogDownload")({
|
|
41
|
+
architecture: CatalogArchitecture,
|
|
42
|
+
url: Schema.NonEmptyString,
|
|
43
|
+
filename: NonEmptyName,
|
|
44
|
+
sha256: Sha256Digest
|
|
45
|
+
}) {}
|
|
46
|
+
|
|
47
|
+
const rendererFields = {
|
|
48
|
+
name: NonEmptyName,
|
|
49
|
+
description: Schema.NonEmptyString,
|
|
50
|
+
homepage: Schema.NonEmptyString,
|
|
51
|
+
license: optional(Schema.NonEmptyString)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class HomebrewRenderer extends Schema.TaggedClass<HomebrewRenderer>()("homebrew", {
|
|
55
|
+
...rendererFields,
|
|
56
|
+
installPath: NonEmptyName
|
|
57
|
+
}) {}
|
|
58
|
+
|
|
59
|
+
export class ScoopRenderer extends Schema.TaggedClass<ScoopRenderer>()("scoop", {
|
|
60
|
+
...rendererFields,
|
|
61
|
+
bin: NonEmptyName
|
|
62
|
+
}) {}
|
|
63
|
+
|
|
64
|
+
export const CatalogRenderer = Schema.Union([HomebrewRenderer, ScoopRenderer])
|
|
65
|
+
export type CatalogRenderer = typeof CatalogRenderer.Type
|
|
66
|
+
|
|
67
|
+
export class PreparedCatalogRenderer
|
|
68
|
+
extends Schema.Class<PreparedCatalogRenderer>("PreparedCatalogRenderer")({
|
|
69
|
+
renderer: CatalogRenderer,
|
|
70
|
+
downloads: Schema.NonEmptyArray(PreparedCatalogDownload)
|
|
71
|
+
}) {}
|
|
72
|
+
|
|
73
|
+
export const CatalogManagedStatus = Schema.Literals(["active", "corrected", "superseded"])
|
|
74
|
+
|
|
75
|
+
export class CatalogManagedState extends Schema.Class<CatalogManagedState>("CatalogManagedState")({
|
|
76
|
+
schemaVersion: Schema.Literal("ts-release/catalog-state/v2"),
|
|
77
|
+
catalogId: NonEmptyName,
|
|
78
|
+
renderer: Schema.Literals(["homebrew", "scoop"]),
|
|
79
|
+
generation: Version,
|
|
80
|
+
status: CatalogManagedStatus,
|
|
81
|
+
targetDigest: Sha256Digest,
|
|
82
|
+
sourceRepository: GitHubRepositoryCoordinate,
|
|
83
|
+
sourceTag: NonEmptyName,
|
|
84
|
+
correctionId: optional(Sha256Digest),
|
|
85
|
+
reason: optional(Schema.NonEmptyString),
|
|
86
|
+
replacementVersion: optional(Version)
|
|
87
|
+
}) {}
|
|
88
|
+
|
|
89
|
+
export const encodeCatalogManagedState = (value: CatalogManagedState): Uint8Array =>
|
|
90
|
+
new TextEncoder().encode(encodeCanonicalJson(Schema.encodeSync(CatalogManagedState)(value)))
|
|
91
|
+
|
|
92
|
+
export const decodeCatalogManagedState = (bytes: Uint8Array): CatalogManagedState | undefined => {
|
|
93
|
+
try {
|
|
94
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes)
|
|
95
|
+
const value = Schema.decodeUnknownSync(CatalogManagedState, { onExcessProperty: "error" })(parseStrictJson(text))
|
|
96
|
+
if (Semver.valid(value.generation.toString()) !== value.generation.toString()) return undefined
|
|
97
|
+
const canonical = encodeCatalogManagedState(value)
|
|
98
|
+
return canonical.length === bytes.length && canonical.every((byte, index) => byte === bytes[index])
|
|
99
|
+
? value
|
|
100
|
+
: undefined
|
|
101
|
+
} catch {
|
|
102
|
+
return undefined
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const canonicalCatalogVersion = (value: string): Version => {
|
|
107
|
+
const parsed = Semver.valid(value)
|
|
108
|
+
if (parsed === null || parsed !== value) throw new Error(`Catalog generation requires a canonical semantic version, got ${JSON.stringify(value)}.`)
|
|
109
|
+
return Version.make(value)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const compareCatalogVersions = (left: string, right: string): number => {
|
|
113
|
+
canonicalCatalogVersion(left)
|
|
114
|
+
canonicalCatalogVersion(right)
|
|
115
|
+
return Semver.compare(left, right)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const assertDownloads = (downloads: ReadonlyArray<PreparedCatalogDownload>): void => {
|
|
119
|
+
if (downloads.length === 0) throw new Error("Catalog renderer requires at least one download.")
|
|
120
|
+
const architectures = downloads.map((download) => download.architecture)
|
|
121
|
+
if (new Set(architectures).size !== architectures.length) {
|
|
122
|
+
throw new Error("Catalog renderer repeats an architecture.")
|
|
123
|
+
}
|
|
124
|
+
for (const download of downloads) {
|
|
125
|
+
const url = new URL(download.url)
|
|
126
|
+
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.hash !== "") {
|
|
127
|
+
throw new Error("Catalog download URLs must be credential-free HTTPS URLs.")
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const rubyString = (value: string): string => JSON.stringify(value)
|
|
133
|
+
const formulaClass = (value: string): string => value.split(/[^A-Za-z0-9]+/u).filter(Boolean)
|
|
134
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join("") || "GeneratedFormula"
|
|
135
|
+
|
|
136
|
+
const homebrewDownload = (download: PreparedCatalogDownload, indent: string): ReadonlyArray<string> => [
|
|
137
|
+
`${indent}url ${rubyString(download.url)}`,
|
|
138
|
+
`${indent}sha256 ${rubyString(download.sha256.hex)}`
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
const renderHomebrew = (
|
|
142
|
+
version: Version,
|
|
143
|
+
renderer: HomebrewRenderer,
|
|
144
|
+
downloads: ReadonlyArray<PreparedCatalogDownload>
|
|
145
|
+
): string => {
|
|
146
|
+
const lines = [
|
|
147
|
+
`class ${formulaClass(renderer.name)} < Formula`,
|
|
148
|
+
` desc ${rubyString(renderer.description)}`,
|
|
149
|
+
` homepage ${rubyString(renderer.homepage)}`,
|
|
150
|
+
...(renderer.license === undefined ? [] : [` license ${rubyString(renderer.license)}`]),
|
|
151
|
+
` version ${rubyString(version.toString())}`
|
|
152
|
+
]
|
|
153
|
+
if (downloads.length === 1) {
|
|
154
|
+
lines.push(...homebrewDownload(downloads[0]!, " "))
|
|
155
|
+
} else {
|
|
156
|
+
lines.push("", " on_macos do")
|
|
157
|
+
for (const architecture of ["arm64", "x64"] as const) {
|
|
158
|
+
const download = downloads.find((candidate) => candidate.architecture === architecture)
|
|
159
|
+
if (download === undefined) continue
|
|
160
|
+
lines.push(` ${architecture === "arm64" ? "on_arm" : "on_intel"} do`)
|
|
161
|
+
lines.push(...homebrewDownload(download, " "))
|
|
162
|
+
lines.push(" end")
|
|
163
|
+
}
|
|
164
|
+
lines.push(" end")
|
|
165
|
+
}
|
|
166
|
+
lines.push(
|
|
167
|
+
"",
|
|
168
|
+
" def install",
|
|
169
|
+
` bin.install ${rubyString(renderer.installPath)} => ${rubyString(renderer.name)}`,
|
|
170
|
+
" end",
|
|
171
|
+
"",
|
|
172
|
+
" test do",
|
|
173
|
+
` assert_predicate bin/${rubyString(renderer.name)}, :executable?`,
|
|
174
|
+
" end",
|
|
175
|
+
"end",
|
|
176
|
+
""
|
|
177
|
+
)
|
|
178
|
+
return lines.join("\n")
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const scoopDownload = (download: PreparedCatalogDownload): Readonly<Record<string, string>> => ({
|
|
182
|
+
url: download.url,
|
|
183
|
+
hash: download.sha256.hex
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
const renderScoop = (
|
|
187
|
+
version: Version,
|
|
188
|
+
renderer: ScoopRenderer,
|
|
189
|
+
downloads: ReadonlyArray<PreparedCatalogDownload>
|
|
190
|
+
): string => {
|
|
191
|
+
const common: Record<string, unknown> = {
|
|
192
|
+
version: version.toString(),
|
|
193
|
+
description: renderer.description,
|
|
194
|
+
homepage: renderer.homepage,
|
|
195
|
+
...(renderer.license === undefined ? {} : { license: renderer.license })
|
|
196
|
+
}
|
|
197
|
+
const value = downloads.length === 1
|
|
198
|
+
? { ...common, ...scoopDownload(downloads[0]!), bin: renderer.bin.toString() }
|
|
199
|
+
: {
|
|
200
|
+
...common,
|
|
201
|
+
architecture: Object.fromEntries(downloads
|
|
202
|
+
.slice()
|
|
203
|
+
.sort((left, right) => left.architecture < right.architecture ? -1 : 1)
|
|
204
|
+
.map((download) => [download.architecture === "x64" ? "64bit" : "arm64", scoopDownload(download)])),
|
|
205
|
+
bin: renderer.bin.toString()
|
|
206
|
+
}
|
|
207
|
+
return `${JSON.stringify(value, null, 2)}\n`
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export const renderCatalog = (
|
|
211
|
+
version: Version,
|
|
212
|
+
renderer: CatalogRenderer,
|
|
213
|
+
downloads: ReadonlyArray<PreparedCatalogDownload>
|
|
214
|
+
): Uint8Array => {
|
|
215
|
+
canonicalCatalogVersion(version.toString())
|
|
216
|
+
assertDownloads(downloads)
|
|
217
|
+
return new TextEncoder().encode(renderer._tag === "homebrew"
|
|
218
|
+
? renderHomebrew(version, renderer, downloads)
|
|
219
|
+
: renderScoop(version, renderer, downloads))
|
|
220
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
import { createHash } from "node:crypto"
|
|
3
|
+
|
|
4
|
+
const lowercaseHex = (algorithm: "sha1" | "sha256" | "sha512", length: number) =>
|
|
5
|
+
Schema.String.check(Schema.makeFilter((value: string) =>
|
|
6
|
+
new RegExp(`^[a-f0-9]{${length}}$`, "u").test(value)
|
|
7
|
+
? undefined
|
|
8
|
+
: `${algorithm} digest bytes must be exactly ${length} lowercase hexadecimal characters.`
|
|
9
|
+
)).pipe(Schema.brand(`${algorithm}Hex`))
|
|
10
|
+
|
|
11
|
+
export const Sha1Hex = lowercaseHex("sha1", 40)
|
|
12
|
+
export type Sha1Hex = typeof Sha1Hex.Type
|
|
13
|
+
|
|
14
|
+
export const Sha256Hex = lowercaseHex("sha256", 64)
|
|
15
|
+
export type Sha256Hex = typeof Sha256Hex.Type
|
|
16
|
+
|
|
17
|
+
export const Sha512Hex = lowercaseHex("sha512", 128)
|
|
18
|
+
export type Sha512Hex = typeof Sha512Hex.Type
|
|
19
|
+
|
|
20
|
+
export class Sha1Digest
|
|
21
|
+
extends Schema.TaggedClass<Sha1Digest>()("Sha1Digest", {
|
|
22
|
+
algorithm: Schema.Literal("sha1"),
|
|
23
|
+
hex: Sha1Hex
|
|
24
|
+
}) {}
|
|
25
|
+
|
|
26
|
+
export class Sha256Digest
|
|
27
|
+
extends Schema.TaggedClass<Sha256Digest>()("Sha256Digest", {
|
|
28
|
+
algorithm: Schema.Literal("sha256"),
|
|
29
|
+
hex: Sha256Hex
|
|
30
|
+
}) {}
|
|
31
|
+
|
|
32
|
+
export class Sha512Digest
|
|
33
|
+
extends Schema.TaggedClass<Sha512Digest>()("Sha512Digest", {
|
|
34
|
+
algorithm: Schema.Literal("sha512"),
|
|
35
|
+
hex: Sha512Hex
|
|
36
|
+
}) {}
|
|
37
|
+
|
|
38
|
+
export const AlgorithmDigest = Schema.Union([
|
|
39
|
+
Sha1Digest,
|
|
40
|
+
Sha256Digest,
|
|
41
|
+
Sha512Digest
|
|
42
|
+
])
|
|
43
|
+
export type AlgorithmDigest = typeof AlgorithmDigest.Type
|
|
44
|
+
|
|
45
|
+
export const DigestEncoding = Schema.Literals([
|
|
46
|
+
"sha1-hex",
|
|
47
|
+
"sha256-hex",
|
|
48
|
+
"sha512-hex",
|
|
49
|
+
"github-sha256",
|
|
50
|
+
"npm-sha512-sri",
|
|
51
|
+
"npm-sha1-shasum"
|
|
52
|
+
])
|
|
53
|
+
export type DigestEncoding = typeof DigestEncoding.Type
|
|
54
|
+
|
|
55
|
+
export class DigestCodecError
|
|
56
|
+
extends Schema.TaggedErrorClass<DigestCodecError>()("DigestCodecError", {
|
|
57
|
+
encoding: DigestEncoding,
|
|
58
|
+
reason: Schema.NonEmptyString
|
|
59
|
+
}) {}
|
|
60
|
+
|
|
61
|
+
const decodeHex = (
|
|
62
|
+
value: unknown,
|
|
63
|
+
encoding: "sha1-hex" | "sha256-hex" | "sha512-hex",
|
|
64
|
+
length: 40 | 64 | 128
|
|
65
|
+
): string => {
|
|
66
|
+
if (typeof value !== "string" ||
|
|
67
|
+
!new RegExp(`^[a-f0-9]{${length}}$`, "u").test(value)) {
|
|
68
|
+
throw new DigestCodecError({
|
|
69
|
+
encoding,
|
|
70
|
+
reason: `Value is not a canonical ${encoding} digest encoding.`
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
return value
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const parseSha1Hex = (value: unknown): Sha1Digest => Sha1Digest.make({
|
|
77
|
+
algorithm: "sha1",
|
|
78
|
+
hex: Sha1Hex.make(decodeHex(value, "sha1-hex", 40))
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
export const parseSha256Hex = (value: unknown): Sha256Digest => Sha256Digest.make({
|
|
82
|
+
algorithm: "sha256",
|
|
83
|
+
hex: Sha256Hex.make(decodeHex(value, "sha256-hex", 64))
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
export const parseSha512Hex = (value: unknown): Sha512Digest => Sha512Digest.make({
|
|
87
|
+
algorithm: "sha512",
|
|
88
|
+
hex: Sha512Hex.make(decodeHex(value, "sha512-hex", 128))
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
export const formatSha1Hex = (digest: Sha1Digest): Sha1Hex => digest.hex
|
|
92
|
+
export const formatSha256Hex = (digest: Sha256Digest): Sha256Hex => digest.hex
|
|
93
|
+
export const formatSha512Hex = (digest: Sha512Digest): Sha512Hex => digest.hex
|
|
94
|
+
|
|
95
|
+
export const parseGitHubSha256 = (value: unknown): Sha256Digest => {
|
|
96
|
+
if (typeof value !== "string" || !value.startsWith("sha256:")) {
|
|
97
|
+
throw new DigestCodecError({
|
|
98
|
+
encoding: "github-sha256",
|
|
99
|
+
reason: "GitHub SHA-256 must use the canonical sha256:<lowercase-hex> encoding."
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return parseSha256Hex(value.slice("sha256:".length))
|
|
104
|
+
} catch {
|
|
105
|
+
throw new DigestCodecError({
|
|
106
|
+
encoding: "github-sha256",
|
|
107
|
+
reason: "GitHub SHA-256 must use the canonical sha256:<lowercase-hex> encoding."
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const formatGitHubSha256 = (digest: Sha256Digest): string =>
|
|
113
|
+
`sha256:${formatSha256Hex(digest)}`
|
|
114
|
+
|
|
115
|
+
export const parseNpmSha512Sri = (value: unknown): Sha512Digest => {
|
|
116
|
+
if (typeof value !== "string" || !value.startsWith("sha512-")) {
|
|
117
|
+
throw new DigestCodecError({
|
|
118
|
+
encoding: "npm-sha512-sri",
|
|
119
|
+
reason: "npm SHA-512 integrity must use the canonical sha512-<base64> SRI encoding."
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
const encoded = value.slice("sha512-".length)
|
|
123
|
+
if (!/^[A-Za-z0-9+/]{86}==$/u.test(encoded)) {
|
|
124
|
+
throw new DigestCodecError({
|
|
125
|
+
encoding: "npm-sha512-sri",
|
|
126
|
+
reason: "npm SHA-512 integrity contains malformed or noncanonical base64."
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
const bytes = Buffer.from(encoded, "base64")
|
|
130
|
+
if (bytes.length !== 64 || bytes.toString("base64") !== encoded) {
|
|
131
|
+
throw new DigestCodecError({
|
|
132
|
+
encoding: "npm-sha512-sri",
|
|
133
|
+
reason: "npm SHA-512 integrity contains malformed or noncanonical base64."
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
return parseSha512Hex(bytes.toString("hex"))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const formatNpmSha512Sri = (digest: Sha512Digest): string =>
|
|
140
|
+
`sha512-${Buffer.from(formatSha512Hex(digest), "hex").toString("base64")}`
|
|
141
|
+
|
|
142
|
+
export const parseNpmSha1Shasum = (value: unknown): Sha1Digest => {
|
|
143
|
+
try {
|
|
144
|
+
const parsed = parseSha1Hex(value)
|
|
145
|
+
return Sha1Digest.make({ algorithm: "sha1", hex: parsed.hex })
|
|
146
|
+
} catch {
|
|
147
|
+
throw new DigestCodecError({
|
|
148
|
+
encoding: "npm-sha1-shasum",
|
|
149
|
+
reason: "npm shasum must be exactly 40 lowercase hexadecimal SHA-1 characters."
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const formatNpmSha1Shasum = (digest: Sha1Digest): string =>
|
|
155
|
+
formatSha1Hex(digest)
|
|
156
|
+
|
|
157
|
+
const hashHex = (algorithm: "sha1" | "sha256" | "sha512", bytes: Uint8Array): string =>
|
|
158
|
+
createHash(algorithm).update(bytes).digest("hex")
|
|
159
|
+
|
|
160
|
+
export const sha1Digest = (bytes: Uint8Array): Sha1Digest =>
|
|
161
|
+
parseSha1Hex(hashHex("sha1", bytes))
|
|
162
|
+
|
|
163
|
+
export const sha256Digest = (bytes: Uint8Array): Sha256Digest =>
|
|
164
|
+
parseSha256Hex(hashHex("sha256", bytes))
|
|
165
|
+
|
|
166
|
+
export const sha512Digest = (bytes: Uint8Array): Sha512Digest =>
|
|
167
|
+
parseSha512Hex(hashHex("sha512", bytes))
|
|
168
|
+
|
|
169
|
+
export const digestEquals = (
|
|
170
|
+
left: AlgorithmDigest,
|
|
171
|
+
right: AlgorithmDigest
|
|
172
|
+
): boolean => left.algorithm === right.algorithm && left.hex === right.hex
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
|
|
3
|
+
const reason = { reason: Schema.String }
|
|
4
|
+
export const MISSING_COMMIT = "source.commit is required and could not be observed from the repository."
|
|
5
|
+
export class ConfigValueError extends Schema.TaggedErrorClass<ConfigValueError>()("ConfigValueError", reason) {}
|
|
6
|
+
export class ConfigDecodeError extends Schema.TaggedErrorClass<ConfigDecodeError>()("ConfigDecodeError", reason) {}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
|
|
3
|
+
const identifier = <const Name extends string>(name: Name) =>
|
|
4
|
+
Schema.NonEmptyString.pipe(Schema.brand(name))
|
|
5
|
+
|
|
6
|
+
export const OperationId = identifier("OperationId"); export type OperationId = typeof OperationId.Type
|
|
7
|
+
export const OutputId = identifier("OutputId"); export type OutputId = typeof OutputId.Type
|
|
8
|
+
export const Digest = identifier("Digest"); export type Digest = typeof Digest.Type
|
|
9
|
+
export const NonEmptyName = identifier("NonEmptyName"); export type NonEmptyName = typeof NonEmptyName.Type
|
|
10
|
+
export const Version = identifier("Version"); export type Version = typeof Version.Type
|
|
11
|
+
|
|
12
|
+
export const isSafeRelativePath = (value: string): boolean =>
|
|
13
|
+
value.trim().length > 0 &&
|
|
14
|
+
!value.startsWith("/") &&
|
|
15
|
+
!value.startsWith("\\") &&
|
|
16
|
+
!/^[A-Za-z]:[\\/]/u.test(value) &&
|
|
17
|
+
!value.split(/[\\/]+/u).includes("..")
|
|
18
|
+
|
|
19
|
+
export const SafeRelativePath = Schema.String.check(
|
|
20
|
+
Schema.makeFilter((value: string) =>
|
|
21
|
+
isSafeRelativePath(value)
|
|
22
|
+
? undefined
|
|
23
|
+
: "Path must be nonempty, relative, and contain no parent traversal.")
|
|
24
|
+
).pipe(Schema.brand("SafeRelativePath"))
|
|
25
|
+
export type SafeRelativePath = typeof SafeRelativePath.Type
|
|
26
|
+
|
|
27
|
+
export const SafeArchivePattern = Schema.String.check(
|
|
28
|
+
Schema.makeFilter((value: string) =>
|
|
29
|
+
isSafeRelativePath(value) ? undefined : "Archive pattern must be relative and contain no parent traversal.")
|
|
30
|
+
).pipe(Schema.brand("SafeArchivePattern"))
|
|
31
|
+
export type SafeArchivePattern = typeof SafeArchivePattern.Type
|
|
32
|
+
|
|
33
|
+
export const WorkspaceRoot = Schema.String.check(
|
|
34
|
+
Schema.makeFilter((value: string) =>
|
|
35
|
+
value.startsWith("/") ? undefined : "WorkspaceRoot must be absolute.")
|
|
36
|
+
).pipe(Schema.brand("WorkspaceRoot"))
|
|
37
|
+
export type WorkspaceRoot = typeof WorkspaceRoot.Type
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
|
|
3
|
+
export const PyPiRepository = Schema.Literals(["pypi", "testpypi"])
|
|
4
|
+
export type PyPiRepository = typeof PyPiRepository.Type
|
|
5
|
+
|
|
6
|
+
export const normalizePyPiProjectName = (value: string): string => {
|
|
7
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/u.test(value)) {
|
|
8
|
+
throw new Error("PyPI project names may contain only ASCII letters, digits, period, underscore, and hyphen.")
|
|
9
|
+
}
|
|
10
|
+
return value.toLowerCase().replace(/[-_.]+/gu, "-")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const PyPiProjectName = Schema.NonEmptyString.check(Schema.makeFilter((value: string) => {
|
|
14
|
+
try {
|
|
15
|
+
return normalizePyPiProjectName(value) === value ? undefined : "PyPI project name must be normalized."
|
|
16
|
+
} catch (cause) {
|
|
17
|
+
return cause instanceof Error ? cause.message : String(cause)
|
|
18
|
+
}
|
|
19
|
+
})).pipe(Schema.brand("PyPiProjectName"))
|
|
20
|
+
export type PyPiProjectName = typeof PyPiProjectName.Type
|
|
21
|
+
|
|
22
|
+
export interface PyPiRepositoryEndpoints {
|
|
23
|
+
readonly simpleBaseUrl: string
|
|
24
|
+
readonly uploadUrl: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const pypiRepositoryEndpoints = (repository: PyPiRepository): PyPiRepositoryEndpoints =>
|
|
28
|
+
repository === "pypi"
|
|
29
|
+
? { simpleBaseUrl: "https://pypi.org/simple/", uploadUrl: "https://upload.pypi.org/legacy/" }
|
|
30
|
+
: { simpleBaseUrl: "https://test.pypi.org/simple/", uploadUrl: "https://test.pypi.org/legacy/" }
|