@arkenv/nextjs 0.1.3 → 0.1.5

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/config.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`);c=s(c,1);let l=require(`node:path`);l=s(l,1);let u=require(`node:url`),d=require(`@arkenv/build`),f=require(`jiti`),p=!1;function m(e){return e===`simple`?(process.env.NODE_ENV===`development`&&!p&&(p=!0,console.warn(`⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.`)),`simple`):e===`flat`?`simple`:e}function h(e,t){let n=e?.schemaPath?l.default.resolve(e.schemaPath):(0,d.findSchemaPath)(),r=!1;if(n)if(c.default.existsSync(n))r=!0;else{let e=l.default.extname(n);if(e){let t=n.slice(0,-e.length);c.default.existsSync(t)&&(r=!0)}}if(!n||!r)throw Error(`[ArkEnv] Could not find schema file at ${e?.schemaPath||`src/env.ts or env.ts`}. Please specify 'schemaPath' in setupArkEnv options.`);let{layout:i,baseDir:a}=(0,d.resolveLayout)(n,m(e?.layout)),o=i===`strict`&&a?a:l.default.dirname(n),s=l.default.join(o,`generated`,`env.gen.ts`),p=e?.outputPath?l.default.resolve(e.outputPath):s,h=e?.codegen??!0;if(h)try{_(n,p,i)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[ArkEnv] Failed to generate env.gen.ts: ${t}`)}if(e?.validate??!0)try{globalThis.__arkenv_force_server__=!0;let e=i===`strict`&&a?l.default.join(a,`server.ts`):n,r=typeof __filename<`u`?__filename:require(`url`).pathToFileURL(__filename).href?(0,u.fileURLToPath)(require(`url`).pathToFileURL(__filename).href):``,o=l.default.dirname(r),s=c.default.existsSync(l.default.join(o,`shared.ts`))?l.default.join(o,`shared.ts`):l.default.join(o,`shared.js`);(0,f.createJiti)(e,{moduleCache:!1,fsCache:!1,tsconfigPaths:!0,alias:{"server-only":s,"./script":s,"./script.tsx":s,...t?._jitiAliases}})(e)}catch(e){console.error(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`);c=s(c,1);let l=require(`node:path`);l=s(l,1);let u=require(`node:url`),d=require(`@arkenv/build`),f=require(`jiti`),p=!1;function m(e){return e===`simple`?(process.env.NODE_ENV===`development`&&!p&&(p=!0,console.warn(`⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.`)),`simple`):e===`flat`?`simple`:e}function h(e,t){let n=e?.schemaPath?l.default.resolve(e.schemaPath):(0,d.findSchemaPath)(),r=!1;if(n)if(c.default.existsSync(n))r=!0;else{let e=l.default.extname(n);if(e){let t=n.slice(0,-e.length);c.default.existsSync(t)&&(r=!0)}}if(!n||!r)throw Error((0,d.formatMissingSchemaError)({schemaPath:e?.schemaPath,optionsHint:`setupArkEnv options`}));let{layout:i,baseDir:a}=(0,d.resolveLayout)(n,m(e?.layout)),o=i===`strict`&&a?a:l.default.dirname(n),s=l.default.join(o,`generated`,`env.gen.ts`),p=e?.outputPath?l.default.resolve(e.outputPath):s,h=e?.codegen??!0;if(h)try{_(n,p,i)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[ArkEnv] Failed to generate env.gen.ts: ${t}`)}if(e?.validate??!0)try{globalThis.__arkenv_force_server__=!0;let e=i===`strict`&&a?l.default.join(a,`server.ts`):n,r=typeof __filename<`u`?__filename:require(`url`).pathToFileURL(__filename).href?(0,u.fileURLToPath)(require(`url`).pathToFileURL(__filename).href):``,o=l.default.dirname(r),s=c.default.existsSync(l.default.join(o,`shared.ts`))?l.default.join(o,`shared.ts`):l.default.join(o,`shared.js`);(0,f.createJiti)(e,{moduleCache:!1,fsCache:!1,tsconfigPaths:!0,alias:{"server-only":s,"./script":s,"./script.tsx":s,...t?._jitiAliases}})(e)}catch(e){console.error(`
2
2
  ❌ [ArkEnv] Environment validation failed:`),console.error(e instanceof Error?e.message:String(e)),console.error(``),process.exit(1)}finally{delete globalThis.__arkenv_force_server__}(process.env.NODE_ENV===`development`||process.env.NEXT_PHASE===`phase-development-server`)&&h&&(0,d.watchSchema)(i===`strict`&&a?[l.default.join(a,`internal`,`shared.ts`),l.default.join(a,`client.ts`),l.default.join(a,`server.ts`)].filter(c.default.existsSync):[n],()=>{_(n,p,i)})}function g(e,t){return h(t),e}function _(e,t,n){let{layout:r,baseDir:i}=(0,d.resolveLayout)(e,m(n)),a=``;if(r===`strict`){let e=l.default.join(i,`client.ts`),t=l.default.join(i,`internal`,`shared.ts`),n=c.default.existsSync(e)?c.default.readFileSync(e,`utf-8`):``,r=c.default.existsSync(t)?c.default.readFileSync(t,`utf-8`):``;a=w((0,d.extractClientKeys)(n),(0,d.extractSharedKeys)(r))}else{let{clientKeys:t,sharedKeys:n,isLegacy:r}=v(c.default.readFileSync(e,`utf-8`));a=r?S(t,n):C(t,n)}let o=l.default.dirname(t);c.default.existsSync(o)||c.default.mkdirSync(o,{recursive:!0});let s=!0;c.default.existsSync(t)&&c.default.readFileSync(t,`utf-8`)===a&&(s=!1),s&&c.default.writeFileSync(t,a,`utf-8`)}function v(e){return(0,d.extractKeys)(e,`NEXT_PUBLIC_`)}function y(e,t){return Array.from(new Set([...e,...t])).map(e=>`\t\t\t${e}: typeof window !== "undefined" ? (globalThis as any).__arkenv_env__?.${e} ?? process.env.${e} : process.env.${e},`).join(`
3
3
  `)}const b=`/* eslint-disable */
4
4
  // biome-ignore format: auto-generated
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs","names":["path","fs"],"sources":["../src/config.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\textractKeys as coreExtractKeys,\n\textractClientKeys,\n\textractSharedKeys,\n\tfindSchemaPath,\n\tresolveLayout,\n\twatchSchema,\n} from \"@arkenv/build\";\nimport { createJiti } from \"jiti\";\n\nexport { extractClientKeys, extractSharedKeys };\n\nlet hasWarnedSimpleLayout = false;\n\nfunction normalizeLayout(\n\tlayout: ArkEnvConfigOptions[\"layout\"],\n): \"simple\" | \"strict\" | undefined {\n\tif (layout === \"simple\") {\n\t\tif (process.env.NODE_ENV === \"development\" && !hasWarnedSimpleLayout) {\n\t\t\thasWarnedSimpleLayout = true;\n\t\t\tconsole.warn(\n\t\t\t\t\"⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.\",\n\t\t\t);\n\t\t}\n\t\treturn \"simple\";\n\t}\n\tif (layout === \"flat\") {\n\t\treturn \"simple\";\n\t}\n\treturn layout;\n}\n\n/**\n * Configuration options for the ArkEnv Next.js integration.\n *\n * @example\n * ```ts\n * const configOptions: ArkEnvConfigOptions = {\n * schemaPath: \"./src/env.ts\",\n * outputPath: \"./src/generated/env.gen.ts\"\n * };\n * ```\n */\nexport type ArkEnvConfigOptions = {\n\t/**\n\t * Specify the path to the schema definition file.\n\t *\n\t * Defaults to searching for `\"src/env.ts\"` or `\"env.ts\"` in the project root.\n\t *\n\t * @default \"src/env.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * schemaPath: \"./src/env.ts\"\n\t * });\n\t * ```\n\t */\n\tschemaPath?: string;\n\n\t/**\n\t * Specify the path where the generated file (`env.gen.ts`) should be written.\n\t *\n\t * Defaults to `\"generated/env.gen.ts\"` in the same directory as the schema file.\n\t *\n\t * @default \"[schemaDirectory]/generated/env.gen.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * outputPath: \"./src/generated/env.gen.ts\"\n\t * });\n\t * ```\n\t */\n\toutputPath?: string;\n\n\t/**\n\t * Specify the configuration layout.\n\t *\n\t * - `\"flat\"` (default): A single `env.ts` schema file.\n\t * - `\"strict\"`: A 3-file split schema layout (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`).\n\t *\n\t * @default \"flat\"\n\t */\n\tlayout?:\n\t\t| \"flat\"\n\t\t| \"strict\"\n\t\t/** @deprecated Use `\"flat\"` instead. `\"simple\"` will be removed in the next major version. */\n\t\t| \"simple\";\n\n\t/**\n\t * Enable or disable build-time environment variable validation during build/dev startup.\n\t *\n\t * @default true\n\t */\n\tvalidate?: boolean;\n\n\t/**\n\t * Enable or disable automatic code generation of the `env.gen.ts` file.\n\t *\n\t * @default true\n\t */\n\tcodegen?: boolean;\n};\n\n/**\n * Run ArkEnv codegen and setup without wrapping nextConfig.\n *\n * @param options Optional configuration paths for schema and output files\n * @param internalOptions Optional configuration for internal testing hooks\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function setupArkEnv(\n\toptions?: ArkEnvConfigOptions,\n\tinternalOptions?: { _jitiAliases?: Record<string, string> },\n): void {\n\t// 1. Locate the env.ts schema file or strict schema directory\n\tconst schemaPath = options?.schemaPath\n\t\t? path.resolve(options.schemaPath)\n\t\t: findSchemaPath();\n\n\t// Auto-detect layout if not specified\n\tlet exists = false;\n\tif (schemaPath) {\n\t\tif (fs.existsSync(schemaPath)) {\n\t\t\texists = true;\n\t\t} else {\n\t\t\tconst ext = path.extname(schemaPath);\n\t\t\tif (ext) {\n\t\t\t\tconst baseWithoutExt = schemaPath.slice(0, -ext.length);\n\t\t\t\tif (fs.existsSync(baseWithoutExt)) {\n\t\t\t\t\texists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!schemaPath || !exists) {\n\t\tthrow new Error(\n\t\t\t`[ArkEnv] Could not find schema file at ${\n\t\t\t\toptions?.schemaPath || \"src/env.ts or env.ts\"\n\t\t\t}. Please specify 'schemaPath' in setupArkEnv options.`,\n\t\t);\n\t}\n\n\tconst normalizedLayout = normalizeLayout(options?.layout);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\t// 2. Determine outputPath (defaults to generated/env.gen.ts in the same directory as schemaPath/baseDir)\n\tconst defaultOutputDir =\n\t\tresolvedLayout === \"strict\" && baseDir ? baseDir : path.dirname(schemaPath);\n\tconst defaultOutputPath = path.join(\n\t\tdefaultOutputDir,\n\t\t\"generated\",\n\t\t\"env.gen.ts\",\n\t);\n\tconst outputPath = options?.outputPath\n\t\t? path.resolve(options.outputPath)\n\t\t: defaultOutputPath;\n\n\t// 3. Run initial code generation if enabled\n\tconst codegen = options?.codegen ?? true;\n\tif (codegen) {\n\t\ttry {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`[ArkEnv] Failed to generate env.gen.ts: ${message}`);\n\t\t}\n\t}\n\n\t// 4. Validate schema against environment variables\n\tconst runValidation = options?.validate ?? true;\n\tif (runValidation) {\n\t\ttry {\n\t\t\t(globalThis as any).__arkenv_force_server__ = true;\n\t\t\tconst fileToEvaluate =\n\t\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t\t? path.join(baseDir, \"server.ts\")\n\t\t\t\t\t: schemaPath;\n\n\t\t\tconst filenameForJiti =\n\t\t\t\ttypeof __filename !== \"undefined\"\n\t\t\t\t\t? __filename\n\t\t\t\t\t: typeof import.meta !== \"undefined\" && import.meta.url\n\t\t\t\t\t\t? fileURLToPath(import.meta.url)\n\t\t\t\t\t\t: \"\";\n\t\t\tconst dir = path.dirname(filenameForJiti);\n\t\t\tconst sharedPath = fs.existsSync(path.join(dir, \"shared.ts\"))\n\t\t\t\t? path.join(dir, \"shared.ts\")\n\t\t\t\t: path.join(dir, \"shared.js\");\n\n\t\t\tconst aliases: Record<string, string> = {\n\t\t\t\t\"server-only\": sharedPath,\n\t\t\t\t\"./script\": sharedPath,\n\t\t\t\t\"./script.tsx\": sharedPath,\n\t\t\t\t...internalOptions?._jitiAliases,\n\t\t\t};\n\n\t\t\tconst jiti = createJiti(fileToEvaluate, {\n\t\t\t\tmoduleCache: false,\n\t\t\t\tfsCache: false,\n\t\t\t\ttsconfigPaths: true,\n\t\t\t\talias: aliases,\n\t\t\t});\n\t\t\tjiti(fileToEvaluate);\n\t\t} catch (error: unknown) {\n\t\t\tconsole.error(\"\\n❌ [ArkEnv] Environment validation failed:\");\n\t\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\t\tconsole.error(\"\");\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tdelete (globalThis as any).__arkenv_force_server__;\n\t\t}\n\t}\n\n\t// 5. Initialize development file watcher if in dev mode and codegen is enabled\n\tconst isDev =\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NEXT_PHASE === \"phase-development-server\";\n\tif (isDev && codegen) {\n\t\tconst watchPaths =\n\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t? [\n\t\t\t\t\t\tpath.join(baseDir, \"internal\", \"shared.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"client.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"server.ts\"),\n\t\t\t\t\t].filter(fs.existsSync)\n\t\t\t\t: [schemaPath];\n\t\twatchSchema(watchPaths, () => {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t});\n\t}\n}\n\n/**\n * Wrap a Next.js configuration object to automatically generate the `runtimeEnv` block in `env.gen.ts`.\n *\n * @param nextConfig The Next.js configuration object or function\n * @param options Optional configuration paths for schema and output files\n * @returns The Next.js configuration object unchanged\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function withArkEnv<T>(nextConfig: T, options?: ArkEnvConfigOptions): T {\n\tsetupArkEnv(options);\n\treturn nextConfig;\n}\n\n/**\n * Run code generation to read the schema file and generate the env.gen.ts factory.\n *\n * @param schemaPath The absolute path to the schema file or directory\n * @param outputPath The absolute path to the generated output file\n * @param layoutOption The explicit layout to use; auto-detected from the filesystem when omitted\n * @throws An error if strict layout files are missing when `layoutOption` is `\"strict\"`\n */\nexport function runCodegen(\n\tschemaPath: string,\n\toutputPath: string,\n\tlayoutOption?: ArkEnvConfigOptions[\"layout\"],\n) {\n\tconst normalizedLayout = normalizeLayout(layoutOption);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\tlet generatedCode = \"\";\n\tif (resolvedLayout === \"strict\") {\n\t\tconst clientPath = path.join(baseDir, \"client.ts\");\n\t\tconst sharedPath = path.join(baseDir, \"internal\", \"shared.ts\");\n\n\t\tconst clientContent = fs.existsSync(clientPath)\n\t\t\t? fs.readFileSync(clientPath, \"utf-8\")\n\t\t\t: \"\";\n\t\tconst sharedContent = fs.existsSync(sharedPath)\n\t\t\t? fs.readFileSync(sharedPath, \"utf-8\")\n\t\t\t: \"\";\n\n\t\tconst clientKeys = extractClientKeys(clientContent);\n\t\tconst sharedKeys = extractSharedKeys(sharedContent);\n\n\t\tgeneratedCode = generateClientFactoryCode(clientKeys, sharedKeys);\n\t} else {\n\t\tconst fileContent = fs.readFileSync(schemaPath, \"utf-8\");\n\t\tconst { clientKeys, sharedKeys, isLegacy } = extractKeys(fileContent);\n\t\tif (isLegacy) {\n\t\t\tgeneratedCode = generateFactoryCode(clientKeys, sharedKeys);\n\t\t} else {\n\t\t\tgeneratedCode = generateFlatFactoryCode(clientKeys, sharedKeys);\n\t\t}\n\t}\n\n\t// Ensure parent directory exists\n\tconst outputDir = path.dirname(outputPath);\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\t// Write if changed to avoid unnecessary filesystem/watcher triggers\n\tlet shouldWrite = true;\n\tif (fs.existsSync(outputPath)) {\n\t\tconst existingContent = fs.readFileSync(outputPath, \"utf-8\");\n\t\tif (existingContent === generatedCode) {\n\t\t\tshouldWrite = false;\n\t\t}\n\t}\n\n\tif (shouldWrite) {\n\t\tfs.writeFileSync(outputPath, generatedCode, \"utf-8\");\n\t}\n}\n\n/**\n * Statically extract client and shared keys from the schema content using NEXT_PUBLIC_ prefix.\n *\n * @param content The schema file string content\n * @returns An object containing the extracted client and shared keys\n */\nexport function extractKeys(content: string): {\n\tclientKeys: string[];\n\tsharedKeys: string[];\n\tserverKeys: string[];\n\tisLegacy?: boolean;\n} {\n\treturn coreExtractKeys(content, \"NEXT_PUBLIC_\");\n}\n\n/**\n * Generate the triple-tab indented runtime environment variables mapping.\n */\nfunction generateRuntimeEnvLines(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst allKeys = Array.from(new Set([...clientKeys, ...sharedKeys]));\n\treturn allKeys\n\t\t.map(\n\t\t\t(key) =>\n\t\t\t\t`\\t\\t\\t${key}: typeof window !== \"undefined\" ? (globalThis as any).__arkenv_env__?.${key} ?? process.env.${key} : process.env.${key},`,\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nconst GENERATED_HEADER = `/* eslint-disable */\n// biome-ignore format: auto-generated\n// Generated by ArkEnv. DO NOT EDIT DIRECTLY.\n`;\n\nconst GENERATED_FOOTER = `\nexport default createEnv;\n`;\n\n/**\n * Generate the TypeScript factory code for the tailored createEnv helper.\n *\n * @param clientKeys The client environment variable keys\n * @param sharedKeys The shared environment variable keys\n * @returns The generated TypeScript source code string\n */\nfunction generateFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TServer extends Record<string, any> = {},\n\tconst TClient extends Record<string, any> = {},\n\tconst TShared extends Record<string, any> = {},\n>(options: {\n\tserver?: TServer;\n\tclient?: TClient & {\n\t\t[K in keyof TClient]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t};\n\tshared?: TShared;\n}) {\n\treturn coreCreateEnv({\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any) as any;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the Flat Layout createEnv helper.\n *\n * @remarks\n * **Architecture tripwire:** Do not statically compile the schema here or\n * reference internal-only types (the `$` scope or `MergeExtends`).\n *\n * - **Generic wrapper:** The factory must stay generic because the concrete\n * schema is owned by the user-land `env.ts`.\n * - **Type strategy:** It intentionally returns the full schema type to ensure\n * flawless Server Component autocomplete.\n * - **Security boundary:** Client-side protection is deliberately deferred to\n * the runtime Proxy in `@arkenv/nextjs`, which throws on unauthorized access.\n *\n * 📖 See ADR-0010: Flat layout codegen and type inference strategy\n * (`docs/adr/0010-flat-layout-codegen-type-strategy.md`).\n */\nfunction generateFlatFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\nimport type { type as at, distill } from \"arktype\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, unknown> & { runtimeEnv?: never } = {},\n\tconst TExpose extends keyof TSchema = never,\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema,\n\toptions?: {\n\t\t/**\n\t\t * Custom environment variables to expose to the client bundle.\n\t\t * By default, variables prefixed with \\`NEXT_PUBLIC_\\` and \\`NODE_ENV\\` are exposed automatically.\n\t\t * Use this option to expose custom variables that do not have the \\`NEXT_PUBLIC_\\` prefix.\n\t\t */\n\t\texposeToClient?: readonly TExpose[];\n\t\textends?: [...TExtends];\n\t},\n): Readonly<distill.Out<at.infer<TSchema>>> {\n\t// Types expose the full schema for a great DX on the server; the runtime\n\t// Proxy from \\`@arkenv/nextjs\\` enforces the security boundary by throwing\n\t// when a server-only variable is accessed on the client.\n\tconst env = coreCreateEnv(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n\treturn env as unknown as Readonly<distill.Out<at.infer<TSchema>>>;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the strict-layout `createEnv` helper.\n *\n * Unlike `generateFactoryCode`, this variant imports from `@arkenv/nextjs/client`\n * and exposes a positional-schema signature suited for split-file projects.\n *\n * @param clientKeys The env var keys extracted from `client.ts`\n * @param sharedKeys The env var keys extracted from `internal/shared.ts`\n * @returns The generated TypeScript source code string\n */\nfunction generateClientFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs/client\";\n\nexport { type } from \"@arkenv/nextjs/client\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, any> = {},\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema & {\n\t\t[K in keyof TSchema]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t},\n\toptions?: {\n\t\textends?: [...TExtends];\n\t},\n) {\n\treturn coreCreateEnv<TSchema, TExtends>(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n}\n${GENERATED_FOOTER}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.cjs","names":["path","fs"],"sources":["../src/config.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\textractKeys as coreExtractKeys,\n\textractClientKeys,\n\textractSharedKeys,\n\tfindSchemaPath,\n\tformatMissingSchemaError,\n\tresolveLayout,\n\twatchSchema,\n} from \"@arkenv/build\";\nimport { createJiti } from \"jiti\";\n\nexport { extractClientKeys, extractSharedKeys };\n\nlet hasWarnedSimpleLayout = false;\n\nfunction normalizeLayout(\n\tlayout: ArkEnvConfigOptions[\"layout\"],\n): \"simple\" | \"strict\" | undefined {\n\tif (layout === \"simple\") {\n\t\tif (process.env.NODE_ENV === \"development\" && !hasWarnedSimpleLayout) {\n\t\t\thasWarnedSimpleLayout = true;\n\t\t\tconsole.warn(\n\t\t\t\t\"⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.\",\n\t\t\t);\n\t\t}\n\t\treturn \"simple\";\n\t}\n\tif (layout === \"flat\") {\n\t\treturn \"simple\";\n\t}\n\treturn layout;\n}\n\n/**\n * Configuration options for the ArkEnv Next.js integration.\n *\n * @example\n * ```ts\n * const configOptions: ArkEnvConfigOptions = {\n * schemaPath: \"./src/env.ts\",\n * outputPath: \"./src/generated/env.gen.ts\"\n * };\n * ```\n */\nexport type ArkEnvConfigOptions = {\n\t/**\n\t * Specify the path to the schema definition file.\n\t *\n\t * Defaults to searching for `\"src/env.ts\"` or `\"env.ts\"` in the project root.\n\t *\n\t * @default \"src/env.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * schemaPath: \"./src/env.ts\"\n\t * });\n\t * ```\n\t */\n\tschemaPath?: string;\n\n\t/**\n\t * Specify the path where the generated file (`env.gen.ts`) should be written.\n\t *\n\t * Defaults to `\"generated/env.gen.ts\"` in the same directory as the schema file.\n\t *\n\t * @default \"[schemaDirectory]/generated/env.gen.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * outputPath: \"./src/generated/env.gen.ts\"\n\t * });\n\t * ```\n\t */\n\toutputPath?: string;\n\n\t/**\n\t * Specify the configuration layout.\n\t *\n\t * - `\"flat\"` (default): A single `env.ts` schema file.\n\t * - `\"strict\"`: A split schema layout (`env/client.ts`, `env/server.ts`, and optionally `env/internal/shared.ts`).\n\t *\n\t * @default \"flat\"\n\t */\n\tlayout?:\n\t\t| \"flat\"\n\t\t| \"strict\"\n\t\t/** @deprecated Use `\"flat\"` instead. `\"simple\"` will be removed in the next major version. */\n\t\t| \"simple\";\n\n\t/**\n\t * Enable or disable build-time environment variable validation during build/dev startup.\n\t *\n\t * @default true\n\t */\n\tvalidate?: boolean;\n\n\t/**\n\t * Enable or disable automatic code generation of the `env.gen.ts` file.\n\t *\n\t * @default true\n\t */\n\tcodegen?: boolean;\n};\n\n/**\n * Run ArkEnv codegen and setup without wrapping nextConfig.\n *\n * @param options Optional configuration paths for schema and output files\n * @param internalOptions Optional configuration for internal testing hooks\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function setupArkEnv(\n\toptions?: ArkEnvConfigOptions,\n\tinternalOptions?: { _jitiAliases?: Record<string, string> },\n): void {\n\t// 1. Locate the env.ts schema file or strict schema directory\n\tconst schemaPath = options?.schemaPath\n\t\t? path.resolve(options.schemaPath)\n\t\t: findSchemaPath();\n\n\t// Auto-detect layout if not specified\n\tlet exists = false;\n\tif (schemaPath) {\n\t\tif (fs.existsSync(schemaPath)) {\n\t\t\texists = true;\n\t\t} else {\n\t\t\tconst ext = path.extname(schemaPath);\n\t\t\tif (ext) {\n\t\t\t\tconst baseWithoutExt = schemaPath.slice(0, -ext.length);\n\t\t\t\tif (fs.existsSync(baseWithoutExt)) {\n\t\t\t\t\texists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!schemaPath || !exists) {\n\t\tthrow new Error(\n\t\t\tformatMissingSchemaError({\n\t\t\t\tschemaPath: options?.schemaPath,\n\t\t\t\toptionsHint: \"setupArkEnv options\",\n\t\t\t}),\n\t\t);\n\t}\n\n\tconst normalizedLayout = normalizeLayout(options?.layout);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\t// 2. Determine outputPath (defaults to generated/env.gen.ts in the same directory as schemaPath/baseDir)\n\tconst defaultOutputDir =\n\t\tresolvedLayout === \"strict\" && baseDir ? baseDir : path.dirname(schemaPath);\n\tconst defaultOutputPath = path.join(\n\t\tdefaultOutputDir,\n\t\t\"generated\",\n\t\t\"env.gen.ts\",\n\t);\n\tconst outputPath = options?.outputPath\n\t\t? path.resolve(options.outputPath)\n\t\t: defaultOutputPath;\n\n\t// 3. Run initial code generation if enabled\n\tconst codegen = options?.codegen ?? true;\n\tif (codegen) {\n\t\ttry {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`[ArkEnv] Failed to generate env.gen.ts: ${message}`);\n\t\t}\n\t}\n\n\t// 4. Validate schema against environment variables\n\tconst runValidation = options?.validate ?? true;\n\tif (runValidation) {\n\t\ttry {\n\t\t\t(globalThis as any).__arkenv_force_server__ = true;\n\t\t\tconst fileToEvaluate =\n\t\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t\t? path.join(baseDir, \"server.ts\")\n\t\t\t\t\t: schemaPath;\n\n\t\t\tconst filenameForJiti =\n\t\t\t\ttypeof __filename !== \"undefined\"\n\t\t\t\t\t? __filename\n\t\t\t\t\t: typeof import.meta !== \"undefined\" && import.meta.url\n\t\t\t\t\t\t? fileURLToPath(import.meta.url)\n\t\t\t\t\t\t: \"\";\n\t\t\tconst dir = path.dirname(filenameForJiti);\n\t\t\tconst sharedPath = fs.existsSync(path.join(dir, \"shared.ts\"))\n\t\t\t\t? path.join(dir, \"shared.ts\")\n\t\t\t\t: path.join(dir, \"shared.js\");\n\n\t\t\tconst aliases: Record<string, string> = {\n\t\t\t\t\"server-only\": sharedPath,\n\t\t\t\t\"./script\": sharedPath,\n\t\t\t\t\"./script.tsx\": sharedPath,\n\t\t\t\t...internalOptions?._jitiAliases,\n\t\t\t};\n\n\t\t\tconst jiti = createJiti(fileToEvaluate, {\n\t\t\t\tmoduleCache: false,\n\t\t\t\tfsCache: false,\n\t\t\t\ttsconfigPaths: true,\n\t\t\t\talias: aliases,\n\t\t\t});\n\t\t\tjiti(fileToEvaluate);\n\t\t} catch (error: unknown) {\n\t\t\tconsole.error(\"\\n❌ [ArkEnv] Environment validation failed:\");\n\t\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\t\tconsole.error(\"\");\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tdelete (globalThis as any).__arkenv_force_server__;\n\t\t}\n\t}\n\n\t// 5. Initialize development file watcher if in dev mode and codegen is enabled\n\tconst isDev =\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NEXT_PHASE === \"phase-development-server\";\n\tif (isDev && codegen) {\n\t\tconst watchPaths =\n\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t? [\n\t\t\t\t\t\tpath.join(baseDir, \"internal\", \"shared.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"client.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"server.ts\"),\n\t\t\t\t\t].filter(fs.existsSync)\n\t\t\t\t: [schemaPath];\n\t\twatchSchema(watchPaths, () => {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t});\n\t}\n}\n\n/**\n * Wrap a Next.js configuration object to automatically generate the `runtimeEnv` block in `env.gen.ts`.\n *\n * @param nextConfig The Next.js configuration object or function\n * @param options Optional configuration paths for schema and output files\n * @returns The Next.js configuration object unchanged\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function withArkEnv<T>(nextConfig: T, options?: ArkEnvConfigOptions): T {\n\tsetupArkEnv(options);\n\treturn nextConfig;\n}\n\n/**\n * Run code generation to read the schema file and generate the env.gen.ts factory.\n *\n * @param schemaPath The absolute path to the schema file or directory\n * @param outputPath The absolute path to the generated output file\n * @param layoutOption The explicit layout to use; auto-detected from the filesystem when omitted\n * @throws An error if strict layout files are missing when `layoutOption` is `\"strict\"`\n */\nexport function runCodegen(\n\tschemaPath: string,\n\toutputPath: string,\n\tlayoutOption?: ArkEnvConfigOptions[\"layout\"],\n) {\n\tconst normalizedLayout = normalizeLayout(layoutOption);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\tlet generatedCode = \"\";\n\tif (resolvedLayout === \"strict\") {\n\t\tconst clientPath = path.join(baseDir, \"client.ts\");\n\t\tconst sharedPath = path.join(baseDir, \"internal\", \"shared.ts\");\n\n\t\tconst clientContent = fs.existsSync(clientPath)\n\t\t\t? fs.readFileSync(clientPath, \"utf-8\")\n\t\t\t: \"\";\n\t\tconst sharedContent = fs.existsSync(sharedPath)\n\t\t\t? fs.readFileSync(sharedPath, \"utf-8\")\n\t\t\t: \"\";\n\n\t\tconst clientKeys = extractClientKeys(clientContent);\n\t\tconst sharedKeys = extractSharedKeys(sharedContent);\n\n\t\tgeneratedCode = generateClientFactoryCode(clientKeys, sharedKeys);\n\t} else {\n\t\tconst fileContent = fs.readFileSync(schemaPath, \"utf-8\");\n\t\tconst { clientKeys, sharedKeys, isLegacy } = extractKeys(fileContent);\n\t\tif (isLegacy) {\n\t\t\tgeneratedCode = generateFactoryCode(clientKeys, sharedKeys);\n\t\t} else {\n\t\t\tgeneratedCode = generateFlatFactoryCode(clientKeys, sharedKeys);\n\t\t}\n\t}\n\n\t// Ensure parent directory exists\n\tconst outputDir = path.dirname(outputPath);\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\t// Write if changed to avoid unnecessary filesystem/watcher triggers\n\tlet shouldWrite = true;\n\tif (fs.existsSync(outputPath)) {\n\t\tconst existingContent = fs.readFileSync(outputPath, \"utf-8\");\n\t\tif (existingContent === generatedCode) {\n\t\t\tshouldWrite = false;\n\t\t}\n\t}\n\n\tif (shouldWrite) {\n\t\tfs.writeFileSync(outputPath, generatedCode, \"utf-8\");\n\t}\n}\n\n/**\n * Statically extract client and shared keys from the schema content using NEXT_PUBLIC_ prefix.\n *\n * @param content The schema file string content\n * @returns An object containing the extracted client and shared keys\n */\nexport function extractKeys(content: string): {\n\tclientKeys: string[];\n\tsharedKeys: string[];\n\tserverKeys: string[];\n\tisLegacy?: boolean;\n} {\n\treturn coreExtractKeys(content, \"NEXT_PUBLIC_\");\n}\n\n/**\n * Generate the triple-tab indented runtime environment variables mapping.\n */\nfunction generateRuntimeEnvLines(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst allKeys = Array.from(new Set([...clientKeys, ...sharedKeys]));\n\treturn allKeys\n\t\t.map(\n\t\t\t(key) =>\n\t\t\t\t`\\t\\t\\t${key}: typeof window !== \"undefined\" ? (globalThis as any).__arkenv_env__?.${key} ?? process.env.${key} : process.env.${key},`,\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nconst GENERATED_HEADER = `/* eslint-disable */\n// biome-ignore format: auto-generated\n// Generated by ArkEnv. DO NOT EDIT DIRECTLY.\n`;\n\nconst GENERATED_FOOTER = `\nexport default createEnv;\n`;\n\n/**\n * Generate the TypeScript factory code for the tailored createEnv helper.\n *\n * @param clientKeys The client environment variable keys\n * @param sharedKeys The shared environment variable keys\n * @returns The generated TypeScript source code string\n */\nfunction generateFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TServer extends Record<string, any> = {},\n\tconst TClient extends Record<string, any> = {},\n\tconst TShared extends Record<string, any> = {},\n>(options: {\n\tserver?: TServer;\n\tclient?: TClient & {\n\t\t[K in keyof TClient]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t};\n\tshared?: TShared;\n}) {\n\treturn coreCreateEnv({\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any) as any;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the Flat Layout createEnv helper.\n *\n * @remarks\n * **Architecture tripwire:** Do not statically compile the schema here or\n * reference internal-only types (the `$` scope or `MergeExtends`).\n *\n * - **Generic wrapper:** The factory must stay generic because the concrete\n * schema is owned by the user-land `env.ts`.\n * - **Type strategy:** It intentionally returns the full schema type to ensure\n * flawless Server Component autocomplete.\n * - **Security boundary:** Client-side protection is deliberately deferred to\n * the runtime Proxy in `@arkenv/nextjs`, which throws on unauthorized access.\n *\n * 📖 See ADR-0010: Flat layout codegen and type inference strategy\n * (`docs/adr/0010-flat-layout-codegen-type-strategy.md`).\n */\nfunction generateFlatFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\nimport type { type as at, distill } from \"arktype\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, unknown> & { runtimeEnv?: never } = {},\n\tconst TExpose extends keyof TSchema = never,\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema,\n\toptions?: {\n\t\t/**\n\t\t * Custom environment variables to expose to the client bundle.\n\t\t * By default, variables prefixed with \\`NEXT_PUBLIC_\\` and \\`NODE_ENV\\` are exposed automatically.\n\t\t * Use this option to expose custom variables that do not have the \\`NEXT_PUBLIC_\\` prefix.\n\t\t */\n\t\texposeToClient?: readonly TExpose[];\n\t\textends?: [...TExtends];\n\t},\n): Readonly<distill.Out<at.infer<TSchema>>> {\n\t// Types expose the full schema for a great DX on the server; the runtime\n\t// Proxy from \\`@arkenv/nextjs\\` enforces the security boundary by throwing\n\t// when a server-only variable is accessed on the client.\n\tconst env = coreCreateEnv(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n\treturn env as unknown as Readonly<distill.Out<at.infer<TSchema>>>;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the strict-layout `createEnv` helper.\n *\n * Unlike `generateFactoryCode`, this variant imports from `@arkenv/nextjs/client`\n * and exposes a positional-schema signature suited for split-file projects.\n *\n * @param clientKeys The env var keys extracted from `client.ts`\n * @param sharedKeys The env var keys extracted from `internal/shared.ts`\n * @returns The generated TypeScript source code string\n */\nfunction generateClientFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs/client\";\n\nexport { type } from \"@arkenv/nextjs/client\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, any> = {},\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema & {\n\t\t[K in keyof TSchema]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t},\n\toptions?: {\n\t\textends?: [...TExtends];\n\t},\n) {\n\treturn coreCreateEnv<TSchema, TExtends>(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n}\n${GENERATED_FOOTER}`;\n}\n"],"mappings":"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"}
package/dist/config.d.cts CHANGED
@@ -45,7 +45,7 @@ type ArkEnvConfigOptions = {
45
45
  * Specify the configuration layout.
46
46
  *
47
47
  * - `"flat"` (default): A single `env.ts` schema file.
48
- * - `"strict"`: A 3-file split schema layout (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`).
48
+ * - `"strict"`: A split schema layout (`env/client.ts`, `env/server.ts`, and optionally `env/internal/shared.ts`).
49
49
  *
50
50
  * @default "flat"
51
51
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":";;;;AA8CA;;;;;;;;;;KAAY,mBAAA;EAmEI;;;;;;;;;;;AAuIhB;;EA5LC,UAAA;EA4LyC;;;;;;;;;;;;;EA7KzC,UAAA;EA0LyB;;;;;;;;EAhLzB,MAAA,qBAgPe;;;;;;EArOf,QAAA;EAyOA;;;;;EAlOA,OAAA;AAAA;;;;;;;;iBAUe,WAAA,CACf,OAAA,GAAU,mBAAA,EACV,eAAA;EAAoB,YAAA,GAAe,MAAA;AAAA;;;;;;;;;iBAqIpB,UAAA,GAAA,CAAc,UAAA,EAAY,CAAA,EAAG,OAAA,GAAU,mBAAA,GAAsB,CAAA;;;;;;;;;iBAa7D,UAAA,CACf,UAAA,UACA,UAAA,UACA,YAAA,GAAe,mBAAA;;;;;;;iBA6DA,WAAA,CAAY,OAAA;EAC3B,UAAA;EACA,UAAA;EACA,UAAA;EACA,QAAA;AAAA"}
1
+ {"version":3,"file":"config.d.cts","names":[],"sources":["../src/config.ts"],"mappings":";;;;AA+CA;;;;;;;;;;KAAY,mBAAA;EAmEI;;;;;;;;;;;AAwIhB;;EA7LC,UAAA;EA6LyC;;;;;;;;;;;;;EA9KzC,UAAA;EA2LyB;;;;;;;;EAjLzB,MAAA,qBAiPe;;;;;;EAtOf,QAAA;EA0OA;;;;;EAnOA,OAAA;AAAA;;;;;;;;iBAUe,WAAA,CACf,OAAA,GAAU,mBAAA,EACV,eAAA;EAAoB,YAAA,GAAe,MAAA;AAAA;;;;;;;;;iBAsIpB,UAAA,GAAA,CAAc,UAAA,EAAY,CAAA,EAAG,OAAA,GAAU,mBAAA,GAAsB,CAAA;;;;;;;;;iBAa7D,UAAA,CACf,UAAA,UACA,UAAA,UACA,YAAA,GAAe,mBAAA;;;;;;;iBA6DA,WAAA,CAAY,OAAA;EAC3B,UAAA;EACA,UAAA;EACA,UAAA;EACA,QAAA;AAAA"}
package/dist/config.d.ts CHANGED
@@ -45,7 +45,7 @@ type ArkEnvConfigOptions = {
45
45
  * Specify the configuration layout.
46
46
  *
47
47
  * - `"flat"` (default): A single `env.ts` schema file.
48
- * - `"strict"`: A 3-file split schema layout (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`).
48
+ * - `"strict"`: A split schema layout (`env/client.ts`, `env/server.ts`, and optionally `env/internal/shared.ts`).
49
49
  *
50
50
  * @default "flat"
51
51
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;;AA8CA;;;;;;;;;;KAAY,mBAAA;EAmEI;;;;;;;;;;;AAuIhB;;EA5LC,UAAA;EA4LyC;;;;;;;;;;;;;EA7KzC,UAAA;EA0LyB;;;;;;;;EAhLzB,MAAA,qBAgPe;;;;;;EArOf,QAAA;EAyOA;;;;;EAlOA,OAAA;AAAA;;;;;;;;iBAUe,WAAA,CACf,OAAA,GAAU,mBAAA,EACV,eAAA;EAAoB,YAAA,GAAe,MAAA;AAAA;;;;;;;;;iBAqIpB,UAAA,GAAA,CAAc,UAAA,EAAY,CAAA,EAAG,OAAA,GAAU,mBAAA,GAAsB,CAAA;;;;;;;;;iBAa7D,UAAA,CACf,UAAA,UACA,UAAA,UACA,YAAA,GAAe,mBAAA;;;;;;;iBA6DA,WAAA,CAAY,OAAA;EAC3B,UAAA;EACA,UAAA;EACA,UAAA;EACA,QAAA;AAAA"}
1
+ {"version":3,"file":"config.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;;AA+CA;;;;;;;;;;KAAY,mBAAA;EAmEI;;;;;;;;;;;AAwIhB;;EA7LC,UAAA;EA6LyC;;;;;;;;;;;;;EA9KzC,UAAA;EA2LyB;;;;;;;;EAjLzB,MAAA,qBAiPe;;;;;;EAtOf,QAAA;EA0OA;;;;;EAnOA,OAAA;AAAA;;;;;;;;iBAUe,WAAA,CACf,OAAA,GAAU,mBAAA,EACV,eAAA;EAAoB,YAAA,GAAe,MAAA;AAAA;;;;;;;;;iBAsIpB,UAAA,GAAA,CAAc,UAAA,EAAY,CAAA,EAAG,OAAA,GAAU,mBAAA,GAAsB,CAAA;;;;;;;;;iBAa7D,UAAA,CACf,UAAA,UACA,UAAA,UACA,YAAA,GAAe,mBAAA;;;;;;;iBA6DA,WAAA,CAAY,OAAA;EAC3B,UAAA;EACA,UAAA;EACA,UAAA;EACA,QAAA;AAAA"}
package/dist/config.js CHANGED
@@ -1,11 +1,11 @@
1
- import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import{extractClientKeys as r,extractKeys as i,extractSharedKeys as a,findSchemaPath as o,resolveLayout as s,watchSchema as c}from"@arkenv/build";import{createJiti as l}from"jiti";let u=!1;function d(e){return e===`simple`?(process.env.NODE_ENV===`development`&&!u&&(u=!0,console.warn(`⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.`)),`simple`):e===`flat`?`simple`:e}function f(r,i){let a=r?.schemaPath?t.resolve(r.schemaPath):o(),u=!1;if(a)if(e.existsSync(a))u=!0;else{let n=t.extname(a);if(n){let t=a.slice(0,-n.length);e.existsSync(t)&&(u=!0)}}if(!a||!u)throw Error(`[ArkEnv] Could not find schema file at ${r?.schemaPath||`src/env.ts or env.ts`}. Please specify 'schemaPath' in setupArkEnv options.`);let{layout:f,baseDir:p}=s(a,d(r?.layout)),h=f===`strict`&&p?p:t.dirname(a),g=t.join(h,`generated`,`env.gen.ts`),_=r?.outputPath?t.resolve(r.outputPath):g,v=r?.codegen??!0;if(v)try{m(a,_,f)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[ArkEnv] Failed to generate env.gen.ts: ${t}`)}if(r?.validate??!0)try{globalThis.__arkenv_force_server__=!0;let r=f===`strict`&&p?t.join(p,`server.ts`):a,o=typeof __filename<`u`?__filename:import.meta.url?n(import.meta.url):``,s=t.dirname(o),c=e.existsSync(t.join(s,`shared.ts`))?t.join(s,`shared.ts`):t.join(s,`shared.js`);l(r,{moduleCache:!1,fsCache:!1,tsconfigPaths:!0,alias:{"server-only":c,"./script":c,"./script.tsx":c,...i?._jitiAliases}})(r)}catch(e){console.error(`
2
- ❌ [ArkEnv] Environment validation failed:`),console.error(e instanceof Error?e.message:String(e)),console.error(``),process.exit(1)}finally{delete globalThis.__arkenv_force_server__}(process.env.NODE_ENV===`development`||process.env.NEXT_PHASE===`phase-development-server`)&&v&&c(f===`strict`&&p?[t.join(p,`internal`,`shared.ts`),t.join(p,`client.ts`),t.join(p,`server.ts`)].filter(e.existsSync):[a],()=>{m(a,_,f)})}function p(e,t){return f(t),e}function m(n,i,o){let{layout:c,baseDir:l}=s(n,d(o)),u=``;if(c===`strict`){let n=t.join(l,`client.ts`),i=t.join(l,`internal`,`shared.ts`),o=e.existsSync(n)?e.readFileSync(n,`utf-8`):``,s=e.existsSync(i)?e.readFileSync(i,`utf-8`):``;u=x(r(o),a(s))}else{let{clientKeys:t,sharedKeys:r,isLegacy:i}=h(e.readFileSync(n,`utf-8`));u=i?y(t,r):b(t,r)}let f=t.dirname(i);e.existsSync(f)||e.mkdirSync(f,{recursive:!0});let p=!0;e.existsSync(i)&&e.readFileSync(i,`utf-8`)===u&&(p=!1),p&&e.writeFileSync(i,u,`utf-8`)}function h(e){return i(e,`NEXT_PUBLIC_`)}function g(e,t){return Array.from(new Set([...e,...t])).map(e=>`\t\t\t${e}: typeof window !== "undefined" ? (globalThis as any).__arkenv_env__?.${e} ?? process.env.${e} : process.env.${e},`).join(`
3
- `)}const _=`/* eslint-disable */
1
+ import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import{extractClientKeys as r,extractKeys as i,extractSharedKeys as a,findSchemaPath as o,formatMissingSchemaError as s,resolveLayout as c,watchSchema as l}from"@arkenv/build";import{createJiti as u}from"jiti";let d=!1;function f(e){return e===`simple`?(process.env.NODE_ENV===`development`&&!d&&(d=!0,console.warn(`⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.`)),`simple`):e===`flat`?`simple`:e}function p(r,i){let a=r?.schemaPath?t.resolve(r.schemaPath):o(),d=!1;if(a)if(e.existsSync(a))d=!0;else{let n=t.extname(a);if(n){let t=a.slice(0,-n.length);e.existsSync(t)&&(d=!0)}}if(!a||!d)throw Error(s({schemaPath:r?.schemaPath,optionsHint:`setupArkEnv options`}));let{layout:p,baseDir:m}=c(a,f(r?.layout)),g=p===`strict`&&m?m:t.dirname(a),_=t.join(g,`generated`,`env.gen.ts`),v=r?.outputPath?t.resolve(r.outputPath):_,y=r?.codegen??!0;if(y)try{h(a,v,p)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[ArkEnv] Failed to generate env.gen.ts: ${t}`)}if(r?.validate??!0)try{globalThis.__arkenv_force_server__=!0;let r=p===`strict`&&m?t.join(m,`server.ts`):a,o=typeof __filename<`u`?__filename:import.meta.url?n(import.meta.url):``,s=t.dirname(o),c=e.existsSync(t.join(s,`shared.ts`))?t.join(s,`shared.ts`):t.join(s,`shared.js`);u(r,{moduleCache:!1,fsCache:!1,tsconfigPaths:!0,alias:{"server-only":c,"./script":c,"./script.tsx":c,...i?._jitiAliases}})(r)}catch(e){console.error(`
2
+ ❌ [ArkEnv] Environment validation failed:`),console.error(e instanceof Error?e.message:String(e)),console.error(``),process.exit(1)}finally{delete globalThis.__arkenv_force_server__}(process.env.NODE_ENV===`development`||process.env.NEXT_PHASE===`phase-development-server`)&&y&&l(p===`strict`&&m?[t.join(m,`internal`,`shared.ts`),t.join(m,`client.ts`),t.join(m,`server.ts`)].filter(e.existsSync):[a],()=>{h(a,v,p)})}function m(e,t){return p(t),e}function h(n,i,o){let{layout:s,baseDir:l}=c(n,f(o)),u=``;if(s===`strict`){let n=t.join(l,`client.ts`),i=t.join(l,`internal`,`shared.ts`),o=e.existsSync(n)?e.readFileSync(n,`utf-8`):``,s=e.existsSync(i)?e.readFileSync(i,`utf-8`):``;u=S(r(o),a(s))}else{let{clientKeys:t,sharedKeys:r,isLegacy:i}=g(e.readFileSync(n,`utf-8`));u=i?b(t,r):x(t,r)}let d=t.dirname(i);e.existsSync(d)||e.mkdirSync(d,{recursive:!0});let p=!0;e.existsSync(i)&&e.readFileSync(i,`utf-8`)===u&&(p=!1),p&&e.writeFileSync(i,u,`utf-8`)}function g(e){return i(e,`NEXT_PUBLIC_`)}function _(e,t){return Array.from(new Set([...e,...t])).map(e=>`\t\t\t${e}: typeof window !== "undefined" ? (globalThis as any).__arkenv_env__?.${e} ?? process.env.${e} : process.env.${e},`).join(`
3
+ `)}const v=`/* eslint-disable */
4
4
  // biome-ignore format: auto-generated
5
5
  // Generated by ArkEnv. DO NOT EDIT DIRECTLY.
6
- `,v=`
6
+ `,y=`
7
7
  export default createEnv;
8
- `;function y(e,t){return`${_}
8
+ `;function b(e,t){return`${v}
9
9
  import { createEnv as coreCreateEnv } from "@arkenv/nextjs";
10
10
 
11
11
  export { type } from "@arkenv/nextjs";
@@ -24,11 +24,11 @@ export function createEnv<
24
24
  return coreCreateEnv({
25
25
  ...options,
26
26
  runtimeEnv: {
27
- ${g(e,t)}
27
+ ${_(e,t)}
28
28
  },
29
29
  } as any) as any;
30
30
  }
31
- ${v}`}function b(e,t){return`${_}
31
+ ${y}`}function x(e,t){return`${v}
32
32
  import { createEnv as coreCreateEnv } from "@arkenv/nextjs";
33
33
  import type { type as at, distill } from "arktype";
34
34
 
@@ -56,12 +56,12 @@ export function createEnv<
56
56
  const env = coreCreateEnv(schema as any, {
57
57
  ...options,
58
58
  runtimeEnv: {
59
- ${g(e,t)}
59
+ ${_(e,t)}
60
60
  },
61
61
  } as any);
62
62
  return env as unknown as Readonly<distill.Out<at.infer<TSchema>>>;
63
63
  }
64
- ${v}`}function x(e,t){return`${_}
64
+ ${y}`}function S(e,t){return`${v}
65
65
  import { createEnv as coreCreateEnv } from "@arkenv/nextjs/client";
66
66
 
67
67
  export { type } from "@arkenv/nextjs/client";
@@ -80,9 +80,9 @@ export function createEnv<
80
80
  return coreCreateEnv<TSchema, TExtends>(schema as any, {
81
81
  ...options,
82
82
  runtimeEnv: {
83
- ${g(e,t)}
83
+ ${_(e,t)}
84
84
  },
85
85
  } as any);
86
86
  }
87
- ${v}`}export{r as extractClientKeys,h as extractKeys,a as extractSharedKeys,m as runCodegen,f as setupArkEnv,p as withArkEnv};
87
+ ${y}`}export{r as extractClientKeys,g as extractKeys,a as extractSharedKeys,h as runCodegen,p as setupArkEnv,m as withArkEnv};
88
88
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":["coreExtractKeys"],"sources":["../src/config.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\textractKeys as coreExtractKeys,\n\textractClientKeys,\n\textractSharedKeys,\n\tfindSchemaPath,\n\tresolveLayout,\n\twatchSchema,\n} from \"@arkenv/build\";\nimport { createJiti } from \"jiti\";\n\nexport { extractClientKeys, extractSharedKeys };\n\nlet hasWarnedSimpleLayout = false;\n\nfunction normalizeLayout(\n\tlayout: ArkEnvConfigOptions[\"layout\"],\n): \"simple\" | \"strict\" | undefined {\n\tif (layout === \"simple\") {\n\t\tif (process.env.NODE_ENV === \"development\" && !hasWarnedSimpleLayout) {\n\t\t\thasWarnedSimpleLayout = true;\n\t\t\tconsole.warn(\n\t\t\t\t\"⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.\",\n\t\t\t);\n\t\t}\n\t\treturn \"simple\";\n\t}\n\tif (layout === \"flat\") {\n\t\treturn \"simple\";\n\t}\n\treturn layout;\n}\n\n/**\n * Configuration options for the ArkEnv Next.js integration.\n *\n * @example\n * ```ts\n * const configOptions: ArkEnvConfigOptions = {\n * schemaPath: \"./src/env.ts\",\n * outputPath: \"./src/generated/env.gen.ts\"\n * };\n * ```\n */\nexport type ArkEnvConfigOptions = {\n\t/**\n\t * Specify the path to the schema definition file.\n\t *\n\t * Defaults to searching for `\"src/env.ts\"` or `\"env.ts\"` in the project root.\n\t *\n\t * @default \"src/env.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * schemaPath: \"./src/env.ts\"\n\t * });\n\t * ```\n\t */\n\tschemaPath?: string;\n\n\t/**\n\t * Specify the path where the generated file (`env.gen.ts`) should be written.\n\t *\n\t * Defaults to `\"generated/env.gen.ts\"` in the same directory as the schema file.\n\t *\n\t * @default \"[schemaDirectory]/generated/env.gen.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * outputPath: \"./src/generated/env.gen.ts\"\n\t * });\n\t * ```\n\t */\n\toutputPath?: string;\n\n\t/**\n\t * Specify the configuration layout.\n\t *\n\t * - `\"flat\"` (default): A single `env.ts` schema file.\n\t * - `\"strict\"`: A 3-file split schema layout (`env/internal/shared.ts`, `env/client.ts`, `env/server.ts`).\n\t *\n\t * @default \"flat\"\n\t */\n\tlayout?:\n\t\t| \"flat\"\n\t\t| \"strict\"\n\t\t/** @deprecated Use `\"flat\"` instead. `\"simple\"` will be removed in the next major version. */\n\t\t| \"simple\";\n\n\t/**\n\t * Enable or disable build-time environment variable validation during build/dev startup.\n\t *\n\t * @default true\n\t */\n\tvalidate?: boolean;\n\n\t/**\n\t * Enable or disable automatic code generation of the `env.gen.ts` file.\n\t *\n\t * @default true\n\t */\n\tcodegen?: boolean;\n};\n\n/**\n * Run ArkEnv codegen and setup without wrapping nextConfig.\n *\n * @param options Optional configuration paths for schema and output files\n * @param internalOptions Optional configuration for internal testing hooks\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function setupArkEnv(\n\toptions?: ArkEnvConfigOptions,\n\tinternalOptions?: { _jitiAliases?: Record<string, string> },\n): void {\n\t// 1. Locate the env.ts schema file or strict schema directory\n\tconst schemaPath = options?.schemaPath\n\t\t? path.resolve(options.schemaPath)\n\t\t: findSchemaPath();\n\n\t// Auto-detect layout if not specified\n\tlet exists = false;\n\tif (schemaPath) {\n\t\tif (fs.existsSync(schemaPath)) {\n\t\t\texists = true;\n\t\t} else {\n\t\t\tconst ext = path.extname(schemaPath);\n\t\t\tif (ext) {\n\t\t\t\tconst baseWithoutExt = schemaPath.slice(0, -ext.length);\n\t\t\t\tif (fs.existsSync(baseWithoutExt)) {\n\t\t\t\t\texists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!schemaPath || !exists) {\n\t\tthrow new Error(\n\t\t\t`[ArkEnv] Could not find schema file at ${\n\t\t\t\toptions?.schemaPath || \"src/env.ts or env.ts\"\n\t\t\t}. Please specify 'schemaPath' in setupArkEnv options.`,\n\t\t);\n\t}\n\n\tconst normalizedLayout = normalizeLayout(options?.layout);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\t// 2. Determine outputPath (defaults to generated/env.gen.ts in the same directory as schemaPath/baseDir)\n\tconst defaultOutputDir =\n\t\tresolvedLayout === \"strict\" && baseDir ? baseDir : path.dirname(schemaPath);\n\tconst defaultOutputPath = path.join(\n\t\tdefaultOutputDir,\n\t\t\"generated\",\n\t\t\"env.gen.ts\",\n\t);\n\tconst outputPath = options?.outputPath\n\t\t? path.resolve(options.outputPath)\n\t\t: defaultOutputPath;\n\n\t// 3. Run initial code generation if enabled\n\tconst codegen = options?.codegen ?? true;\n\tif (codegen) {\n\t\ttry {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`[ArkEnv] Failed to generate env.gen.ts: ${message}`);\n\t\t}\n\t}\n\n\t// 4. Validate schema against environment variables\n\tconst runValidation = options?.validate ?? true;\n\tif (runValidation) {\n\t\ttry {\n\t\t\t(globalThis as any).__arkenv_force_server__ = true;\n\t\t\tconst fileToEvaluate =\n\t\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t\t? path.join(baseDir, \"server.ts\")\n\t\t\t\t\t: schemaPath;\n\n\t\t\tconst filenameForJiti =\n\t\t\t\ttypeof __filename !== \"undefined\"\n\t\t\t\t\t? __filename\n\t\t\t\t\t: typeof import.meta !== \"undefined\" && import.meta.url\n\t\t\t\t\t\t? fileURLToPath(import.meta.url)\n\t\t\t\t\t\t: \"\";\n\t\t\tconst dir = path.dirname(filenameForJiti);\n\t\t\tconst sharedPath = fs.existsSync(path.join(dir, \"shared.ts\"))\n\t\t\t\t? path.join(dir, \"shared.ts\")\n\t\t\t\t: path.join(dir, \"shared.js\");\n\n\t\t\tconst aliases: Record<string, string> = {\n\t\t\t\t\"server-only\": sharedPath,\n\t\t\t\t\"./script\": sharedPath,\n\t\t\t\t\"./script.tsx\": sharedPath,\n\t\t\t\t...internalOptions?._jitiAliases,\n\t\t\t};\n\n\t\t\tconst jiti = createJiti(fileToEvaluate, {\n\t\t\t\tmoduleCache: false,\n\t\t\t\tfsCache: false,\n\t\t\t\ttsconfigPaths: true,\n\t\t\t\talias: aliases,\n\t\t\t});\n\t\t\tjiti(fileToEvaluate);\n\t\t} catch (error: unknown) {\n\t\t\tconsole.error(\"\\n❌ [ArkEnv] Environment validation failed:\");\n\t\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\t\tconsole.error(\"\");\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tdelete (globalThis as any).__arkenv_force_server__;\n\t\t}\n\t}\n\n\t// 5. Initialize development file watcher if in dev mode and codegen is enabled\n\tconst isDev =\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NEXT_PHASE === \"phase-development-server\";\n\tif (isDev && codegen) {\n\t\tconst watchPaths =\n\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t? [\n\t\t\t\t\t\tpath.join(baseDir, \"internal\", \"shared.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"client.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"server.ts\"),\n\t\t\t\t\t].filter(fs.existsSync)\n\t\t\t\t: [schemaPath];\n\t\twatchSchema(watchPaths, () => {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t});\n\t}\n}\n\n/**\n * Wrap a Next.js configuration object to automatically generate the `runtimeEnv` block in `env.gen.ts`.\n *\n * @param nextConfig The Next.js configuration object or function\n * @param options Optional configuration paths for schema and output files\n * @returns The Next.js configuration object unchanged\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function withArkEnv<T>(nextConfig: T, options?: ArkEnvConfigOptions): T {\n\tsetupArkEnv(options);\n\treturn nextConfig;\n}\n\n/**\n * Run code generation to read the schema file and generate the env.gen.ts factory.\n *\n * @param schemaPath The absolute path to the schema file or directory\n * @param outputPath The absolute path to the generated output file\n * @param layoutOption The explicit layout to use; auto-detected from the filesystem when omitted\n * @throws An error if strict layout files are missing when `layoutOption` is `\"strict\"`\n */\nexport function runCodegen(\n\tschemaPath: string,\n\toutputPath: string,\n\tlayoutOption?: ArkEnvConfigOptions[\"layout\"],\n) {\n\tconst normalizedLayout = normalizeLayout(layoutOption);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\tlet generatedCode = \"\";\n\tif (resolvedLayout === \"strict\") {\n\t\tconst clientPath = path.join(baseDir, \"client.ts\");\n\t\tconst sharedPath = path.join(baseDir, \"internal\", \"shared.ts\");\n\n\t\tconst clientContent = fs.existsSync(clientPath)\n\t\t\t? fs.readFileSync(clientPath, \"utf-8\")\n\t\t\t: \"\";\n\t\tconst sharedContent = fs.existsSync(sharedPath)\n\t\t\t? fs.readFileSync(sharedPath, \"utf-8\")\n\t\t\t: \"\";\n\n\t\tconst clientKeys = extractClientKeys(clientContent);\n\t\tconst sharedKeys = extractSharedKeys(sharedContent);\n\n\t\tgeneratedCode = generateClientFactoryCode(clientKeys, sharedKeys);\n\t} else {\n\t\tconst fileContent = fs.readFileSync(schemaPath, \"utf-8\");\n\t\tconst { clientKeys, sharedKeys, isLegacy } = extractKeys(fileContent);\n\t\tif (isLegacy) {\n\t\t\tgeneratedCode = generateFactoryCode(clientKeys, sharedKeys);\n\t\t} else {\n\t\t\tgeneratedCode = generateFlatFactoryCode(clientKeys, sharedKeys);\n\t\t}\n\t}\n\n\t// Ensure parent directory exists\n\tconst outputDir = path.dirname(outputPath);\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\t// Write if changed to avoid unnecessary filesystem/watcher triggers\n\tlet shouldWrite = true;\n\tif (fs.existsSync(outputPath)) {\n\t\tconst existingContent = fs.readFileSync(outputPath, \"utf-8\");\n\t\tif (existingContent === generatedCode) {\n\t\t\tshouldWrite = false;\n\t\t}\n\t}\n\n\tif (shouldWrite) {\n\t\tfs.writeFileSync(outputPath, generatedCode, \"utf-8\");\n\t}\n}\n\n/**\n * Statically extract client and shared keys from the schema content using NEXT_PUBLIC_ prefix.\n *\n * @param content The schema file string content\n * @returns An object containing the extracted client and shared keys\n */\nexport function extractKeys(content: string): {\n\tclientKeys: string[];\n\tsharedKeys: string[];\n\tserverKeys: string[];\n\tisLegacy?: boolean;\n} {\n\treturn coreExtractKeys(content, \"NEXT_PUBLIC_\");\n}\n\n/**\n * Generate the triple-tab indented runtime environment variables mapping.\n */\nfunction generateRuntimeEnvLines(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst allKeys = Array.from(new Set([...clientKeys, ...sharedKeys]));\n\treturn allKeys\n\t\t.map(\n\t\t\t(key) =>\n\t\t\t\t`\\t\\t\\t${key}: typeof window !== \"undefined\" ? (globalThis as any).__arkenv_env__?.${key} ?? process.env.${key} : process.env.${key},`,\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nconst GENERATED_HEADER = `/* eslint-disable */\n// biome-ignore format: auto-generated\n// Generated by ArkEnv. DO NOT EDIT DIRECTLY.\n`;\n\nconst GENERATED_FOOTER = `\nexport default createEnv;\n`;\n\n/**\n * Generate the TypeScript factory code for the tailored createEnv helper.\n *\n * @param clientKeys The client environment variable keys\n * @param sharedKeys The shared environment variable keys\n * @returns The generated TypeScript source code string\n */\nfunction generateFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TServer extends Record<string, any> = {},\n\tconst TClient extends Record<string, any> = {},\n\tconst TShared extends Record<string, any> = {},\n>(options: {\n\tserver?: TServer;\n\tclient?: TClient & {\n\t\t[K in keyof TClient]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t};\n\tshared?: TShared;\n}) {\n\treturn coreCreateEnv({\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any) as any;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the Flat Layout createEnv helper.\n *\n * @remarks\n * **Architecture tripwire:** Do not statically compile the schema here or\n * reference internal-only types (the `$` scope or `MergeExtends`).\n *\n * - **Generic wrapper:** The factory must stay generic because the concrete\n * schema is owned by the user-land `env.ts`.\n * - **Type strategy:** It intentionally returns the full schema type to ensure\n * flawless Server Component autocomplete.\n * - **Security boundary:** Client-side protection is deliberately deferred to\n * the runtime Proxy in `@arkenv/nextjs`, which throws on unauthorized access.\n *\n * 📖 See ADR-0010: Flat layout codegen and type inference strategy\n * (`docs/adr/0010-flat-layout-codegen-type-strategy.md`).\n */\nfunction generateFlatFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\nimport type { type as at, distill } from \"arktype\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, unknown> & { runtimeEnv?: never } = {},\n\tconst TExpose extends keyof TSchema = never,\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema,\n\toptions?: {\n\t\t/**\n\t\t * Custom environment variables to expose to the client bundle.\n\t\t * By default, variables prefixed with \\`NEXT_PUBLIC_\\` and \\`NODE_ENV\\` are exposed automatically.\n\t\t * Use this option to expose custom variables that do not have the \\`NEXT_PUBLIC_\\` prefix.\n\t\t */\n\t\texposeToClient?: readonly TExpose[];\n\t\textends?: [...TExtends];\n\t},\n): Readonly<distill.Out<at.infer<TSchema>>> {\n\t// Types expose the full schema for a great DX on the server; the runtime\n\t// Proxy from \\`@arkenv/nextjs\\` enforces the security boundary by throwing\n\t// when a server-only variable is accessed on the client.\n\tconst env = coreCreateEnv(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n\treturn env as unknown as Readonly<distill.Out<at.infer<TSchema>>>;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the strict-layout `createEnv` helper.\n *\n * Unlike `generateFactoryCode`, this variant imports from `@arkenv/nextjs/client`\n * and exposes a positional-schema signature suited for split-file projects.\n *\n * @param clientKeys The env var keys extracted from `client.ts`\n * @param sharedKeys The env var keys extracted from `internal/shared.ts`\n * @returns The generated TypeScript source code string\n */\nfunction generateClientFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs/client\";\n\nexport { type } from \"@arkenv/nextjs/client\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, any> = {},\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema & {\n\t\t[K in keyof TSchema]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t},\n\toptions?: {\n\t\textends?: [...TExtends];\n\t},\n) {\n\treturn coreCreateEnv<TSchema, TExtends>(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n}\n${GENERATED_FOOTER}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":["coreExtractKeys"],"sources":["../src/config.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\textractKeys as coreExtractKeys,\n\textractClientKeys,\n\textractSharedKeys,\n\tfindSchemaPath,\n\tformatMissingSchemaError,\n\tresolveLayout,\n\twatchSchema,\n} from \"@arkenv/build\";\nimport { createJiti } from \"jiti\";\n\nexport { extractClientKeys, extractSharedKeys };\n\nlet hasWarnedSimpleLayout = false;\n\nfunction normalizeLayout(\n\tlayout: ArkEnvConfigOptions[\"layout\"],\n): \"simple\" | \"strict\" | undefined {\n\tif (layout === \"simple\") {\n\t\tif (process.env.NODE_ENV === \"development\" && !hasWarnedSimpleLayout) {\n\t\t\thasWarnedSimpleLayout = true;\n\t\t\tconsole.warn(\n\t\t\t\t\"⚠️ [arkenv] The 'simple' layout option is deprecated and will be removed in the next major version. Use 'flat' instead.\",\n\t\t\t);\n\t\t}\n\t\treturn \"simple\";\n\t}\n\tif (layout === \"flat\") {\n\t\treturn \"simple\";\n\t}\n\treturn layout;\n}\n\n/**\n * Configuration options for the ArkEnv Next.js integration.\n *\n * @example\n * ```ts\n * const configOptions: ArkEnvConfigOptions = {\n * schemaPath: \"./src/env.ts\",\n * outputPath: \"./src/generated/env.gen.ts\"\n * };\n * ```\n */\nexport type ArkEnvConfigOptions = {\n\t/**\n\t * Specify the path to the schema definition file.\n\t *\n\t * Defaults to searching for `\"src/env.ts\"` or `\"env.ts\"` in the project root.\n\t *\n\t * @default \"src/env.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * schemaPath: \"./src/env.ts\"\n\t * });\n\t * ```\n\t */\n\tschemaPath?: string;\n\n\t/**\n\t * Specify the path where the generated file (`env.gen.ts`) should be written.\n\t *\n\t * Defaults to `\"generated/env.gen.ts\"` in the same directory as the schema file.\n\t *\n\t * @default \"[schemaDirectory]/generated/env.gen.ts\"\n\t * @example\n\t * ```ts\n\t * export default withArkEnv(nextConfig, {\n\t * outputPath: \"./src/generated/env.gen.ts\"\n\t * });\n\t * ```\n\t */\n\toutputPath?: string;\n\n\t/**\n\t * Specify the configuration layout.\n\t *\n\t * - `\"flat\"` (default): A single `env.ts` schema file.\n\t * - `\"strict\"`: A split schema layout (`env/client.ts`, `env/server.ts`, and optionally `env/internal/shared.ts`).\n\t *\n\t * @default \"flat\"\n\t */\n\tlayout?:\n\t\t| \"flat\"\n\t\t| \"strict\"\n\t\t/** @deprecated Use `\"flat\"` instead. `\"simple\"` will be removed in the next major version. */\n\t\t| \"simple\";\n\n\t/**\n\t * Enable or disable build-time environment variable validation during build/dev startup.\n\t *\n\t * @default true\n\t */\n\tvalidate?: boolean;\n\n\t/**\n\t * Enable or disable automatic code generation of the `env.gen.ts` file.\n\t *\n\t * @default true\n\t */\n\tcodegen?: boolean;\n};\n\n/**\n * Run ArkEnv codegen and setup without wrapping nextConfig.\n *\n * @param options Optional configuration paths for schema and output files\n * @param internalOptions Optional configuration for internal testing hooks\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function setupArkEnv(\n\toptions?: ArkEnvConfigOptions,\n\tinternalOptions?: { _jitiAliases?: Record<string, string> },\n): void {\n\t// 1. Locate the env.ts schema file or strict schema directory\n\tconst schemaPath = options?.schemaPath\n\t\t? path.resolve(options.schemaPath)\n\t\t: findSchemaPath();\n\n\t// Auto-detect layout if not specified\n\tlet exists = false;\n\tif (schemaPath) {\n\t\tif (fs.existsSync(schemaPath)) {\n\t\t\texists = true;\n\t\t} else {\n\t\t\tconst ext = path.extname(schemaPath);\n\t\t\tif (ext) {\n\t\t\t\tconst baseWithoutExt = schemaPath.slice(0, -ext.length);\n\t\t\t\tif (fs.existsSync(baseWithoutExt)) {\n\t\t\t\t\texists = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!schemaPath || !exists) {\n\t\tthrow new Error(\n\t\t\tformatMissingSchemaError({\n\t\t\t\tschemaPath: options?.schemaPath,\n\t\t\t\toptionsHint: \"setupArkEnv options\",\n\t\t\t}),\n\t\t);\n\t}\n\n\tconst normalizedLayout = normalizeLayout(options?.layout);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\t// 2. Determine outputPath (defaults to generated/env.gen.ts in the same directory as schemaPath/baseDir)\n\tconst defaultOutputDir =\n\t\tresolvedLayout === \"strict\" && baseDir ? baseDir : path.dirname(schemaPath);\n\tconst defaultOutputPath = path.join(\n\t\tdefaultOutputDir,\n\t\t\"generated\",\n\t\t\"env.gen.ts\",\n\t);\n\tconst outputPath = options?.outputPath\n\t\t? path.resolve(options.outputPath)\n\t\t: defaultOutputPath;\n\n\t// 3. Run initial code generation if enabled\n\tconst codegen = options?.codegen ?? true;\n\tif (codegen) {\n\t\ttry {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`[ArkEnv] Failed to generate env.gen.ts: ${message}`);\n\t\t}\n\t}\n\n\t// 4. Validate schema against environment variables\n\tconst runValidation = options?.validate ?? true;\n\tif (runValidation) {\n\t\ttry {\n\t\t\t(globalThis as any).__arkenv_force_server__ = true;\n\t\t\tconst fileToEvaluate =\n\t\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t\t? path.join(baseDir, \"server.ts\")\n\t\t\t\t\t: schemaPath;\n\n\t\t\tconst filenameForJiti =\n\t\t\t\ttypeof __filename !== \"undefined\"\n\t\t\t\t\t? __filename\n\t\t\t\t\t: typeof import.meta !== \"undefined\" && import.meta.url\n\t\t\t\t\t\t? fileURLToPath(import.meta.url)\n\t\t\t\t\t\t: \"\";\n\t\t\tconst dir = path.dirname(filenameForJiti);\n\t\t\tconst sharedPath = fs.existsSync(path.join(dir, \"shared.ts\"))\n\t\t\t\t? path.join(dir, \"shared.ts\")\n\t\t\t\t: path.join(dir, \"shared.js\");\n\n\t\t\tconst aliases: Record<string, string> = {\n\t\t\t\t\"server-only\": sharedPath,\n\t\t\t\t\"./script\": sharedPath,\n\t\t\t\t\"./script.tsx\": sharedPath,\n\t\t\t\t...internalOptions?._jitiAliases,\n\t\t\t};\n\n\t\t\tconst jiti = createJiti(fileToEvaluate, {\n\t\t\t\tmoduleCache: false,\n\t\t\t\tfsCache: false,\n\t\t\t\ttsconfigPaths: true,\n\t\t\t\talias: aliases,\n\t\t\t});\n\t\t\tjiti(fileToEvaluate);\n\t\t} catch (error: unknown) {\n\t\t\tconsole.error(\"\\n❌ [ArkEnv] Environment validation failed:\");\n\t\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\t\tconsole.error(\"\");\n\t\t\tprocess.exit(1);\n\t\t} finally {\n\t\t\tdelete (globalThis as any).__arkenv_force_server__;\n\t\t}\n\t}\n\n\t// 5. Initialize development file watcher if in dev mode and codegen is enabled\n\tconst isDev =\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NEXT_PHASE === \"phase-development-server\";\n\tif (isDev && codegen) {\n\t\tconst watchPaths =\n\t\t\tresolvedLayout === \"strict\" && baseDir\n\t\t\t\t? [\n\t\t\t\t\t\tpath.join(baseDir, \"internal\", \"shared.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"client.ts\"),\n\t\t\t\t\t\tpath.join(baseDir, \"server.ts\"),\n\t\t\t\t\t].filter(fs.existsSync)\n\t\t\t\t: [schemaPath];\n\t\twatchSchema(watchPaths, () => {\n\t\t\trunCodegen(schemaPath, outputPath, resolvedLayout);\n\t\t});\n\t}\n}\n\n/**\n * Wrap a Next.js configuration object to automatically generate the `runtimeEnv` block in `env.gen.ts`.\n *\n * @param nextConfig The Next.js configuration object or function\n * @param options Optional configuration paths for schema and output files\n * @returns The Next.js configuration object unchanged\n * @throws An error if the schema file cannot be found or if code generation fails\n */\nexport function withArkEnv<T>(nextConfig: T, options?: ArkEnvConfigOptions): T {\n\tsetupArkEnv(options);\n\treturn nextConfig;\n}\n\n/**\n * Run code generation to read the schema file and generate the env.gen.ts factory.\n *\n * @param schemaPath The absolute path to the schema file or directory\n * @param outputPath The absolute path to the generated output file\n * @param layoutOption The explicit layout to use; auto-detected from the filesystem when omitted\n * @throws An error if strict layout files are missing when `layoutOption` is `\"strict\"`\n */\nexport function runCodegen(\n\tschemaPath: string,\n\toutputPath: string,\n\tlayoutOption?: ArkEnvConfigOptions[\"layout\"],\n) {\n\tconst normalizedLayout = normalizeLayout(layoutOption);\n\n\tconst { layout: resolvedLayout, baseDir } = resolveLayout(\n\t\tschemaPath,\n\t\tnormalizedLayout,\n\t);\n\n\tlet generatedCode = \"\";\n\tif (resolvedLayout === \"strict\") {\n\t\tconst clientPath = path.join(baseDir, \"client.ts\");\n\t\tconst sharedPath = path.join(baseDir, \"internal\", \"shared.ts\");\n\n\t\tconst clientContent = fs.existsSync(clientPath)\n\t\t\t? fs.readFileSync(clientPath, \"utf-8\")\n\t\t\t: \"\";\n\t\tconst sharedContent = fs.existsSync(sharedPath)\n\t\t\t? fs.readFileSync(sharedPath, \"utf-8\")\n\t\t\t: \"\";\n\n\t\tconst clientKeys = extractClientKeys(clientContent);\n\t\tconst sharedKeys = extractSharedKeys(sharedContent);\n\n\t\tgeneratedCode = generateClientFactoryCode(clientKeys, sharedKeys);\n\t} else {\n\t\tconst fileContent = fs.readFileSync(schemaPath, \"utf-8\");\n\t\tconst { clientKeys, sharedKeys, isLegacy } = extractKeys(fileContent);\n\t\tif (isLegacy) {\n\t\t\tgeneratedCode = generateFactoryCode(clientKeys, sharedKeys);\n\t\t} else {\n\t\t\tgeneratedCode = generateFlatFactoryCode(clientKeys, sharedKeys);\n\t\t}\n\t}\n\n\t// Ensure parent directory exists\n\tconst outputDir = path.dirname(outputPath);\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\t// Write if changed to avoid unnecessary filesystem/watcher triggers\n\tlet shouldWrite = true;\n\tif (fs.existsSync(outputPath)) {\n\t\tconst existingContent = fs.readFileSync(outputPath, \"utf-8\");\n\t\tif (existingContent === generatedCode) {\n\t\t\tshouldWrite = false;\n\t\t}\n\t}\n\n\tif (shouldWrite) {\n\t\tfs.writeFileSync(outputPath, generatedCode, \"utf-8\");\n\t}\n}\n\n/**\n * Statically extract client and shared keys from the schema content using NEXT_PUBLIC_ prefix.\n *\n * @param content The schema file string content\n * @returns An object containing the extracted client and shared keys\n */\nexport function extractKeys(content: string): {\n\tclientKeys: string[];\n\tsharedKeys: string[];\n\tserverKeys: string[];\n\tisLegacy?: boolean;\n} {\n\treturn coreExtractKeys(content, \"NEXT_PUBLIC_\");\n}\n\n/**\n * Generate the triple-tab indented runtime environment variables mapping.\n */\nfunction generateRuntimeEnvLines(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst allKeys = Array.from(new Set([...clientKeys, ...sharedKeys]));\n\treturn allKeys\n\t\t.map(\n\t\t\t(key) =>\n\t\t\t\t`\\t\\t\\t${key}: typeof window !== \"undefined\" ? (globalThis as any).__arkenv_env__?.${key} ?? process.env.${key} : process.env.${key},`,\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nconst GENERATED_HEADER = `/* eslint-disable */\n// biome-ignore format: auto-generated\n// Generated by ArkEnv. DO NOT EDIT DIRECTLY.\n`;\n\nconst GENERATED_FOOTER = `\nexport default createEnv;\n`;\n\n/**\n * Generate the TypeScript factory code for the tailored createEnv helper.\n *\n * @param clientKeys The client environment variable keys\n * @param sharedKeys The shared environment variable keys\n * @returns The generated TypeScript source code string\n */\nfunction generateFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TServer extends Record<string, any> = {},\n\tconst TClient extends Record<string, any> = {},\n\tconst TShared extends Record<string, any> = {},\n>(options: {\n\tserver?: TServer;\n\tclient?: TClient & {\n\t\t[K in keyof TClient]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t};\n\tshared?: TShared;\n}) {\n\treturn coreCreateEnv({\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any) as any;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the Flat Layout createEnv helper.\n *\n * @remarks\n * **Architecture tripwire:** Do not statically compile the schema here or\n * reference internal-only types (the `$` scope or `MergeExtends`).\n *\n * - **Generic wrapper:** The factory must stay generic because the concrete\n * schema is owned by the user-land `env.ts`.\n * - **Type strategy:** It intentionally returns the full schema type to ensure\n * flawless Server Component autocomplete.\n * - **Security boundary:** Client-side protection is deliberately deferred to\n * the runtime Proxy in `@arkenv/nextjs`, which throws on unauthorized access.\n *\n * 📖 See ADR-0010: Flat layout codegen and type inference strategy\n * (`docs/adr/0010-flat-layout-codegen-type-strategy.md`).\n */\nfunction generateFlatFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs\";\nimport type { type as at, distill } from \"arktype\";\n\nexport { type } from \"@arkenv/nextjs\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, unknown> & { runtimeEnv?: never } = {},\n\tconst TExpose extends keyof TSchema = never,\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema,\n\toptions?: {\n\t\t/**\n\t\t * Custom environment variables to expose to the client bundle.\n\t\t * By default, variables prefixed with \\`NEXT_PUBLIC_\\` and \\`NODE_ENV\\` are exposed automatically.\n\t\t * Use this option to expose custom variables that do not have the \\`NEXT_PUBLIC_\\` prefix.\n\t\t */\n\t\texposeToClient?: readonly TExpose[];\n\t\textends?: [...TExtends];\n\t},\n): Readonly<distill.Out<at.infer<TSchema>>> {\n\t// Types expose the full schema for a great DX on the server; the runtime\n\t// Proxy from \\`@arkenv/nextjs\\` enforces the security boundary by throwing\n\t// when a server-only variable is accessed on the client.\n\tconst env = coreCreateEnv(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n\treturn env as unknown as Readonly<distill.Out<at.infer<TSchema>>>;\n}\n${GENERATED_FOOTER}`;\n}\n\n/**\n * Generate the TypeScript factory code for the strict-layout `createEnv` helper.\n *\n * Unlike `generateFactoryCode`, this variant imports from `@arkenv/nextjs/client`\n * and exposes a positional-schema signature suited for split-file projects.\n *\n * @param clientKeys The env var keys extracted from `client.ts`\n * @param sharedKeys The env var keys extracted from `internal/shared.ts`\n * @returns The generated TypeScript source code string\n */\nfunction generateClientFactoryCode(\n\tclientKeys: string[],\n\tsharedKeys: string[],\n): string {\n\tconst runtimeEnvLines = generateRuntimeEnvLines(clientKeys, sharedKeys);\n\n\treturn `${GENERATED_HEADER}\nimport { createEnv as coreCreateEnv } from \"@arkenv/nextjs/client\";\n\nexport { type } from \"@arkenv/nextjs/client\";\n\nexport function createEnv<\n\tconst TSchema extends Record<string, any> = {},\n\tconst TExtends extends readonly unknown[] = [],\n>(\n\tschema: TSchema & {\n\t\t[K in keyof TSchema]: K extends \\`NEXT_PUBLIC_\\${string}\\` ? unknown : never;\n\t},\n\toptions?: {\n\t\textends?: [...TExtends];\n\t},\n) {\n\treturn coreCreateEnv<TSchema, TExtends>(schema as any, {\n\t\t...options,\n\t\truntimeEnv: {\n${runtimeEnvLines}\n\t\t},\n\t} as any);\n}\n${GENERATED_FOOTER}`;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkenv/nextjs",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "author": "Yam Borodetsky <yam@yam.codes>",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,8 +12,8 @@
12
12
  "chokidar": "^4.0.3",
13
13
  "jiti": "2.7.0",
14
14
  "server-only": "^0.0.1",
15
- "arkenv": "0.12.2",
16
- "@arkenv/build": "0.0.2"
15
+ "@arkenv/build": "0.0.3",
16
+ "arkenv": "0.12.3"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@size-limit/preset-small-lib": "12.1.0",
@@ -75,10 +75,15 @@
75
75
  ],
76
76
  "homepage": "https://arkenv.js.org",
77
77
  "keywords": [
78
- "arktype",
79
78
  "arkenv",
80
- "environment",
81
- "variables",
79
+ "arktype",
80
+ "env",
81
+ "environment-variables",
82
+ "dotenv",
83
+ "config",
84
+ "validation",
85
+ "typesafe",
86
+ "standard-schema",
82
87
  "next",
83
88
  "nextjs"
84
89
  ],