@pithy-sh/core 0.1.2 → 0.1.3
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/dist/address/address.d.ts +57 -0
- package/dist/address/address.d.ts.map +1 -0
- package/dist/address/address.js +71 -0
- package/dist/audit/auditEvent.d.ts +89 -0
- package/dist/audit/auditEvent.d.ts.map +1 -0
- package/dist/audit/auditEvent.js +69 -0
- package/dist/audit/recorder.d.ts +18 -0
- package/dist/audit/recorder.d.ts.map +1 -0
- package/dist/audit/recorder.js +8 -0
- package/dist/capability/bindings.d.ts +62 -0
- package/dist/capability/bindings.d.ts.map +1 -0
- package/dist/capability/bindings.js +97 -0
- package/dist/capability/capability.d.ts +501 -0
- package/dist/capability/capability.d.ts.map +1 -0
- package/dist/capability/capability.js +16 -0
- package/dist/capability/client.d.ts +70 -0
- package/dist/capability/client.d.ts.map +1 -0
- package/dist/capability/client.js +86 -0
- package/dist/capability/compose.d.ts +25 -0
- package/dist/capability/compose.d.ts.map +1 -0
- package/dist/capability/compose.js +54 -0
- package/dist/capability/composition.d.ts +26 -0
- package/dist/capability/composition.d.ts.map +1 -0
- package/dist/capability/composition.js +84 -0
- package/dist/capability/config.d.ts +7 -0
- package/dist/capability/config.d.ts.map +1 -0
- package/dist/capability/config.js +14 -0
- package/dist/capability/devSecret.d.ts +32 -0
- package/dist/capability/devSecret.d.ts.map +1 -0
- package/dist/capability/devSecret.js +28 -0
- package/dist/capability/manifest.d.ts +298 -0
- package/dist/capability/manifest.d.ts.map +1 -0
- package/dist/capability/manifest.js +356 -0
- package/dist/capability/secretOrigin.d.ts +121 -0
- package/dist/capability/secretOrigin.d.ts.map +1 -0
- package/dist/capability/secretOrigin.js +134 -0
- package/dist/capability/settings.d.ts +119 -0
- package/dist/capability/settings.d.ts.map +1 -0
- package/dist/capability/settings.js +66 -0
- package/dist/capability/validateBindings.d.ts +4 -0
- package/dist/capability/validateBindings.d.ts.map +1 -0
- package/dist/capability/validateBindings.js +34 -0
- package/dist/capability/vanishingKey.d.ts +31 -0
- package/dist/capability/vanishingKey.d.ts.map +1 -0
- package/dist/capability/vanishingKey.js +79 -0
- package/dist/controlPlane/audit/actions.d.ts +70 -0
- package/dist/controlPlane/audit/actions.d.ts.map +1 -0
- package/dist/controlPlane/audit/actions.js +76 -0
- package/dist/controlPlane/capability.d.ts +47 -0
- package/dist/controlPlane/capability.d.ts.map +1 -0
- package/dist/controlPlane/capability.js +138 -0
- package/dist/controlPlane/config/config.d.ts +19 -0
- package/dist/controlPlane/config/config.d.ts.map +1 -0
- package/dist/controlPlane/config/config.js +85 -0
- package/dist/controlPlane/context.d.ts +27 -0
- package/dist/controlPlane/context.d.ts.map +1 -0
- package/dist/controlPlane/context.js +29 -0
- package/dist/controlPlane/data/connection.d.ts +79 -0
- package/dist/controlPlane/data/connection.d.ts.map +1 -0
- package/dist/controlPlane/data/connection.js +55 -0
- package/dist/controlPlane/data/keyLifecycle.d.ts +62 -0
- package/dist/controlPlane/data/keyLifecycle.d.ts.map +1 -0
- package/dist/controlPlane/data/keyLifecycle.js +126 -0
- package/dist/controlPlane/data/replay.d.ts +18 -0
- package/dist/controlPlane/data/replay.d.ts.map +1 -0
- package/dist/controlPlane/data/replay.js +20 -0
- package/dist/controlPlane/data/tables.d.ts +34 -0
- package/dist/controlPlane/data/tables.d.ts.map +1 -0
- package/dist/controlPlane/data/tables.js +37 -0
- package/dist/controlPlane/discovery/adminRoute.d.ts +313 -0
- package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -0
- package/dist/controlPlane/discovery/adminRoute.js +136 -0
- package/dist/controlPlane/discovery/configuration.d.ts +108 -0
- package/dist/controlPlane/discovery/configuration.d.ts.map +1 -0
- package/dist/controlPlane/discovery/configuration.js +187 -0
- package/dist/controlPlane/discovery/drift.d.ts +64 -0
- package/dist/controlPlane/discovery/drift.d.ts.map +1 -0
- package/dist/controlPlane/discovery/drift.js +58 -0
- package/dist/controlPlane/discovery/health.d.ts +99 -0
- package/dist/controlPlane/discovery/health.d.ts.map +1 -0
- package/dist/controlPlane/discovery/health.js +151 -0
- package/dist/controlPlane/discovery/healthSummary.d.ts +236 -0
- package/dist/controlPlane/discovery/healthSummary.d.ts.map +1 -0
- package/dist/controlPlane/discovery/healthSummary.js +278 -0
- package/dist/controlPlane/error/errors.d.ts +67 -0
- package/dist/controlPlane/error/errors.d.ts.map +1 -0
- package/dist/controlPlane/error/errors.js +79 -0
- package/dist/controlPlane/http/cors.d.ts +112 -0
- package/dist/controlPlane/http/cors.d.ts.map +1 -0
- package/dist/controlPlane/http/cors.js +192 -0
- package/dist/controlPlane/http/guard.d.ts +77 -0
- package/dist/controlPlane/http/guard.d.ts.map +1 -0
- package/dist/controlPlane/http/guard.js +142 -0
- package/dist/controlPlane/http/handlers.d.ts +179 -0
- package/dist/controlPlane/http/handlers.d.ts.map +1 -0
- package/dist/controlPlane/http/handlers.js +245 -0
- package/dist/controlPlane/http/responses.d.ts +99 -0
- package/dist/controlPlane/http/responses.d.ts.map +1 -0
- package/dist/controlPlane/http/responses.js +63 -0
- package/dist/controlPlane/http/routes.d.ts +40 -0
- package/dist/controlPlane/http/routes.d.ts.map +1 -0
- package/dist/controlPlane/http/routes.js +83 -0
- package/dist/controlPlane/http/schemas.d.ts +39 -0
- package/dist/controlPlane/http/schemas.d.ts.map +1 -0
- package/dist/controlPlane/http/schemas.js +31 -0
- package/dist/controlPlane/http/verify.d.ts +84 -0
- package/dist/controlPlane/http/verify.d.ts.map +1 -0
- package/dist/controlPlane/http/verify.js +65 -0
- package/dist/controlPlane/migrations/0001_init.d.ts +51 -0
- package/dist/controlPlane/migrations/0001_init.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0001_init.js +65 -0
- package/dist/controlPlane/replay/d1Guard.d.ts +29 -0
- package/dist/controlPlane/replay/d1Guard.d.ts.map +1 -0
- package/dist/controlPlane/replay/d1Guard.js +39 -0
- package/dist/controlPlane/replay/guard.d.ts +52 -0
- package/dist/controlPlane/replay/guard.d.ts.map +1 -0
- package/dist/controlPlane/replay/guard.js +0 -0
- package/dist/controlPlane/replay/kvGuard.d.ts +99 -0
- package/dist/controlPlane/replay/kvGuard.d.ts.map +1 -0
- package/dist/controlPlane/replay/kvGuard.js +101 -0
- package/dist/controlPlane/scope/scope.d.ts +68 -0
- package/dist/controlPlane/scope/scope.d.ts.map +1 -0
- package/dist/controlPlane/scope/scope.js +63 -0
- package/dist/controlPlane/token/base64url.d.ts +10 -0
- package/dist/controlPlane/token/base64url.d.ts.map +1 -0
- package/dist/controlPlane/token/base64url.js +48 -0
- package/dist/controlPlane/token/claims.d.ts +83 -0
- package/dist/controlPlane/token/claims.d.ts.map +1 -0
- package/dist/controlPlane/token/claims.js +86 -0
- package/dist/controlPlane/token/digest.d.ts +44 -0
- package/dist/controlPlane/token/digest.d.ts.map +1 -0
- package/dist/controlPlane/token/digest.js +56 -0
- package/dist/controlPlane/token/jws.d.ts +52 -0
- package/dist/controlPlane/token/jws.d.ts.map +1 -0
- package/dist/controlPlane/token/jws.js +65 -0
- package/dist/controlPlane/token/mint.d.ts +56 -0
- package/dist/controlPlane/token/mint.d.ts.map +1 -0
- package/dist/controlPlane/token/mint.js +55 -0
- package/dist/controlPlane/wire.d.ts +122 -0
- package/dist/controlPlane/wire.d.ts.map +1 -0
- package/dist/controlPlane/wire.js +123 -0
- package/dist/createBackend.d.ts +58 -0
- package/dist/createBackend.d.ts.map +1 -0
- package/dist/createBackend.js +170 -0
- package/dist/createEntrypoint.d.ts +53 -0
- package/dist/createEntrypoint.d.ts.map +1 -0
- package/dist/createEntrypoint.js +52 -0
- package/dist/data/boundParameters.d.ts +83 -0
- package/dist/data/boundParameters.d.ts.map +1 -0
- package/dist/data/boundParameters.js +162 -0
- package/dist/data/codecs.d.ts +34 -0
- package/dist/data/codecs.d.ts.map +1 -0
- package/dist/data/codecs.js +135 -0
- package/dist/data/cursor.d.ts +81 -0
- package/dist/data/cursor.d.ts.map +1 -0
- package/dist/data/cursor.js +104 -0
- package/dist/data/databases.d.ts +55 -0
- package/dist/data/databases.d.ts.map +1 -0
- package/dist/data/databases.js +32 -0
- package/dist/data/db.d.ts +42 -0
- package/dist/data/db.d.ts.map +1 -0
- package/dist/data/db.js +24 -0
- package/dist/data/withD1Retry.d.ts +91 -0
- package/dist/data/withD1Retry.d.ts.map +1 -0
- package/dist/data/withD1Retry.js +152 -0
- package/dist/entitlement/entitlement.d.ts +118 -0
- package/dist/entitlement/entitlement.d.ts.map +1 -0
- package/dist/entitlement/entitlement.js +59 -0
- package/dist/entitlement/gateScan.d.ts +26 -0
- package/dist/entitlement/gateScan.d.ts.map +1 -0
- package/dist/entitlement/gateScan.js +96 -0
- package/dist/entitlement/require.d.ts +12 -0
- package/dist/entitlement/require.d.ts.map +1 -0
- package/dist/entitlement/require.js +123 -0
- package/dist/env/ambient.d.ts +52 -0
- package/dist/env/ambient.d.ts.map +1 -0
- package/dist/env/ambient.js +35 -0
- package/dist/env/ci.d.ts +36 -0
- package/dist/env/ci.d.ts.map +1 -0
- package/dist/env/ci.js +40 -0
- package/dist/env/stem.d.ts +23 -0
- package/dist/env/stem.d.ts.map +1 -0
- package/dist/env/stem.js +29 -0
- package/dist/error/cause.d.ts +143 -0
- package/dist/error/cause.d.ts.map +1 -0
- package/dist/error/cause.js +192 -0
- package/dist/error/client.d.ts +35 -0
- package/dist/error/client.d.ts.map +1 -0
- package/dist/error/client.js +38 -0
- package/dist/error/extend.d.ts +101 -0
- package/dist/error/extend.d.ts.map +1 -0
- package/dist/error/extend.js +76 -0
- package/dist/error/http.d.ts +1516 -0
- package/dist/error/http.d.ts.map +1 -0
- package/dist/error/http.js +72 -0
- package/dist/error/payload.d.ts +3034 -0
- package/dist/error/payload.d.ts.map +1 -0
- package/dist/error/payload.js +1110 -0
- package/dist/error/pithyError.d.ts +154 -0
- package/dist/error/pithyError.d.ts.map +1 -0
- package/dist/error/pithyError.js +197 -0
- package/dist/error/terminal.d.ts +28 -0
- package/dist/error/terminal.d.ts.map +1 -0
- package/dist/error/terminal.js +33 -0
- package/dist/http/authContext.d.ts +21 -0
- package/dist/http/authContext.d.ts.map +1 -0
- package/dist/http/authContext.js +23 -0
- package/dist/http/routeContract.d.ts +39 -0
- package/dist/http/routeContract.d.ts.map +1 -0
- package/dist/http/routeContract.js +82 -0
- package/dist/http/sameOrigin.d.ts +47 -0
- package/dist/http/sameOrigin.d.ts.map +1 -0
- package/dist/http/sameOrigin.js +24 -0
- package/dist/http/signedWebhook.d.ts +225 -0
- package/dist/http/signedWebhook.d.ts.map +1 -0
- package/dist/http/signedWebhook.js +247 -0
- package/dist/http/validation.d.ts +37 -0
- package/dist/http/validation.d.ts.map +1 -0
- package/dist/http/validation.js +14 -0
- package/dist/http/verification.d.ts +10 -0
- package/dist/http/verification.d.ts.map +1 -0
- package/dist/http/verification.js +17 -0
- package/dist/i18n/acceptLanguage.d.ts +22 -0
- package/dist/i18n/acceptLanguage.d.ts.map +1 -0
- package/dist/i18n/acceptLanguage.js +55 -0
- package/dist/i18n/catalog.d.ts +39 -0
- package/dist/i18n/catalog.d.ts.map +1 -0
- package/dist/i18n/catalog.js +57 -0
- package/dist/i18n/locale.d.ts +74 -0
- package/dist/i18n/locale.d.ts.map +1 -0
- package/dist/i18n/locale.js +109 -0
- package/dist/i18n/localeMarker.d.ts +29 -0
- package/dist/i18n/localeMarker.d.ts.map +1 -0
- package/dist/i18n/localeMarker.js +112 -0
- package/dist/i18n/match.d.ts +26 -0
- package/dist/i18n/match.d.ts.map +1 -0
- package/dist/i18n/match.js +88 -0
- package/dist/i18n/registry.d.ts +25 -0
- package/dist/i18n/registry.d.ts.map +1 -0
- package/dist/i18n/registry.js +51 -0
- package/dist/i18n/translator.d.ts +107 -0
- package/dist/i18n/translator.d.ts.map +1 -0
- package/dist/i18n/translator.js +80 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/kv/kv.d.ts +166 -0
- package/dist/kv/kv.d.ts.map +1 -0
- package/dist/kv/kv.js +261 -0
- package/dist/kv/namespaces.d.ts +58 -0
- package/dist/kv/namespaces.d.ts.map +1 -0
- package/dist/kv/namespaces.js +40 -0
- package/dist/logger/local.d.ts +41 -0
- package/dist/logger/local.d.ts.map +1 -0
- package/dist/logger/local.js +45 -0
- package/dist/logger/logger.d.ts +56 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +83 -0
- package/dist/logger/record.d.ts +919 -0
- package/dist/logger/record.d.ts.map +1 -0
- package/dist/logger/record.js +79 -0
- package/dist/logger/worker.d.ts +74 -0
- package/dist/logger/worker.d.ts.map +1 -0
- package/dist/logger/worker.js +54 -0
- package/dist/migrations/batch.d.ts +10 -0
- package/dist/migrations/batch.d.ts.map +1 -0
- package/dist/migrations/batch.js +193 -0
- package/dist/migrations/bookkeeping.d.ts +24 -0
- package/dist/migrations/bookkeeping.d.ts.map +1 -0
- package/dist/migrations/bookkeeping.js +57 -0
- package/dist/migrations/owner.d.ts +41 -0
- package/dist/migrations/owner.d.ts.map +1 -0
- package/dist/migrations/owner.js +105 -0
- package/dist/migrations/registry.d.ts +36 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +70 -0
- package/dist/migrations/runner.d.ts +67 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +218 -0
- package/dist/naming/domains.d.ts +108 -0
- package/dist/naming/domains.d.ts.map +1 -0
- package/dist/naming/domains.js +156 -0
- package/dist/naming/environment.d.ts +118 -0
- package/dist/naming/environment.d.ts.map +1 -0
- package/dist/naming/environment.js +190 -0
- package/dist/naming/feature.d.ts +68 -0
- package/dist/naming/feature.d.ts.map +1 -0
- package/dist/naming/feature.js +106 -0
- package/dist/naming/limits.d.ts +229 -0
- package/dist/naming/limits.d.ts.map +1 -0
- package/dist/naming/limits.js +187 -0
- package/dist/naming/provisionScope.d.ts +91 -0
- package/dist/naming/provisionScope.d.ts.map +1 -0
- package/dist/naming/provisionScope.js +65 -0
- package/dist/naming/resource.d.ts +169 -0
- package/dist/naming/resource.d.ts.map +1 -0
- package/dist/naming/resource.js +220 -0
- package/dist/naming/resourceNames.d.ts +83 -0
- package/dist/naming/resourceNames.d.ts.map +1 -0
- package/dist/naming/resourceNames.js +102 -0
- package/dist/naming/segment.d.ts +29 -0
- package/dist/naming/segment.d.ts.map +1 -0
- package/dist/naming/segment.js +31 -0
- package/dist/projection/asRead.d.ts +72 -0
- package/dist/projection/asRead.d.ts.map +1 -0
- package/dist/projection/asRead.js +169 -0
- package/dist/projection/published.d.ts +95 -0
- package/dist/projection/published.d.ts.map +1 -0
- package/dist/projection/published.js +114 -0
- package/dist/schema/describedness.d.ts +55 -0
- package/dist/schema/describedness.d.ts.map +1 -0
- package/dist/schema/describedness.js +180 -0
- package/dist/seed/compose.d.ts +41 -0
- package/dist/seed/compose.d.ts.map +1 -0
- package/dist/seed/compose.js +51 -0
- package/dist/seed/devLogin.d.ts +50 -0
- package/dist/seed/devLogin.d.ts.map +1 -0
- package/dist/seed/devLogin.js +52 -0
- package/dist/seed/exampleIdentities.d.ts +58 -0
- package/dist/seed/exampleIdentities.d.ts.map +1 -0
- package/dist/seed/exampleIdentities.js +26 -0
- package/dist/seed/metadata.d.ts +20 -0
- package/dist/seed/metadata.d.ts.map +1 -0
- package/dist/seed/metadata.js +27 -0
- package/dist/seed/seed.d.ts +264 -0
- package/dist/seed/seed.d.ts.map +1 -0
- package/dist/seed/seed.js +37 -0
- package/dist/seed/seededRows.d.ts +26 -0
- package/dist/seed/seededRows.d.ts.map +1 -0
- package/dist/seed/seededRows.js +20 -0
- package/dist/seed/writeD1.d.ts +43 -0
- package/dist/seed/writeD1.d.ts.map +1 -0
- package/dist/seed/writeD1.js +73 -0
- package/dist/seed/writeKv.d.ts +29 -0
- package/dist/seed/writeKv.d.ts.map +1 -0
- package/dist/seed/writeKv.js +63 -0
- package/dist/semver/semver.d.ts +62 -0
- package/dist/semver/semver.d.ts.map +1 -0
- package/dist/semver/semver.js +137 -0
- package/dist/text/comments.d.ts +62 -0
- package/dist/text/comments.d.ts.map +1 -0
- package/dist/text/comments.js +161 -0
- package/dist/version.generated.d.ts +5 -0
- package/dist/version.generated.d.ts.map +1 -0
- package/dist/version.generated.js +7 -0
- package/dist/worker/health.d.ts +39 -0
- package/dist/worker/health.d.ts.map +1 -0
- package/dist/worker/health.js +41 -0
- package/dist/worker/identity.d.ts +191 -0
- package/dist/worker/identity.d.ts.map +1 -0
- package/dist/worker/identity.js +162 -0
- package/dist/workflow/bindings.d.ts +41 -0
- package/dist/workflow/bindings.d.ts.map +1 -0
- package/dist/workflow/bindings.js +53 -0
- package/dist/workflow/dispatch.d.ts +98 -0
- package/dist/workflow/dispatch.d.ts.map +1 -0
- package/dist/workflow/dispatch.js +148 -0
- package/dist/workflow/dispatchRoute.d.ts +80 -0
- package/dist/workflow/dispatchRoute.d.ts.map +1 -0
- package/dist/workflow/dispatchRoute.js +134 -0
- package/dist/workflow/faults.d.ts +97 -0
- package/dist/workflow/faults.d.ts.map +1 -0
- package/dist/workflow/faults.js +111 -0
- package/dist/workflow/host.d.ts +176 -0
- package/dist/workflow/host.d.ts.map +1 -0
- package/dist/workflow/host.js +116 -0
- package/dist/workflow/hostEntry.d.ts +50 -0
- package/dist/workflow/hostEntry.d.ts.map +1 -0
- package/dist/workflow/hostEntry.js +24 -0
- package/dist/workflow/hostEnv.d.ts +143 -0
- package/dist/workflow/hostEnv.d.ts.map +1 -0
- package/dist/workflow/hostEnv.js +170 -0
- package/dist/workflow/loopback.d.ts +52 -0
- package/dist/workflow/loopback.d.ts.map +1 -0
- package/dist/workflow/loopback.js +76 -0
- package/dist/workflow/naming.d.ts +79 -0
- package/dist/workflow/naming.d.ts.map +1 -0
- package/dist/workflow/naming.js +138 -0
- package/dist/workflow/register.d.ts +19 -0
- package/dist/workflow/register.d.ts.map +1 -0
- package/dist/workflow/register.js +40 -0
- package/dist/workflow/schemas.d.ts +44 -0
- package/dist/workflow/schemas.d.ts.map +1 -0
- package/dist/workflow/schemas.js +43 -0
- package/dist/workflow/spec.d.ts +81 -0
- package/dist/workflow/spec.d.ts.map +1 -0
- package/dist/workflow/spec.js +0 -0
- package/dist/workflow/stepMessage.d.ts +122 -0
- package/dist/workflow/stepMessage.d.ts.map +1 -0
- package/dist/workflow/stepMessage.js +152 -0
- package/package.json +20 -9
- package/src/capability/manifest.ts +21 -0
- package/src/version.generated.ts +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { type WorkflowHostNameParts } from "./naming";
|
|
2
|
+
import type { WorkflowRegistry } from "./spec";
|
|
3
|
+
/**
|
|
4
|
+
* The prebuilt-worker host contract.
|
|
5
|
+
*
|
|
6
|
+
* A capability that owns Workflows ships a committed `wrangler.jsonc` **template** beside its
|
|
7
|
+
* worker entry — not an env-stanza file, because staging and production are genuinely separate
|
|
8
|
+
* Workers. `pithy <capability> provision` resolves that template into one complete config per
|
|
9
|
+
* environment and deploys each with `wrangler deploy --config <resolved>`. The adopter authors
|
|
10
|
+
* none of it.
|
|
11
|
+
*
|
|
12
|
+
* Email, secrets, and media each grew their own copy of that resolver. This module is the one they
|
|
13
|
+
* converge on: a template shape wide enough for all three, and a pure resolver that fills it.
|
|
14
|
+
*
|
|
15
|
+
* Pure by construction — no filesystem, no Cloudflare, no `cloudflare:workers`. The caller parses
|
|
16
|
+
* the template and writes the result. That keeps core node-safe (its `.describe()` meta-test
|
|
17
|
+
* imports every module eagerly under node) and keeps the ordering and idempotency logic unit-
|
|
18
|
+
* testable without an account.
|
|
19
|
+
*
|
|
20
|
+
* **Workflows cannot use remote bindings**, so a host always runs locally in `wrangler dev`. Any
|
|
21
|
+
* binding it needs that has no local emulation — Vectorize and Workers AI both lack one — must
|
|
22
|
+
* carry `remote: true`, which is why {@link WorkflowHostParams.remoteBindings} exists rather than
|
|
23
|
+
* the flag being inferred per binding kind.
|
|
24
|
+
*/
|
|
25
|
+
/** A D1 binding in a host template. `database_name` is rewritten only when the caller supplies one. */
|
|
26
|
+
export interface HostD1Binding {
|
|
27
|
+
binding: string;
|
|
28
|
+
database_name: string;
|
|
29
|
+
database_id: string;
|
|
30
|
+
}
|
|
31
|
+
/** A KV namespace binding in a host template. */
|
|
32
|
+
export interface HostKvBinding {
|
|
33
|
+
binding: string;
|
|
34
|
+
id: string;
|
|
35
|
+
}
|
|
36
|
+
/** An R2 bucket binding in a host template. */
|
|
37
|
+
export interface HostR2Binding {
|
|
38
|
+
binding: string;
|
|
39
|
+
bucket_name: string;
|
|
40
|
+
remote?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** A Vectorize index binding in a host template. Always `remote: true` — Vectorize has no local emulation. */
|
|
43
|
+
export interface HostVectorizeBinding {
|
|
44
|
+
binding: string;
|
|
45
|
+
index_name: string;
|
|
46
|
+
remote?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** The Workers AI binding in a host template. Always `remote: true` — Workers AI has no local emulation. */
|
|
49
|
+
export interface HostAiBinding {
|
|
50
|
+
binding: string;
|
|
51
|
+
remote?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** A Cloudflare Email Service send binding in a host template. */
|
|
54
|
+
export interface HostSendEmailBinding {
|
|
55
|
+
name: string;
|
|
56
|
+
remote?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** A Secrets Store entry in a host template — the master key a host reads its secrets through. */
|
|
59
|
+
export interface HostSecretsStoreBinding {
|
|
60
|
+
binding: string;
|
|
61
|
+
store_id: string;
|
|
62
|
+
secret_name: string;
|
|
63
|
+
}
|
|
64
|
+
/** One Workflow the host worker hosts: the binding, the deployed name, and the class that runs it. */
|
|
65
|
+
export interface HostWorkflowBinding {
|
|
66
|
+
binding: string;
|
|
67
|
+
name: string;
|
|
68
|
+
class_name: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A capability's committed `wrangler.jsonc` template, typed. Every field is optional but `name` and
|
|
72
|
+
* `main` — a host that binds no D1 is legal, and email binds no R2. Unknown keys survive
|
|
73
|
+
* `structuredClone` untouched, so a template may carry fields this contract does not model.
|
|
74
|
+
*/
|
|
75
|
+
export interface WorkflowHostTemplate {
|
|
76
|
+
name: string;
|
|
77
|
+
main: string;
|
|
78
|
+
compatibility_date?: string;
|
|
79
|
+
compatibility_flags?: string[];
|
|
80
|
+
workers_dev?: boolean;
|
|
81
|
+
d1_databases?: HostD1Binding[];
|
|
82
|
+
kv_namespaces?: HostKvBinding[];
|
|
83
|
+
r2_buckets?: HostR2Binding[];
|
|
84
|
+
vectorize?: HostVectorizeBinding[];
|
|
85
|
+
ai?: HostAiBinding;
|
|
86
|
+
send_email?: HostSendEmailBinding[];
|
|
87
|
+
secrets_store_secrets?: HostSecretsStoreBinding[];
|
|
88
|
+
workflows?: HostWorkflowBinding[];
|
|
89
|
+
triggers?: {
|
|
90
|
+
crons: string[];
|
|
91
|
+
};
|
|
92
|
+
vars?: Record<string, string>;
|
|
93
|
+
}
|
|
94
|
+
/** What one environment's resolution needs. Everything absent is left exactly as the template had it. */
|
|
95
|
+
export interface WorkflowHostParams {
|
|
96
|
+
/**
|
|
97
|
+
* The project name — the `<project>` segment every derived name leads with. The root
|
|
98
|
+
* `pithy.config.ts` `name`, resolved by `requireProjectName` and **never guessed**: Worker script
|
|
99
|
+
* and Workflow names are account-scoped, so a wrong value here overwrites another project's
|
|
100
|
+
* running Worker rather than colliding with it.
|
|
101
|
+
*/
|
|
102
|
+
project: string;
|
|
103
|
+
/** The capability that owns the host — the `<capability>` segment of every derived name. */
|
|
104
|
+
capability: string;
|
|
105
|
+
/** The target environment (`dev` | `staging` | `production`). */
|
|
106
|
+
env: string;
|
|
107
|
+
/** D1 binding name → database id. An unlisted binding keeps the template's id. */
|
|
108
|
+
databaseIds?: Record<string, string>;
|
|
109
|
+
/**
|
|
110
|
+
* D1 binding name → database name. Rewritten **only** for the bindings listed here. Email
|
|
111
|
+
* deliberately lets `pithy-app`/`pithy-secrets` pass through while secrets rewrites its own, so
|
|
112
|
+
* the choice cannot be a blanket rule.
|
|
113
|
+
*/
|
|
114
|
+
databaseNames?: Record<string, string>;
|
|
115
|
+
/** KV binding name → namespace id. */
|
|
116
|
+
kvNamespaceIds?: Record<string, string>;
|
|
117
|
+
/** R2 binding name → bucket name. */
|
|
118
|
+
r2BucketNames?: Record<string, string>;
|
|
119
|
+
/** Vectorize binding name → index name. */
|
|
120
|
+
vectorizeIndexNames?: Record<string, string>;
|
|
121
|
+
/** The Secrets Store id, set on every `secrets_store_secrets` entry. */
|
|
122
|
+
secretsStoreId?: string;
|
|
123
|
+
/**
|
|
124
|
+
* The environment-scoped name of the master-key secret. Passed in rather than derived: core must
|
|
125
|
+
* not depend on `@pithy-sh/secrets`, which owns that naming.
|
|
126
|
+
*/
|
|
127
|
+
masterKeySecretName?: string;
|
|
128
|
+
/** Vars merged over the template's, e.g. the capability's config serialized as one JSON blob. */
|
|
129
|
+
vars?: Record<string, string>;
|
|
130
|
+
/**
|
|
131
|
+
* Binding names that must carry `remote: true`. A Workflow host runs locally in dev, so any
|
|
132
|
+
* binding without local emulation has to reach the real service.
|
|
133
|
+
*/
|
|
134
|
+
remoteBindings?: readonly string[];
|
|
135
|
+
/**
|
|
136
|
+
* KV binding names to drop. A template declares every binding a capability *might* need; a mode
|
|
137
|
+
* that does not use one must not ship a binding pointing at a namespace that was never created.
|
|
138
|
+
*/
|
|
139
|
+
omitKvBindings?: readonly string[];
|
|
140
|
+
/**
|
|
141
|
+
* The host's `workflows` array, already derived from the capability's registry by
|
|
142
|
+
* {@link hostWorkflowsFor}. **Required whenever the template declares any `workflows`.**
|
|
143
|
+
*
|
|
144
|
+
* The resolver used to build these by appending `-<env>` to the template's own name, which cannot
|
|
145
|
+
* produce a project-scoped name: the template says `pithy-email-send`, and the resolver has no way
|
|
146
|
+
* to recover the job from it. Deriving them from the registry is the only path that knows both the
|
|
147
|
+
* project and the job, so the textual suffix is gone and its absence is an error rather than a
|
|
148
|
+
* silent fallback to an unscoped, account-colliding Workflow name.
|
|
149
|
+
*/
|
|
150
|
+
workflows?: readonly HostWorkflowBinding[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Resolve a host template into one environment's complete, standalone config.
|
|
154
|
+
*
|
|
155
|
+
* Structural, never textual: the template is `structuredClone`d and fields are overwritten by
|
|
156
|
+
* binding-name lookup. The `<filled-at-provision>` markers in the committed templates are
|
|
157
|
+
* documentation for whoever reads the file — nothing matches or replaces them, so a template that
|
|
158
|
+
* spells a placeholder differently still resolves correctly.
|
|
159
|
+
*
|
|
160
|
+
* The worker name becomes `<project>-<env>-<capability>` through {@link workflowHostName}, and the
|
|
161
|
+
* `workflows` array is replaced wholesale by `params.workflows` (derived from the registry by
|
|
162
|
+
* {@link hostWorkflowsFor}), so the deployed names cannot drift from what the dispatcher and the
|
|
163
|
+
* CLI compute. `binding` and
|
|
164
|
+
* `class_name` are never rewritten — they are code references, not deployment identities.
|
|
165
|
+
*/
|
|
166
|
+
export declare function resolveWorkflowHost(template: WorkflowHostTemplate, params: WorkflowHostParams): WorkflowHostTemplate;
|
|
167
|
+
/**
|
|
168
|
+
* Derive a host's `workflows` array and `triggers.crons` from the registry, so a capability's specs
|
|
169
|
+
* — not a hand-maintained block in its template — are the source of both. A spec without a
|
|
170
|
+
* `className` cannot be hosted: there would be no class for wrangler to instantiate.
|
|
171
|
+
*/
|
|
172
|
+
export declare function hostWorkflowsFor(registry: WorkflowRegistry, parts: WorkflowHostNameParts): {
|
|
173
|
+
workflows: HostWorkflowBinding[];
|
|
174
|
+
crons: string[];
|
|
175
|
+
};
|
|
176
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/workflow/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { InternalError } from "../error/pithyError.js";
|
|
2
|
+
import { ENVIRONMENT_VAR, PROJECT_VAR } from "../worker/identity.js";
|
|
3
|
+
import { workflowHostName, workflowScriptName } from "./naming.js";
|
|
4
|
+
//#region src/workflow/host.ts
|
|
5
|
+
/** Apply `remote: true` to an entry whose binding the caller listed. */
|
|
6
|
+
function withRemote(entry, name, remote) {
|
|
7
|
+
return remote.has(name) ? {
|
|
8
|
+
...entry,
|
|
9
|
+
remote: true
|
|
10
|
+
} : entry;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a host template into one environment's complete, standalone config.
|
|
14
|
+
*
|
|
15
|
+
* Structural, never textual: the template is `structuredClone`d and fields are overwritten by
|
|
16
|
+
* binding-name lookup. The `<filled-at-provision>` markers in the committed templates are
|
|
17
|
+
* documentation for whoever reads the file — nothing matches or replaces them, so a template that
|
|
18
|
+
* spells a placeholder differently still resolves correctly.
|
|
19
|
+
*
|
|
20
|
+
* The worker name becomes `<project>-<env>-<capability>` through {@link workflowHostName}, and the
|
|
21
|
+
* `workflows` array is replaced wholesale by `params.workflows` (derived from the registry by
|
|
22
|
+
* {@link hostWorkflowsFor}), so the deployed names cannot drift from what the dispatcher and the
|
|
23
|
+
* CLI compute. `binding` and
|
|
24
|
+
* `class_name` are never rewritten — they are code references, not deployment identities.
|
|
25
|
+
*/
|
|
26
|
+
function resolveWorkflowHost(template, params) {
|
|
27
|
+
const resolved = structuredClone(template);
|
|
28
|
+
const remote = new Set(params.remoteBindings ?? []);
|
|
29
|
+
resolved.name = workflowHostName({
|
|
30
|
+
project: params.project,
|
|
31
|
+
capability: params.capability,
|
|
32
|
+
env: params.env
|
|
33
|
+
});
|
|
34
|
+
if (resolved.d1_databases) resolved.d1_databases = resolved.d1_databases.map((entry) => ({
|
|
35
|
+
...entry,
|
|
36
|
+
database_name: params.databaseNames?.[entry.binding] ?? entry.database_name,
|
|
37
|
+
database_id: params.databaseIds?.[entry.binding] ?? entry.database_id
|
|
38
|
+
}));
|
|
39
|
+
if (resolved.kv_namespaces) {
|
|
40
|
+
const omit = new Set(params.omitKvBindings ?? []);
|
|
41
|
+
const kept = resolved.kv_namespaces.filter((entry) => !omit.has(entry.binding));
|
|
42
|
+
if (kept.length > 0) resolved.kv_namespaces = kept.map((entry) => ({
|
|
43
|
+
...entry,
|
|
44
|
+
id: params.kvNamespaceIds?.[entry.binding] ?? entry.id
|
|
45
|
+
}));
|
|
46
|
+
else resolved.kv_namespaces = void 0;
|
|
47
|
+
}
|
|
48
|
+
if (resolved.r2_buckets) resolved.r2_buckets = resolved.r2_buckets.map((entry) => withRemote({
|
|
49
|
+
...entry,
|
|
50
|
+
bucket_name: params.r2BucketNames?.[entry.binding] ?? entry.bucket_name
|
|
51
|
+
}, entry.binding, remote));
|
|
52
|
+
if (resolved.vectorize) resolved.vectorize = resolved.vectorize.map((entry) => withRemote({
|
|
53
|
+
...entry,
|
|
54
|
+
index_name: params.vectorizeIndexNames?.[entry.binding] ?? entry.index_name
|
|
55
|
+
}, entry.binding, remote));
|
|
56
|
+
if (resolved.ai) resolved.ai = withRemote(resolved.ai, resolved.ai.binding, remote);
|
|
57
|
+
if (resolved.send_email) resolved.send_email = resolved.send_email.map((entry) => withRemote(entry, entry.name, remote));
|
|
58
|
+
if (resolved.secrets_store_secrets && params.secretsStoreId !== void 0) {
|
|
59
|
+
const storeId = params.secretsStoreId;
|
|
60
|
+
const masterKey = params.masterKeySecretName;
|
|
61
|
+
resolved.secrets_store_secrets = resolved.secrets_store_secrets.map((entry) => ({
|
|
62
|
+
...entry,
|
|
63
|
+
store_id: storeId,
|
|
64
|
+
secret_name: masterKey !== void 0 && entry.binding === "SECRETS_ENCRYPTION_KEYS" ? masterKey : entry.secret_name
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
if (resolved.workflows) {
|
|
68
|
+
if (!params.workflows) throw new InternalError({
|
|
69
|
+
message: `The ${params.capability} host template declares workflows but none were derived.`,
|
|
70
|
+
action: "Pass `workflows` from hostWorkflowsFor(registry, { project, capability, env }).",
|
|
71
|
+
detail: "A Workflow name is account-scoped and must carry the project; the template name alone cannot produce one."
|
|
72
|
+
});
|
|
73
|
+
resolved.workflows = params.workflows.map((entry) => ({ ...entry }));
|
|
74
|
+
}
|
|
75
|
+
resolved.vars = {
|
|
76
|
+
...resolved.vars,
|
|
77
|
+
...params.vars,
|
|
78
|
+
[ENVIRONMENT_VAR]: params.env,
|
|
79
|
+
[PROJECT_VAR]: params.project
|
|
80
|
+
};
|
|
81
|
+
return resolved;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Derive a host's `workflows` array and `triggers.crons` from the registry, so a capability's specs
|
|
85
|
+
* — not a hand-maintained block in its template — are the source of both. A spec without a
|
|
86
|
+
* `className` cannot be hosted: there would be no class for wrangler to instantiate.
|
|
87
|
+
*/
|
|
88
|
+
function hostWorkflowsFor(registry, parts) {
|
|
89
|
+
const { project, capability, env } = parts;
|
|
90
|
+
const owned = Object.values(registry).filter((entry) => entry.capability === capability);
|
|
91
|
+
const workflows = [];
|
|
92
|
+
const crons = [];
|
|
93
|
+
for (const entry of owned) {
|
|
94
|
+
if (!entry.spec.className) throw new InternalError({
|
|
95
|
+
message: `Workflow "${entry.key}" cannot be hosted without a className.`,
|
|
96
|
+
action: "Add className to the spec, naming the exported WorkflowEntrypoint class."
|
|
97
|
+
});
|
|
98
|
+
workflows.push({
|
|
99
|
+
binding: entry.spec.binding,
|
|
100
|
+
name: workflowScriptName({
|
|
101
|
+
project,
|
|
102
|
+
capability,
|
|
103
|
+
job: entry.job,
|
|
104
|
+
env
|
|
105
|
+
}),
|
|
106
|
+
class_name: entry.spec.className
|
|
107
|
+
});
|
|
108
|
+
if (entry.spec.schedule) crons.push(entry.spec.schedule);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
workflows,
|
|
112
|
+
crons
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { hostWorkflowsFor, resolveWorkflowHost };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The default export of a Workflow host that serves nothing over HTTP (#426).
|
|
3
|
+
*
|
|
4
|
+
* ## Why a host needs a default export at all
|
|
5
|
+
*
|
|
6
|
+
* wrangler infers a worker's **module format** from one thing: whether the entry has a default export. A
|
|
7
|
+
* module that exports only classes is read as a service worker, and a service worker may not import
|
|
8
|
+
* `cloudflare:workers` — so the build does not warn and continue, it fails:
|
|
9
|
+
*
|
|
10
|
+
* ▲ [WARNING] The entrypoint … has exports like an ES Module, but hasn't defined a default export
|
|
11
|
+
* like a module worker normally would. Building the worker using "service-worker" format...
|
|
12
|
+
* ✘ [ERROR] Unexpected external import of "cloudflare:workers" and "cloudflare:workflows".
|
|
13
|
+
*
|
|
14
|
+
* `pithy dev` builds each worker separately and carries on past one that fails, so the whole of what an
|
|
15
|
+
* adopter sees is a host that is not there. `support`, `media` and `vector` each shipped that way, and every
|
|
16
|
+
* host that did not was a host with a cron — `export default { async scheduled(…) }`, written for the cron,
|
|
17
|
+
* making the module an ES module by accident. The four authors who satisfied the rule had a reason unrelated
|
|
18
|
+
* to it, and the three who did not had no reason at all. `cli/src/ci/workflowModuleFormat.test.ts` is what
|
|
19
|
+
* now asks the question of the class rather than of the author.
|
|
20
|
+
*
|
|
21
|
+
* ## Why it refuses rather than being empty
|
|
22
|
+
*
|
|
23
|
+
* `export default {}` would build. It would also say nothing: an operator who reaches this Worker in a
|
|
24
|
+
* browser or with a stray `curl` gets an empty 200-shaped nothing from a Worker they were told hosts a job.
|
|
25
|
+
* A Workflow host has no request surface — an app Worker starts its jobs through a cross-script Workflow
|
|
26
|
+
* binding, and a host with a cron fires its own `scheduled` — so an HTTP request arriving at one is a
|
|
27
|
+
* misconfiguration, and the refusal is the sentence that ends the operator's search. `core/not_found`,
|
|
28
|
+
* because that is the truth: this Worker has no HTTP resources. The `action` names the path that does work
|
|
29
|
+
* and is stripped before the body goes out, like every other action.
|
|
30
|
+
*
|
|
31
|
+
* ## The one host this is not for
|
|
32
|
+
*
|
|
33
|
+
* A host that *does* serve HTTP mounts `registerWorkflowDispatchRoute` (./dispatchRoute) and exports its own
|
|
34
|
+
* handler. `@pithy-sh/email` is the case, and its door is the loopback dispatch `pithy dev` knocks on
|
|
35
|
+
* (#410). The other hosts have not been given that door yet; when one is, its `export default` becomes the
|
|
36
|
+
* Hono app and this refusal becomes that app's fallthrough. Nothing here has to change for that.
|
|
37
|
+
*/
|
|
38
|
+
/** What a refusing host exports: a `fetch`, and nothing else. Every other entry a Worker has is absent. */
|
|
39
|
+
export interface WorkflowHostEntry {
|
|
40
|
+
/** Refuse the request. The platform passes a request, an env and a context; none is read, so none is declared. */
|
|
41
|
+
fetch(): Promise<Response>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the default export for a Workflow host with no HTTP surface.
|
|
45
|
+
*
|
|
46
|
+
* Takes the capability so the refusal says which Worker answered — an operator holding a port number and a
|
|
47
|
+
* 404 needs that before anything else.
|
|
48
|
+
*/
|
|
49
|
+
export declare function workflowHostEntry(capability: string): WorkflowHostEntry;
|
|
50
|
+
//# sourceMappingURL=hostEntry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostEntry.d.ts","sourceRoot":"","sources":["../../src/workflow/hostEntry.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,2GAA2G;AAC3G,MAAM,WAAW,iBAAiB;IAChC,kHAAkH;IAClH,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,CAcvE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NotFoundError } from "../error/pithyError.js";
|
|
2
|
+
import { HttpError } from "../error/http.js";
|
|
3
|
+
//#region src/workflow/hostEntry.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build the default export for a Workflow host with no HTTP surface.
|
|
6
|
+
*
|
|
7
|
+
* Takes the capability so the refusal says which Worker answered — an operator holding a port number and a
|
|
8
|
+
* 404 needs that before anything else.
|
|
9
|
+
*/
|
|
10
|
+
function workflowHostEntry(capability) {
|
|
11
|
+
return { async fetch() {
|
|
12
|
+
const refusal = new NotFoundError({
|
|
13
|
+
message: `The ${capability} workflow host serves no HTTP requests.`,
|
|
14
|
+
action: `Start its Workflows through the ${capability} Workflow binding, not over HTTP.`,
|
|
15
|
+
detail: "This Worker hosts Workflow classes and registers no routes."
|
|
16
|
+
});
|
|
17
|
+
return new Response(JSON.stringify({ error: HttpError.encode(refusal.payload) }), {
|
|
18
|
+
status: refusal.payload.status,
|
|
19
|
+
headers: { "content-type": "application/json" }
|
|
20
|
+
});
|
|
21
|
+
} };
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { workflowHostEntry };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Logger } from "../logger/logger";
|
|
3
|
+
/**
|
|
4
|
+
* What a capability host worker reads out of its env, and what fills each of it.
|
|
5
|
+
*
|
|
6
|
+
* A host is a Worker nobody authored: `pithy <capability> provision` resolves a committed template
|
|
7
|
+
* (see {@link ./host.ts}) and deploys it. Everything it needs therefore arrives as a binding, a var,
|
|
8
|
+
* a Secrets Store entry or a serialized config blob — and until this module, **none of it was
|
|
9
|
+
* validated anywhere.** `@pithy-sh/email`'s host read fourteen fields raw: a missing `BASE_URL`
|
|
10
|
+
* became a magic link to `undefined/…`, an unparseable `EMAIL_THEME` threw inside a render step
|
|
11
|
+
* three retries deep, and a `SCHEDULER_BATCH_SIZE` somebody typed as `"fifty"` became `NaN`, so the
|
|
12
|
+
* scheduler claimed nothing, quietly, forever. Every one of those is discovered as a mail that did
|
|
13
|
+
* not arrive.
|
|
14
|
+
*
|
|
15
|
+
* So a host declares its env once, as a Zod object with a `.describe()` per field, and pairs each
|
|
16
|
+
* field with the thing that provides it. Two consumers read that one declaration:
|
|
17
|
+
*
|
|
18
|
+
* - the host itself, at boot, through {@link requireHostEnv} — one legible block naming every
|
|
19
|
+
* unusable value and what fills it, then a refusal. A host that cannot work does not wait to be
|
|
20
|
+
* asked.
|
|
21
|
+
* - `pithy doctor`, statically, through {@link hostEnvFields} and {@link checkHostEnv} — the same
|
|
22
|
+
* schema, so the check an operator runs and the check the host runs cannot disagree.
|
|
23
|
+
*
|
|
24
|
+
* ## Kept importable from the CLI
|
|
25
|
+
*
|
|
26
|
+
* No `cloudflare:` import, no Node builtin, no filesystem — the same constraint {@link ./host.ts}
|
|
27
|
+
* carries, and for the same reason: `pithy doctor` runs under node and imports this to read a
|
|
28
|
+
* capability's declaration without executing its Worker.
|
|
29
|
+
*/
|
|
30
|
+
/** The kinds of thing that can fill a host env field. One of these names is what an operator acts on. */
|
|
31
|
+
export declare const HostEnvProviderKind: z.ZodEnum<{
|
|
32
|
+
binding: "binding";
|
|
33
|
+
config: "config";
|
|
34
|
+
secret: "secret";
|
|
35
|
+
var: "var";
|
|
36
|
+
}>;
|
|
37
|
+
export type HostEnvProviderKind = z.infer<typeof HostEnvProviderKind>;
|
|
38
|
+
/**
|
|
39
|
+
* What provides one field. The whole point of the declaration: a report that says `BASE_URL is
|
|
40
|
+
* missing` sends a developer looking, and a report that says `Var BASE_URL in the host's
|
|
41
|
+
* wrangler.jsonc. Run pithy email provision --env dev.` ends the search.
|
|
42
|
+
*/
|
|
43
|
+
export declare const HostEnvProvider: z.ZodObject<{
|
|
44
|
+
kind: z.ZodEnum<{
|
|
45
|
+
binding: "binding";
|
|
46
|
+
config: "config";
|
|
47
|
+
secret: "secret";
|
|
48
|
+
var: "var";
|
|
49
|
+
}>;
|
|
50
|
+
name: z.ZodString;
|
|
51
|
+
command: z.ZodOptional<z.ZodString>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
export type HostEnvProvider = z.infer<typeof HostEnvProvider>;
|
|
54
|
+
/**
|
|
55
|
+
* A host's env declaration: the capability that owns it, the schema, and a provider per field.
|
|
56
|
+
*
|
|
57
|
+
* **This type is the contract `pithy doctor` reads** (pithy-sh/pithy#411). A capability exports one
|
|
58
|
+
* of these as an ordinary value, so the CLI can import it, walk the schema, and validate a resolved
|
|
59
|
+
* configuration against the very object the deployed Worker validates itself against.
|
|
60
|
+
*/
|
|
61
|
+
export interface HostEnvDeclaration<Env extends z.ZodObject = z.ZodObject> {
|
|
62
|
+
/** The capability that owns the host — the `<capability>` segment of its worker name. */
|
|
63
|
+
readonly capability: string;
|
|
64
|
+
/** The env schema. `z.output` is what the host runs on; coercions and JSON parses belong in here. */
|
|
65
|
+
readonly env: Env;
|
|
66
|
+
/** Field name → what fills it. Every field of {@link env} has an entry; nothing else may. */
|
|
67
|
+
readonly provided: Readonly<Record<string, HostEnvProvider>>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Declare a host's env. The mapped `provided` type makes an unaccounted field a compile error; the
|
|
71
|
+
* runtime check below makes it an error for a declaration the CLI reads back off a package it never
|
|
72
|
+
* compiled, which is the case `pithy doctor` is entirely made of.
|
|
73
|
+
*/
|
|
74
|
+
export declare function defineHostEnv<Env extends z.ZodObject>(declaration: {
|
|
75
|
+
capability: string;
|
|
76
|
+
env: Env;
|
|
77
|
+
provided: {
|
|
78
|
+
readonly [Field in keyof Env["shape"] & string]: HostEnvProvider;
|
|
79
|
+
};
|
|
80
|
+
}): HostEnvDeclaration<Env>;
|
|
81
|
+
/** One field of a host env that is missing or unparseable, with what would fix it. */
|
|
82
|
+
export interface HostEnvProblem {
|
|
83
|
+
/** The field name, as declared. */
|
|
84
|
+
field: string;
|
|
85
|
+
/** Why it is unusable — the Zod issue's own message, unedited. */
|
|
86
|
+
reason: string;
|
|
87
|
+
/** What provides it. */
|
|
88
|
+
provider: HostEnvProvider;
|
|
89
|
+
}
|
|
90
|
+
/** The outcome of checking one env against one declaration. `value` is present exactly when `ok`. */
|
|
91
|
+
export interface HostEnvReport<Value> {
|
|
92
|
+
/** Whether every declared field parsed. */
|
|
93
|
+
ok: boolean;
|
|
94
|
+
/** The parsed env — the shape the host runs on — or `undefined` when anything failed. */
|
|
95
|
+
value: Value | undefined;
|
|
96
|
+
/** Every unusable field, one entry each, in declaration order. */
|
|
97
|
+
problems: HostEnvProblem[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check an env against a declaration. Pure: it parses, it reports, and it neither logs nor throws —
|
|
101
|
+
* which is what lets `pithy doctor` run the host's own check without a Worker.
|
|
102
|
+
*
|
|
103
|
+
* One problem per field, even where Zod raises several issues for it: an operator fixes a field, not
|
|
104
|
+
* an issue, and three lines about `EMAIL_THEME` push the field they have not read yet off the block.
|
|
105
|
+
*/
|
|
106
|
+
export declare function checkHostEnv<Env extends z.ZodObject>(declaration: HostEnvDeclaration<Env>, env: unknown): HostEnvReport<z.output<Env>>;
|
|
107
|
+
/** One sentence naming the thing an operator changes, plus the command that writes it where there is one. */
|
|
108
|
+
export declare function hostEnvProviderSentence(provider: HostEnvProvider): string;
|
|
109
|
+
/**
|
|
110
|
+
* The block a host logs before it refuses. One headline, then one line per field: the field, why it
|
|
111
|
+
* is unusable, and what fills it. Brand voice — short sentences, deliberate periods, no decoration
|
|
112
|
+
* that a log aggregator would have to strip.
|
|
113
|
+
*/
|
|
114
|
+
export declare function renderHostEnvProblems(capability: string, problems: readonly HostEnvProblem[]): string;
|
|
115
|
+
/**
|
|
116
|
+
* Validate a host's env, or say exactly what is wrong and refuse.
|
|
117
|
+
*
|
|
118
|
+
* Called at boot, before the host serves anything. The block goes to the log (the operator's
|
|
119
|
+
* audience, so it carries the provider lines) and the refusal is `core/internal`: a host that cannot
|
|
120
|
+
* parse config *we* generated is our failure, and our logs are where the answer is (CLAUDE.md
|
|
121
|
+
* §Errors). Nothing about the values themselves is logged — a provider name is a location, never a
|
|
122
|
+
* secret.
|
|
123
|
+
*/
|
|
124
|
+
export declare function requireHostEnv<Env extends z.ZodObject>(declaration: HostEnvDeclaration<Env>, env: unknown, log?: Logger): z.output<Env>;
|
|
125
|
+
/** One declared field, flattened for a reader that never runs the host — `pithy doctor`'s row. */
|
|
126
|
+
export interface HostEnvField {
|
|
127
|
+
/** The field name, as the env carries it. */
|
|
128
|
+
field: string;
|
|
129
|
+
/** The field's own `.describe()`, or `undefined` where the schema carries none. */
|
|
130
|
+
description: string | undefined;
|
|
131
|
+
/** What provides it. */
|
|
132
|
+
provider: HostEnvProvider;
|
|
133
|
+
/** Whether the host works without it — i.e. whether the field's schema accepts `undefined`. */
|
|
134
|
+
optional: boolean;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Read a declaration statically: what the host needs, what documents each field, and what fills it.
|
|
138
|
+
*
|
|
139
|
+
* The static half of this module, and the one `pithy doctor` builds its report from (#411). Field
|
|
140
|
+
* order is the schema's, so a report reads in the order the capability chose to explain itself.
|
|
141
|
+
*/
|
|
142
|
+
export declare function hostEnvFields(declaration: HostEnvDeclaration): HostEnvField[];
|
|
143
|
+
//# sourceMappingURL=hostEnv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostEnv.d.ts","sourceRoot":"","sources":["../../src/workflow/hostEnv.ts"],"names":[],"mappings":"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"}
|