Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/unify-warning-prefix-casing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@arkenv/build": patch
"@arkenv/nextjs": patch
"@arkenv/nuxt": patch
---

#### Standardize warning and error log prefix formatting

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.
13 changes: 10 additions & 3 deletions packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./log": {
"types": "./dist/log.d.ts",
"import": "./dist/log.js",
"require": "./dist/log.cjs"
}
},
"scripts": {
"build": "tsdown",
Expand Down
23 changes: 11 additions & 12 deletions packages/build/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { watch as chokidarWatch, type FSWatcher } from "chokidar";
import { formatBuildError, logWatcherError } from "./log";

// Global watcher reference isolated to this bundle's scope
let activeWatcher: FSWatcher | undefined;
Expand Down Expand Up @@ -95,8 +96,10 @@ export function resolveLayout(
const sharedPath = path.join(baseDir, "internal", "shared.ts");
if (!fs.existsSync(clientPath) || !fs.existsSync(sharedPath)) {
throw new Error(
`[ArkEnv] Strict layout requires "${clientPath}" and "${sharedPath}" to exist. ` +
`Ensure both files are present or remove the 'layout: "strict"' option to let ArkEnv auto-detect.`,
formatBuildError(
`Strict layout requires "${clientPath}" and "${sharedPath}" to exist. ` +
`Ensure both files are present or remove the 'layout: "strict"' option to let ArkEnv auto-detect.`,
),
);
}

Expand Down Expand Up @@ -553,9 +556,7 @@ export function watchSchema(
if (logger) {
logger.error(`Failed to regenerate env: ${message}`);
} else {
console.error(
`[ArkEnv Watcher] Failed to regenerate env: ${message}`,
);
logWatcherError(`Failed to regenerate env: ${message}`);
}
}
});
Expand All @@ -564,9 +565,7 @@ export function watchSchema(
if (logger) {
logger.error(`Failed to start watch on ${schemaPath}: ${message}`);
} else {
console.error(
`[ArkEnv Watcher] Failed to start watch on ${schemaPath}: ${message}`,
);
logWatcherError(`Failed to start watch on ${schemaPath}: ${message}`);
}
}
};
Expand All @@ -577,9 +576,7 @@ export function watchSchema(
if (logger) {
logger.error(`Failed to close previous watcher: ${message}`);
} else {
console.error(
`[ArkEnv Watcher] Failed to close previous watcher: ${message}`,
);
logWatcherError(`Failed to close previous watcher: ${message}`);
}
});
}
Expand All @@ -601,10 +598,12 @@ export async function closeWatcher(logger?: Logger): Promise<void> {
if (logger) {
logger.error(`Failed to close watcher: ${message}`);
} else {
console.error(`[ArkEnv Watcher] Failed to close watcher: ${message}`);
logWatcherError(`Failed to close watcher: ${message}`);
}
} finally {
activeWatcher = undefined;
}
}
}

export * from "./log";
30 changes: 30 additions & 0 deletions packages/build/src/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const BUILD_PREFIX = "[ArkEnv]";
export const WATCHER_PREFIX = "[ArkEnv Watcher]";

/**
* Format an error message with the standard build prefix.
*/
export function formatBuildError(message: string): string {
return `${BUILD_PREFIX} ${message}`;
}

/**
* Log a warning message with the warning symbol and build prefix.
*/
export function logBuildWarning(message: string): void {
console.warn(`⚠️ ${BUILD_PREFIX} ${message}`);
}

/**
* Log an error message with the error symbol and build prefix.
*/
export function logBuildError(message: string): void {
console.error(`❌ ${BUILD_PREFIX} ${message}`);
}

/**
* Log an error message for the watcher.
*/
export function logWatcherError(message: string): void {
console.error(`${WATCHER_PREFIX} ${message}`);
}
2 changes: 1 addition & 1 deletion packages/build/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineConfig } from "tsdown";

export default defineConfig({
entry: ["src/index.ts"],
entry: ["src/index.ts", "src/log.ts"],
format: ["esm", "cjs"],
minify: true,
fixedExtension: false,
Expand Down
5 changes: 3 additions & 2 deletions packages/nextjs/src/arkenv-internal.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { logBuildWarning } from "@arkenv/build/log";
import type { Dict, SchemaShape } from "@repo/types";

export const EXTENDED_ENV = Symbol.for("arkenv.extended_env");
Expand Down Expand Up @@ -54,8 +55,8 @@ export function arkenvInternal(
if (typeof optionsOrIsServer === "boolean") {
if (process.env.NODE_ENV === "development" && !hasWarnedLegacy) {
hasWarnedLegacy = true;
console.warn(
"⚠️ [arkenv] Deprecated: The nested layout structure (specifying 'server', 'client', or 'shared' keys in arkenv) is deprecated and will be removed in the next major version. Please migrate to the flat layout. See guide: https://arkenv.js.org/docs/nextjs/faq#how-do-i-define-client-side-variables",
logBuildWarning(
"Deprecated: The nested layout structure (specifying 'server', 'client', or 'shared' keys in arkenv) is deprecated and will be removed in the next major version. Please migrate to the flat layout. See guide: https://arkenv.js.org/docs/nextjs/faq#how-do-i-define-client-side-variables",
);
}
// Old nested schema behavior (backward compatible)
Expand Down
21 changes: 14 additions & 7 deletions packages/nextjs/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {
extractClientKeys,
extractSharedKeys,
findSchemaPath,
formatBuildError,
logBuildError,
logBuildWarning,
parseBlockKeys,
resolveLayout,
watchSchema,
Expand All @@ -22,8 +25,8 @@ function normalizeLayout(
if (layout === "simple") {
if (process.env.NODE_ENV === "development" && !hasWarnedSimpleLayout) {
hasWarnedSimpleLayout = true;
console.warn(
"⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.",
logBuildWarning(
"The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.",
);
}
return "simple";
Expand Down Expand Up @@ -151,9 +154,11 @@ export function setupArkEnv(

if (!schemaPath || !exists) {
throw new Error(
`[ArkEnv] Could not find schema file at ${
options?.schemaPath || "src/env.ts or env.ts"
}. Please specify 'schemaPath' in setupArkEnv options.`,
formatBuildError(
`Could not find schema file at ${
options?.schemaPath || "src/env.ts or env.ts"
}. Please specify 'schemaPath' in setupArkEnv options.`,
),
);
}

Expand Down Expand Up @@ -183,7 +188,9 @@ export function setupArkEnv(
runCodegen(schemaPath, outputPath, resolvedLayout, options?.standard);
} catch (error: unknown) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`[ArkEnv] Failed to generate env.gen.ts: ${message}`);
throw new Error(
formatBuildError(`Failed to generate env.gen.ts: ${message}`),
);
}
}

Expand Down Expand Up @@ -223,7 +230,7 @@ export function setupArkEnv(
});
jiti(fileToEvaluate);
} catch (error: unknown) {
console.error("\n❌ [ArkEnv] Environment validation failed:");
logBuildError("Environment validation failed:");
console.error(error instanceof Error ? error.message : String(error));
console.error("");
process.exit(1);
Expand Down
5 changes: 4 additions & 1 deletion packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
extractServerKeys,
extractSharedKeys,
findSchemaPath,
formatBuildError,
resolveLayout,
} from "@arkenv/build";
import { defineNuxtModule } from "@nuxt/kit";
Expand Down Expand Up @@ -124,7 +125,9 @@ const module: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({

if (isServerModule) {
throw new Error(
"[ArkEnv] Importing server-only environment schema on the client is not allowed!",
formatBuildError(
"Importing server-only environment schema on the client is not allowed!",
),
);
}
},
Expand Down
Loading