feat: withArkEnv should support split schema#1116
Conversation
🦋 Changeset detectedLatest commit: bf20517 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
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 |
arkenv
@arkenv/bun-plugin
@arkenv/cli
@arkenv/fumadocs-ui
@arkenv/nextjs
@arkenv/vite-plugin
commit: |
📦 Bundle Size Report
✅ All size limits passed! |
There was a problem hiding this comment.
Important
One correctness issue when layout: "strict" is explicitly set but the required split files are missing — the codegen silently produces an empty runtimeEnv instead of throwing. Details inline.
Reviewed changes — Added split-schema ("strict layout") support to the Next.js withArkEnv config wrapper, including auto-detection, static key extraction from split files, and updated CLI scaffolding/next-steps.
- Add
layoutoption and auto-detection towithArkEnv—packages/nextjs/src/config.tsnow resolves"simple"vs"strict"by inspecting the filesystem, and generates a minimalruntimeEnvexport for strict mode. - Introduce
extractClientKeysandextractSharedKeys— New static parsers that extract env var names fromclient.tsandinternal/shared.tsrespectively. - Update CLI strict templates and next-steps —
getStrictEnvTemplatesbranches ondisableCodegen, andgetNextStepsNoteincludeswithArkEnvwrapping instructions for strict-layout projects. - Add tests — Coverage for strict layout auto-detection, key extraction, template generation, and next-steps messaging.
⚠️ Layout resolution logic is duplicated between withArkEnv and runCodegen
The strict-layout auto-detection and baseDir resolution logic appears almost verbatim in both withArkEnv (lines 101–177) and runCodegen (lines 301–367). Keeping two copies in sync is error-prone — a future fix to one is likely to miss the other. Consider extracting a shared resolveLayoutAndBaseDir(schemaPath, layoutOption) helper.
Technical details
# Layout resolution logic is duplicated between `withArkEnv` and `runCodegen`
## Affected sites
- `packages/nextjs/src/config.ts:101-177` — `withArkEnv` layout resolution
- `packages/nextjs/src/config.ts:301-367` — `runCodegen` layout resolution
## Required outcome
- A single source of truth for mapping a `schemaPath` + optional `layout` to a resolved layout and `baseDir`.
- Both `withArkEnv` and `runCodegen` (and the watcher callback) must use it.
## Suggested approach
Extract a pure function:
```ts
function resolveLayout(
schemaPath: string,
layoutOption?: "simple" | "strict",
): { layout: "simple" | "strict"; baseDir: string };
```
Move the `checkStrict` helper and all `fs.existsSync` / `fs.statSync` branching into it. `withArkEnv` calls it once up front and passes the resolved values to `runCodegen`, which can then skip its own re-resolution when they are provided.Kimi K2 | 𝕏
| } else { | ||
| resolvedLayout = "simple"; | ||
| } | ||
| } else if (resolvedLayout === "strict") { |
There was a problem hiding this comment.
layout: "strict" is explicitly set but the required split files (client.ts, internal/shared.ts) don't exist, runCodegen silently produces an empty runtimeEnv instead of throwing a helpful error.
The else if (resolvedLayout === "strict") branch (lines 349–367) resolves baseDir but never validates that client.ts and internal/shared.ts actually exist under it. If they don't, fs.readFileSync isn't called (guarded by fs.existsSync), so clientContent and sharedContent are empty strings, and the generated file exports an empty object.
Technical details
# Explicit strict layout without split files silently produces empty runtimeEnv
## Affected sites
- `packages/nextjs/src/config.ts:369-401` — strict codegen path
## Required outcome
- If `resolvedLayout === "strict"`, the codegen must verify that `client.ts` and `internal/shared.ts` exist under `baseDir`.
- If either is missing, throw a clear error telling the user which files are expected.
## Suggested approach
After resolving `baseDir` in the strict branch, add:
```ts
const clientPath = path.join(baseDir, "client.ts");
const sharedPath = path.join(baseDir, "internal", "shared.ts");
if (!fs.existsSync(clientPath) || !fs.existsSync(sharedPath)) {
throw new Error(
`[ArkEnv] Strict layout requires "${path.join(baseDir, "client.ts")}" and "${path.join(baseDir, "internal", "shared.ts")}".`,
);
}
```
This mirrors the validation already done during auto-detection.| }); | ||
| }); | ||
|
|
||
| describe("strict config key extraction", () => { |
There was a problem hiding this comment.
ℹ️ The new extractClientKeys and extractSharedKeys tests only cover happy paths. Consider adding coverage for edge cases the underlying parsers handle — comments inside blocks, string literals containing braces or colons, and nested object literals — to prevent regressions if the regex/brace-counting logic is ever tightened.
… object templates
…trict layout scaffolding
…matting in CLI scaffolding
…ion for strict mode
|
Pullfrog stalled The agent stopped emitting events for 304s and was killed by the activity-timeout watchdog. 41 events were processed before the failure. Recent agent stderr
|
…e bundle size limit for config package
… codegen utilities
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 main, this PR will be updated. # Releases ## @arkenv/cli@0.2.7 ### Patch Changes - #### Format empty schema objects cleanly in scaffolding _[`#1116`](#1116) [`b62ebbd`](b62ebbd) [@yamcodes](https://github.com/yamcodes)_ Format empty schema objects cleanly as `{}` on a single line (instead of multi-line empty blocks with trailing whitespace) during project scaffolding. - #### Generate tailored `createEnv` factory in Next.js strict layout _[`#1116`](#1116) [`b62ebbd`](b62ebbd) [@yamcodes](https://github.com/yamcodes)_ Generate a tailored `createEnv` factory helper in `env.gen.ts` when using the strict split-schema layout (instead of exporting a raw `runtimeEnv` object). This eliminates the need to manually declare or reference the `runtimeEnv` object inside the client schema `client.ts` file, aligning it closer to the core `arkenv` experience of simply calling `createEnv(schema, options)`. Example usage in `client.ts`: ```ts import { createEnv } from "./generated/env.gen"; import { SharedSchema } from "./internal/shared"; export const env = createEnv( { NEXT_PUBLIC_API_URL: "string", }, { extends: [SharedSchema], } ); ``` - #### Support split schema layout in Next.js config wrapper _[`#1116`](#1116) [`b62ebbd`](b62ebbd) [@yamcodes](https://github.com/yamcodes)_ Add support for the strict split schema layout in the Next.js `withArkEnv` configuration wrapper and update CLI scaffolding instructions: - Add a `layout` option (`"simple" | "strict"`) to `withArkEnv` configuration, which defaults to auto-detecting the strict layout if split files (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`) exist. - Implement key extraction from strict client and shared schema files. - Update CLI next-steps messages to include `withArkEnv` wrapping instructions for strict layout nextjs projects. ## @arkenv/nextjs@0.0.5 ### Patch Changes - #### Generate tailored `createEnv` factory in Next.js strict layout _[`#1116`](#1116) [`b62ebbd`](b62ebbd) [@yamcodes](https://github.com/yamcodes)_ Generate a tailored `createEnv` factory helper in `env.gen.ts` when using the strict split-schema layout (instead of exporting a raw `runtimeEnv` object). This eliminates the need to manually declare or reference the `runtimeEnv` object inside the client schema `client.ts` file, aligning it closer to the core `arkenv` experience of simply calling `createEnv(schema, options)`. Example usage in `client.ts`: ```ts import { createEnv } from "./generated/env.gen"; import { SharedSchema } from "./internal/shared"; export const env = createEnv( { NEXT_PUBLIC_API_URL: "string", }, { extends: [SharedSchema], } ); ``` - #### Support split schema layout in Next.js config wrapper _[`#1116`](#1116) [`b62ebbd`](b62ebbd) [@yamcodes](https://github.com/yamcodes)_ Add support for the strict split schema layout in the Next.js `withArkEnv` configuration wrapper and update CLI scaffolding instructions: - Add a `layout` option (`"simple" | "strict"`) to `withArkEnv` configuration, which defaults to auto-detecting the strict layout if split files (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`) exist. - Implement key extraction from strict client and shared schema files. - Update CLI next-steps messages to include `withArkEnv` wrapping instructions for strict layout nextjs projects. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Fixes #1114
This PR implements split schema layout (strict mode) support in the Next.js config wrapper
withArkEnvand updates the CLI scaffold templates and next steps.