Skip to content

Commit fb43abf

Browse files
yamcodescursoragent
andcommitted
fix: resolve merge conflicts with v1 after #1294
Merge origin/v1 and relocate log helpers from @arkenv/build/log to @repo/utils on top of the core/log split and nuxt flat-layout changes. Co-authored-by: Cursor <cursoragent@cursor.com>
2 parents dcfcafa + 90ac1e1 commit fb43abf

32 files changed

Lines changed: 1837 additions & 708 deletions

.changeset/move-log-helpers-to-repoutils.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
"@arkenv/build": patch
2+
"@arkenv/build": minor
33
"@arkenv/nextjs": patch
44
"@arkenv/nuxt": patch
55
"@arkenv/bun-plugin": patch
@@ -8,7 +8,7 @@
88

99
#### Centralize build log helpers in `@repo/utils`
1010

11-
Move shared build and watcher log helpers to `@repo/utils` and route remaining ad-hoc `console.*` call sites through them or the CLI `LoggerPort`.
11+
Move shared build and watcher log helpers to `@repo/utils` and route remaining ad-hoc `console.*` call sites through them or the CLI `LoggerPort`. Remove the `@arkenv/build/log` subpath introduced in #1294.
1212

1313
Integration packages bundle the helpers via `alwaysBundle` so they keep zero extra runtime dependencies:
1414

@@ -22,3 +22,5 @@ import {
2222
```
2323

2424
The CLI uses a `TextReporter`-backed fallback logger for unhandled rejections before the global logger is initialized.
25+
26+
**BREAKING CHANGE:** Drop the `@arkenv/build/log` export; import log helpers from bundled `@repo/utils` usage instead.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
"@arkenv/build": patch
3+
"arkenv": minor
4+
"@arkenv/nuxt": minor
5+
---
6+
7+
#### Align Nuxt flat layout across CLI, examples, and build resolution
8+
9+
Forward-port flat layout support for Nuxt on v1 by aligning CLI scaffolding, build-time validation, runtime proxy behavior, and `@arkenv/build` layout resolution.
10+
11+
Usage:
12+
13+
```ts
14+
// nuxt.config.ts
15+
export default defineNuxtConfig({
16+
modules: ["@arkenv/nuxt/module"],
17+
arkenv: { layout: "flat" },
18+
});
19+
```
20+
21+
```ts
22+
// env.ts
23+
import arkenv from "@arkenv/nuxt";
24+
25+
export const env = arkenv({
26+
DATABASE_URL: "string",
27+
NUXT_PUBLIC_API_URL: "string",
28+
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
29+
});
30+
```
31+
32+
- `arkenv` init wizard presents "Flat (Recommended)" for Nuxt and scaffolds a flat `env.ts`
33+
- `@arkenv/build` `resolveLayout()` accepts `"flat"` as an alias for the single-file layout mode
34+
- Nuxt examples and playgrounds use flat layout conventions
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@arkenv/build": patch
3+
"@arkenv/nextjs": patch
4+
"@arkenv/nuxt": patch
5+
---
6+
7+
#### Standardize warning and error log prefix formatting
8+
9+
Introduce a shared `log.ts` utility module in `@arkenv/build` with unified prefix constants and helper functions (`logBuildWarning`, `logBuildError`, `formatBuildError`, `logWatcherError`). Update `@arkenv/nextjs` and `@arkenv/nuxt` to use these helpers instead of manually-prefixed string literals, eliminating casing inconsistencies and code duplication.

apps/playgrounds/nuxt/env.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import arkenv from "@arkenv/nuxt";
22

33
export const env = arkenv({
4-
server: {
5-
DATABASE_URL: "string = 'postgres://localhost:5432/mydb'",
6-
},
7-
client: {
8-
NUXT_PUBLIC_API_URL: "string = 'https://api.example.com'",
9-
},
10-
shared: {
11-
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
12-
},
4+
DATABASE_URL: "string = 'postgres://localhost:5432/mydb'",
5+
NUXT_PUBLIC_API_URL: "string = 'https://api.example.com'",
6+
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
137
});
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
---
2+
title: Flat layout
3+
icon: Zap
4+
description: Get the ultimate DX in Nuxt using a single, unified flat schema file.
5+
---
6+
7+
In this setup, you define all your environment variables in a single flat object.
8+
9+
```files
10+
env.ts
11+
```
12+
13+
To protect server-side secrets from ever reaching the client bundle in the browser, ArkEnv uses a proxy that throws a runtime error if a server-side variable is accessed in browser code. Note that during Server-Side Rendering (SSR), client-shared code executes on the server first, where this runtime guard is not active. See the [Security model](/docs/nuxt/security) page for more details.
14+
15+
:::warning[Server logic in client bundle]
16+
Defining your schemas together means the *server validation logic* is shipped in the client bundle.
17+
18+
| ⚠️ Visible in JS bundle | 🔒 Secure on server |
19+
| :------------------------------------------------------------------------------ | :--------------------------------------------------- |
20+
| **Schema** (keys, types, and constraints)<br />e.g., `DATABASE_URL: string.url` | **Runtime values**<br />e.g., `"postgresql://db..."` |
21+
22+
The values themselves are *not* shipped to the client! But if exposing your server variable *names*, *types*, or *constraints* is a security concern, use the [strict layout](/docs/nuxt/layouts/strict) instead.
23+
:::
24+
25+
## Setup
26+
27+
The easiest way to bootstrap the flat layout is with the [ArkEnv CLI](/docs/cli). It automatically configures `@arkenv/nuxt` for your existing Nuxt project and generates your `env.ts` file.
28+
29+
```npm
30+
npx arkenv@latest init
31+
```
32+
33+
## Your schema
34+
35+
When bootstrapping with the CLI, it generates a single `env.ts` file where you define your environment variables directly in a flat structure:
36+
37+
```ts title="env.ts" twoslash
38+
import arkenv from '@arkenv/nuxt';
39+
// ---cut---
40+
export const env = arkenv({
41+
DATABASE_URL: "string",
42+
NUXT_PUBLIC_API_URL: "string",
43+
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
44+
});
45+
```
46+
47+
### Exposing client variables
48+
49+
By default, ArkEnv automatically identifies and exposes variables to the client based on two criteria:
50+
51+
1. Keys prefixed with `NUXT_PUBLIC_` (e.g. `NUXT_PUBLIC_API_URL`).
52+
2. The `NODE_ENV` variable (which is implicitly shared to align with Nuxt's runtime config).
53+
54+
If you have custom variables that do not follow the prefix convention but must be exposed to the client, you can specify them using the `exposeToClient` option:
55+
56+
```ts title="env.ts" twoslash
57+
import arkenv from '@arkenv/nuxt';
58+
// ---cut---
59+
export const env = arkenv({
60+
DATABASE_URL: "string",
61+
NUXT_PUBLIC_API_URL: "string",
62+
CUSTOM_VAR: "string",
63+
}, {
64+
exposeToClient: ["CUSTOM_VAR"]
65+
});
66+
```
67+
68+
<Accordions>
69+
<Accordion title="Manual setup">
70+
### Configure environment [step] [!toc]
71+
72+
Create an `env.ts` file at the root of your project to define your schema. Import `arkenv` from `@arkenv/nuxt`:
73+
74+
```ts twoslash title="env.ts"
75+
import arkenv from '@arkenv/nuxt';
76+
// ---cut---
77+
export const env = arkenv({
78+
DATABASE_URL: "string",
79+
NUXT_PUBLIC_API_URL: "string",
80+
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
81+
});
82+
```
83+
84+
### Register module in Nuxt config [step] [!toc]
85+
86+
Add `@arkenv/nuxt/module` to your modules array in `nuxt.config.ts`. The module scans your schema at build time for validation and registers the public keys to Nuxt's `runtimeConfig`. At runtime, values are resolved dynamically from `useRuntimeConfig()` — no generated files are created or needed:
87+
88+
```ts title="nuxt.config.ts"
89+
export default defineNuxtConfig({
90+
modules: ["@arkenv/nuxt/module"]
91+
});
92+
```
93+
94+
You can customize the schema path and validation behavior using optional parameters:
95+
96+
```ts title="nuxt.config.ts"
97+
export default defineNuxtConfig({
98+
modules: ["@arkenv/nuxt/module"],
99+
arkenv: {
100+
schemaPath: "env.ts", // Path to your schema (default: env.ts or src/env.ts)
101+
layout: "flat", // Explicitly specify layout
102+
validate: true, // Validate environment variables at build-time (default: true)
103+
}
104+
});
105+
```
106+
107+
### Use in your code [step] [!toc]
108+
109+
Import `env` throughout your Nuxt application:
110+
111+
```ts title="components/MyComponent.vue"
112+
import { env } from "~~/env";
113+
114+
// Access is fully typesafe and autocompleted
115+
const apiUrl = env.NUXT_PUBLIC_API_URL;
116+
```
117+
118+
If you accidentally attempt to access a server-side secret in client-side code, it will throw a descriptive runtime exception during browser execution (note that it will not throw during Server-Side Rendering, only once hydration completes in the browser):
119+
120+
```ts title="components/ClientOnlyComponent.vue"
121+
import { env } from "~~/env";
122+
123+
// Throws a runtime error if evaluated in client-side code
124+
const dbUrl = env.DATABASE_URL;
125+
```
126+
</Accordion>
127+
</Accordions>

apps/www/content/docs/nuxt/layouts/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"icon": "Layers",
44
"defaultOpen": true,
55
"pages": [
6-
"[Zap][Simple (Recommended)](/docs/nuxt/layouts/simple)",
6+
"[Zap][Flat (Recommended)](/docs/nuxt/layouts/flat)",
77
"[ShieldCheck][Strict](/docs/nuxt/layouts/strict)"
88
]
99
}

apps/www/next.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ const config = {
5151
destination: "/docs/nextjs/faq#how-do-i-define-client-side-variables",
5252
permanent: true,
5353
},
54+
{
55+
source: "/docs/nuxt/layouts/simple",
56+
destination: "/docs/nuxt/layouts/flat",
57+
permanent: true,
58+
},
5459
];
5560
},
5661
async rewrites() {

examples/with-nuxt/env.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import arkenv from "@arkenv/nuxt";
22

33
export const env = arkenv({
4-
server: {
5-
DATABASE_URL: "string = 'postgres://localhost:5432/mydb'",
6-
},
7-
client: {
8-
NUXT_PUBLIC_API_URL: "string = 'https://api.example.com'",
9-
},
10-
shared: {
11-
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
12-
},
4+
DATABASE_URL: "string = 'postgres://localhost:5432/mydb'",
5+
NUXT_PUBLIC_API_URL: "string = 'https://api.example.com'",
6+
NODE_ENV: "'development' | 'production' | 'test' = 'development'",
137
});

packages/arkenv/src/cli/ui/prompts.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ describe("runPromptWizard", () => {
5555
expect(result?.layout).toBe("flat");
5656
});
5757

58+
it("should default layout to flat for nuxt in isYes mode", async () => {
59+
const result = await runPromptWizard({ framework: "nuxt" }, true);
60+
61+
expect(result?.framework).toBe("nuxt");
62+
expect(result?.layout).toBe("flat");
63+
});
64+
5865
it("should default wrapNextjsConfig to true for nextjs in isYes mode", async () => {
5966
const result = await runPromptWizard({ framework: "nextjs" }, true);
6067

packages/arkenv/src/cli/ui/prompts/steps/framework.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ export async function layoutStep(options?: {
117117
]
118118
: [
119119
{
120-
value: "simple",
121-
label: "Simple (Recommended)",
122-
hint: "A single env.ts file for the best DX",
120+
value: "flat",
121+
label: "Flat (Recommended)",
122+
hint: "A single flat env.ts file for the best DX",
123123
},
124124
{
125125
value: "strict",

0 commit comments

Comments
 (0)