Skip to content

fix(cli): scaffold Valibot PORT as v.number() - #1663

Merged
yamcodes merged 2 commits into
v1from
fix/valibot-port-wrapper
Aug 28, 2026
Merged

fix(cli): scaffold Valibot PORT as v.number()#1663
yamcodes merged 2 commits into
v1from
fix/valibot-port-wrapper

Conversation

@yamcodes

Copy link
Copy Markdown
Owner

Summary

  • arkenv init with Valibot already imports @arkenv/standard/valibot, which binds @valibot/to-json-schema so v.number() coerces env strings.
  • The generated PORT field still used v.pipe(v.string(), v.transform(Number), …), which fights that wrapper. Scaffold PORT as a numeric schema instead (same range/default as before).
  • The examples/with-valibot example on v1 already used the wrapper + v.number(); this aligns the CLI with it.

Test plan

  • pnpm --filter arkenv exec vitest run src/features/scaffold/validators.test.ts
  • Confirm a Valibot arkenv init env file imports @arkenv/standard/valibot and has PORT: v.optional(v.pipe(v.number(), …), 3000)
  • PORT=3000 boots without a manual transform

Made with Cursor

init already imports @arkenv/standard/valibot, so string transforms fight the wrapper instead of letting it coerce env strings.

Co-authored-by: Cursor <cursoragent@cursor.com>
@yamcodes yamcodes added bug Something isn't working arkenv Changes to the `arkenv` npm package. tests This issue or PR is about adding, removing or changing tests labels Aug 28, 2026
@changeset-bot

changeset-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7114998

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
arkenv Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the docs Adds or changes documentation, or acts as documentation in and of itself label Aug 28, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

@arkenv/agent-plugin

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/agent-plugin@1663

arkenv

npm i https://pkg.pr.new/yamcodes/arkenv@1663

@arkenv/build

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/build@1663

@arkenv/bun-plugin

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/bun-plugin@1663

@arkenv/core

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/core@1663

@arkenv/fumadocs-ui

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/fumadocs-ui@1663

@arkenv/nextjs

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/nextjs@1663

@arkenv/nuxt

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/nuxt@1663

@arkenv/standard

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/standard@1663

@arkenv/vite-plugin

npm i https://pkg.pr.new/yamcodes/arkenv/@arkenv/vite-plugin@1663

commit: 7114998

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one minor suggestion inline.

Reviewed changes

  • Valibot scaffold PORT pipelinepackages/arkenv/src/features/scaffold/validators/dialects/valibot.ts now generates PORT: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(65535)), 3000), dropping the v.string() + v.transform(Number) front-end in both the server field and defaultSimpleSchemaFields paths. Same range and default as before.
  • Scaffold template assertionvalidators.test.ts updated to pin the new numeric pipeline.
  • Loader test fixturejiti-schema-loader.adapter.test.ts updated from v.fallback(v.pipe(v.string(), v.transform(Number)), 3000) to v.optional(v.number(), 3000) for the "defaulted keys" case.
  • Changeset — adds a patch changeset for arkenv describing the change.

I verified the fix behaviorally against @arkenv/standard/valibot (built from source): the new schema coerces PORT=3000 to a number, falls back to 3000 when unset, and rejects abc, out-of-range, and fractional values. The old scaffold was genuinely broken — with PORT unset it threw Expected string but received 3000 because Valibot routes the v.optional default through the pipe, so v.string() rejected the numeric default. Both affected test files pass locally.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Cover the scaffolded v.optional(v.pipe(v.number(), …), 3000) schema with an empty env and PORT=3000 so the default-through-pipe regression cannot slip past a template-string assertion.

Co-authored-by: Cursor <cursoragent@cursor.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Added a runtime regression pin in @arkenv/standard — the new commit boots the exact CLI PORT schema (v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(65535)), 3000)) with an empty env (expects default 3000) and with PORT="3000" (expects coerced number 3000), closing out the prior review's minor suggestion and the two still-unchecked boxes in the test plan. I confirmed its regression-catchy: a scratch pin using the old string-transform schema still throws on the empty-env path, so this test would have caught the original default-crash. All 48 CLI scaffold/loader tests and the 5 subpaths.test.ts tests pass against a fresh build.

No concerns with the incremental delta. The behavioral fix itself was already validated in the prior review.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@yamcodes
yamcodes merged commit 0cf0e74 into v1 Aug 28, 2026
19 checks passed
@yamcodes
yamcodes deleted the fix/valibot-port-wrapper branch August 28, 2026 16:12
@arkenv-bot arkenv-bot Bot mentioned this pull request Aug 28, 2026
yamcodes pushed a commit that referenced this pull request Aug 28, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to v1, this PR will
be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

`v1` is currently in **pre mode** so this branch has prereleases rather
than normal releases. If you want to exit prereleases, run `changeset
pre exit` on `v1`.

⚠️⚠️⚠️⚠️⚠️⚠️

# Releases
## arkenv@1.0.0-alpha.15

### Major Changes

- #### Replace `--json` payloads with settlement envelopes
_[`#1633`](#1633)
[`02a5a32`](02a5a32)
[@yamcodes](https://github.com/yamcodes)_

`--json` / `--agent` now write an `ok`-discriminated settlement document
to stdout instead of `{ status, code, message, retryWith }`.
Human-readable output is unchanged. JSON stays on stdout; logs stay on
stderr. Secret values are redacted in `meta`, `summary`, and `why`.

Completed runs use `ok: true` (including `arkenv check` findings, which
still set `exitCode: 4`). Aborts use `ok: false` with a dotted `CLI.*`
or `ENV.*` code. `nextActions` is always present (`[]` when there is
nothing to do). Commands in `nextActions` resolve to the invoked runner
(`pnpm arkenv`, `npx arkenv`, `bunx arkenv`, and so on).

  Example refusal:

  ```json
  {
    "ok": false,
    "commandId": "init",
    "error": {
      "code": "CLI.GIT_TREE_DIRTY",
      "severity": "error",
      "summary": "Git working tree is not clean.",
      "nextActions": [
        {
          "kind": "run-command",
          "label": "Re-run with --force to bypass this check",
          "command": "npx arkenv init --force"
        }
      ]
    },
    "diagnostics": [],
    "nextActions": [
      {
        "kind": "run-command",
        "label": "Re-run with --force to bypass this check",
        "command": "npx arkenv init --force"
      }
    ]
  }
  ```

**BREAKING CHANGE**: Agents must switch from `status` / `retryWith` to
`ok` / `error.code` / `nextActions`. Flat codes such as `GIT_TREE_DIRTY`
are now dotted (`CLI.GIT_TREE_DIRTY`).

  ```diff
- { "status": "error", "code": "GIT_TREE_DIRTY", "retryWith":
["--force"] }
+ { "ok": false, "error": { "code": "CLI.GIT_TREE_DIRTY", "nextActions":
[{ "kind": "run-command", "command": "npx arkenv init --force" }] } }
  ```

### Minor Changes

- #### Add `arkenv check` command and cross-module validation detection
_[`#1632`](#1632)
[`01a028d`](01a028d)
[@yamcodes](https://github.com/yamcodes)_

- Add `arkenv check` CLI command to validate the active environment
against the project's env schema, supporting `--schema` (`-s`),
repeatable `--env-file`, `--json`, `--quiet`, and `--agent` with
CI-friendly exit codes.
- Add structural `ArkErrors` verification in `@arkenv/core` so
cross-module-instance schema evaluation reliably surfaces validation
issues.

- #### Add `arkenv example` to update `.env.example` from the schema
_[`#1643`](#1643)
[`de8add3`](de8add3)
[@yamcodes](https://github.com/yamcodes)_

`arkenv example` now loads the project schema and writes `.env.example`
  with every declared key. Existing comments and values are preserved
  for keys that remain in the schema; removed keys are dropped; new keys
  are appended. `arkenv init` reuses the same path after scaffolding an
  existing project.

  Usage:

  ```sh
  npx arkenv@latest example
  npx arkenv@latest example --schema ./src/env.ts --json
  ```

### Patch Changes

- #### Drop default `z.coerce` from Zod product samples and scaffold
templates _[`#1631`](#1631)
[`ba9f903`](ba9f903)
[@yamcodes](https://github.com/yamcodes)_

Scaffolded Zod templates, `@arkenv/standard` JSDoc examples, and
official example projects now declare numeric and boolean fields with
`z.number()` and `z.boolean()` instead of `z.coerce.number()` or
`z.coerce.boolean()`, reflecting ArkEnv's built-in pre-coercion for
Standard Schema validators.

  ```ts
  import arkenv from "@arkenv/standard";
  import { z } from "zod";

  export const env = arkenv({
    PORT: z.number().default(3000),
    DATABASE_URL: z.string().url(),
    DEBUG: z.boolean().default(false),
  });
  ```

- #### Align Next.js onboarding with `@/.arkenv`
_[`#1639`](#1639)
[`cc87d51`](cc87d51)
[@yamcodes](https://github.com/yamcodes)_

`arkenv init` now scaffolds Next.js schemas that import the codegen
factory from `@/.arkenv`, writes that factory to `.arkenv/env.gen.ts`,
gitignores `.arkenv/`, and maps the specifier in `tsconfig.json`. Docs,
READMEs, and examples match that path instead of `./generated/env.gen`.

  ```ts
  import arkenv from "@/.arkenv";

  export const env = arkenv({
    DATABASE_URL: "string",
    NEXT_PUBLIC_API_URL: "string",
  });
  ```

Existing `outputPath` overrides still work. Keep importing `@/.arkenv`.
`withArkEnv` aliases the specifier for bundlers, and codegen keeps
`.arkenv/index.ts` re-exporting the file so `tsc --noEmit` resolves it
too.

- #### Scaffold Valibot `PORT` as `v.number()` instead of a string
transform _[`#1663`](#1663)
[`0cf0e74`](0cf0e74)
[@yamcodes](https://github.com/yamcodes)_

`arkenv init` with Valibot already imports `@arkenv/standard/valibot`,
which binds `@valibot/to-json-schema` for coercion. Generate `PORT` as a
numeric schema so the wrapper can coerce `"3000"` instead of requiring
`v.transform(Number)`.

  ```ts
  import { arkenv } from "@arkenv/standard/valibot";
  import * as v from "valibot";

  export const env = arkenv({
    PORT: v.optional(
      v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(65535)),
      3000
    ),
  });
  ```
## @arkenv/core@1.0.0-alpha.7

### Patch Changes

- #### Add `arkenv check` command and cross-module validation detection
_[`#1632`](#1632)
[`01a028d`](01a028d)
[@yamcodes](https://github.com/yamcodes)_

- Add `arkenv check` CLI command to validate the active environment
against the project's env schema, supporting `--schema` (`-s`),
repeatable `--env-file`, `--json`, `--quiet`, and `--agent` with
CI-friendly exit codes.
- Add structural `ArkErrors` verification in `@arkenv/core` so
cross-module-instance schema evaluation reliably surfaces validation
issues.
## @arkenv/nextjs@1.0.0-alpha.13

### Patch Changes

- #### Align Next.js onboarding with `@/.arkenv`
_[`#1639`](#1639)
[`cc87d51`](cc87d51)
[@yamcodes](https://github.com/yamcodes)_

`arkenv init` now scaffolds Next.js schemas that import the codegen
factory from `@/.arkenv`, writes that factory to `.arkenv/env.gen.ts`,
gitignores `.arkenv/`, and maps the specifier in `tsconfig.json`. Docs,
READMEs, and examples match that path instead of `./generated/env.gen`.

  ```ts
  import arkenv from "@/.arkenv";

  export const env = arkenv({
    DATABASE_URL: "string",
    NEXT_PUBLIC_API_URL: "string",
  });
  ```

Existing `outputPath` overrides still work. Keep importing `@/.arkenv`.
`withArkEnv` aliases the specifier for bundlers, and codegen keeps
`.arkenv/index.ts` re-exporting the file so `tsc --noEmit` resolves it
too.

<details><summary>Updated 2 dependencies</summary>

<small>


[`01a028d`](01a028d)
[`ba9f903`](ba9f903)

</small>

- `@arkenv/core@1.0.0-alpha.7`
- `@arkenv/standard@1.0.0-alpha.7`

</details>
## @arkenv/standard@1.0.0-alpha.7

### Patch Changes

- #### Drop default `z.coerce` from Zod product samples and scaffold
templates _[`#1631`](#1631)
[`ba9f903`](ba9f903)
[@yamcodes](https://github.com/yamcodes)_

Scaffolded Zod templates, `@arkenv/standard` JSDoc examples, and
official example projects now declare numeric and boolean fields with
`z.number()` and `z.boolean()` instead of `z.coerce.number()` or
`z.coerce.boolean()`, reflecting ArkEnv's built-in pre-coercion for
Standard Schema validators.

  ```ts
  import arkenv from "@arkenv/standard";
  import { z } from "zod";

  export const env = arkenv({
    PORT: z.number().default(3000),
    DATABASE_URL: z.string().url(),
    DEBUG: z.boolean().default(false),
  });
  ```

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arkenv Changes to the `arkenv` npm package. bug Something isn't working docs Adds or changes documentation, or acts as documentation in and of itself tests This issue or PR is about adding, removing or changing tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant