@eventuras/app-config 0.1.4

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChF"}
@@ -0,0 +1,48 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ //#region src/generator.ts
4
+ /**
5
+ * Generate TypeScript types from app.config.json
6
+ * This module provides functions to generate type definitions from configuration files
7
+ */
8
+ function mapTypeToTS(type) {
9
+ return {
10
+ string: "string",
11
+ url: "string",
12
+ int: "number",
13
+ bool: "boolean",
14
+ json: "unknown"
15
+ }[type];
16
+ }
17
+ /**
18
+ * Generate TypeScript type definitions from an app.config.json file
19
+ * @param options - Configuration options for type generation
20
+ */
21
+ async function generateTypes(options) {
22
+ const { configPath, outputPath, interfaceName = "PublicEnv" } = options;
23
+ console.log("📝 Reading config from:", configPath);
24
+ const configContent = await fs.readFile(configPath, "utf-8");
25
+ const config = JSON.parse(configContent);
26
+ const output = `/**
27
+ * AUTO-GENERATED FILE - DO NOT EDIT
28
+ * Generated from app.config.json
29
+ *
30
+ * To regenerate, run: pnpm generate:config-types
31
+ */
32
+
33
+ export interface ${interfaceName} {
34
+ ${Object.entries(config.env).filter(([, def]) => def.client).map(([name, def]) => {
35
+ const tsType = mapTypeToTS(def.type);
36
+ return ` ${name}${def.required ? "" : "?"}: ${tsType};`;
37
+ }).join("\n")}
38
+ }
39
+ `;
40
+ const outputDir = path.dirname(outputPath);
41
+ await fs.mkdir(outputDir, { recursive: true });
42
+ await fs.writeFile(outputPath, output, "utf-8");
43
+ console.log("✅ Generated types at:", outputPath);
44
+ }
45
+ //#endregion
46
+ export { generateTypes };
47
+
48
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","names":[],"sources":["../src/generator.ts"],"sourcesContent":["/**\n * Generate TypeScript types from app.config.json\n * This module provides functions to generate type definitions from configuration files\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\ntype EnvVarType = 'string' | 'url' | 'int' | 'bool' | 'json';\n\ninterface EnvVarDef {\n required: boolean;\n client: boolean;\n type: EnvVarType;\n description: string;\n}\n\ninterface AppConfig {\n env: Record<string, EnvVarDef>;\n}\n\nfunction mapTypeToTS(type: EnvVarType): string {\n const map: Record<EnvVarType, string> = {\n string: 'string',\n url: 'string',\n int: 'number',\n bool: 'boolean',\n json: 'unknown',\n };\n return map[type];\n}\n\nexport interface GenerateTypesOptions {\n /** Path to app.config.json file */\n configPath: string;\n /** Path where the generated .d.ts file should be written */\n outputPath: string;\n /** Name of the interface to generate (default: 'PublicEnv') */\n interfaceName?: string;\n}\n\n/**\n * Generate TypeScript type definitions from an app.config.json file\n * @param options - Configuration options for type generation\n */\nexport async function generateTypes(options: GenerateTypesOptions): Promise<void> {\n const { configPath, outputPath, interfaceName = 'PublicEnv' } = options;\n\n console.log('📝 Reading config from:', configPath);\n\n const configContent = await fs.readFile(configPath, 'utf-8');\n const config: AppConfig = JSON.parse(configContent);\n\n const publicVars = Object.entries(config.env)\n .filter(([, def]) => def.client)\n .map(([name, def]) => {\n const tsType = mapTypeToTS(def.type);\n const optional = def.required ? '' : '?';\n return ` ${name}${optional}: ${tsType};`;\n });\n\n const output = `/**\n * AUTO-GENERATED FILE - DO NOT EDIT\n * Generated from app.config.json\n *\n * To regenerate, run: pnpm generate:config-types\n */\n\nexport interface ${interfaceName} {\n${publicVars.join('\\n')}\n}\n`;\n\n // Ensure the output directory exists\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n\n await fs.writeFile(outputPath, output, 'utf-8');\n console.log('✅ Generated types at:', outputPath);\n}\n"],"mappings":";;;;;;;AAqBA,SAAS,YAAY,MAA0B;CAQ7C,OAAO;EANL,QAAQ;EACR,KAAK;EACL,KAAK;EACL,MAAM;EACN,MAAM;CAED,EAAI;AACb;;;;;AAeA,eAAsB,cAAc,SAA8C;CAChF,MAAM,EAAE,YAAY,YAAY,gBAAgB,gBAAgB;CAEhE,QAAQ,IAAI,2BAA2B,UAAU;CAEjD,MAAM,gBAAgB,MAAM,GAAG,SAAS,YAAY,OAAO;CAC3D,MAAM,SAAoB,KAAK,MAAM,aAAa;CAUlD,MAAM,SAAS;;;;;;;mBAOE,cAAc;EAfZ,OAAO,QAAQ,OAAO,GAAG,CAAC,CAC1C,QAAQ,GAAG,SAAS,IAAI,MAAM,CAAC,CAC/B,KAAK,CAAC,MAAM,SAAS;EACpB,MAAM,SAAS,YAAY,IAAI,IAAI;EAEnC,OAAO,KAAK,OADK,IAAI,WAAW,KAAK,IACT,IAAI,OAAO;CACzC,CAUF,CAAA,CAAW,KAAK,IAAI,EAAE;;;CAKtB,MAAM,YAAY,KAAK,QAAQ,UAAU;CACzC,MAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;CAE7C,MAAM,GAAG,UAAU,YAAY,QAAQ,OAAO;CAC9C,QAAQ,IAAI,yBAAyB,UAAU;AACjD"}
@@ -0,0 +1,6 @@
1
+ export { ConfigLoader, createConfig, validate } from './loader.js';
2
+ export { EnvValidationError, parseEnvValue, getTypeString } from './validator.js';
3
+ export type { AppConfig, EnvVarDefinition, EnvVarType } from './types.js';
4
+ export { appConfigSchema, envVarDefinitionSchema } from './types.js';
5
+ export { createPublicEnvGetters, createEnvironment, type EnvironmentObject } from './next.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,277 @@
1
+ import { z } from "zod";
2
+ //#region src/types.ts
3
+ /**
4
+ * Zod schema for environment variable definition
5
+ */
6
+ var envVarDefinitionSchema = z.object({
7
+ required: z.boolean(),
8
+ client: z.boolean(),
9
+ type: z.enum([
10
+ "string",
11
+ "url",
12
+ "int",
13
+ "bool",
14
+ "json"
15
+ ]),
16
+ description: z.string(),
17
+ default: z.union([
18
+ z.string(),
19
+ z.number(),
20
+ z.boolean(),
21
+ z.object({})
22
+ ]).optional(),
23
+ pattern: z.string().optional(),
24
+ enum: z.array(z.string()).optional()
25
+ });
26
+ /**
27
+ * Zod schema for app configuration
28
+ */
29
+ var appConfigSchema = z.object({
30
+ $schema: z.string().optional(),
31
+ name: z.string(),
32
+ type: z.literal("app"),
33
+ description: z.string().optional(),
34
+ env: z.record(z.string(), envVarDefinitionSchema),
35
+ build: z.object({
36
+ outDir: z.string().optional(),
37
+ target: z.string().optional()
38
+ }).optional(),
39
+ runtime: z.object({ port: z.number().optional() }).optional()
40
+ });
41
+ //#endregion
42
+ //#region src/validator.ts
43
+ /**
44
+ * Validation error class
45
+ */
46
+ var EnvValidationError = class extends Error {
47
+ varName;
48
+ definition;
49
+ constructor(message, varName, definition) {
50
+ super(message);
51
+ this.varName = varName;
52
+ this.definition = definition;
53
+ this.name = "EnvValidationError";
54
+ }
55
+ };
56
+ /**
57
+ * Parse and validate an environment variable value based on its type
58
+ */
59
+ function parseEnvValue(varName, rawValue, definition) {
60
+ if (rawValue === void 0 || rawValue === "") {
61
+ if (definition.required && definition.default === void 0) throw new EnvValidationError(`Required environment variable "${varName}" is not set.\nDescription: ${definition.description}`, varName, definition);
62
+ return definition.default;
63
+ }
64
+ if (definition.enum && !definition.enum.includes(rawValue)) throw new EnvValidationError(`Environment variable "${varName}" must be one of: ${definition.enum.join(", ")}.\nGot: "${rawValue}"`, varName, definition);
65
+ if (definition.pattern) {
66
+ if (!new RegExp(definition.pattern).test(rawValue)) throw new EnvValidationError(`Environment variable "${varName}" does not match pattern: ${definition.pattern}.\nGot: "${rawValue}"`, varName, definition);
67
+ }
68
+ switch (definition.type) {
69
+ case "string": return rawValue;
70
+ case "url": try {
71
+ new URL(rawValue);
72
+ return rawValue;
73
+ } catch {
74
+ throw new EnvValidationError(`Environment variable "${varName}" must be a valid URL.\nGot: "${rawValue}"`, varName, definition);
75
+ }
76
+ case "int": {
77
+ const intValue = Number.parseInt(rawValue, 10);
78
+ if (Number.isNaN(intValue)) throw new EnvValidationError(`Environment variable "${varName}" must be a valid integer.\nGot: "${rawValue}"`, varName, definition);
79
+ return intValue;
80
+ }
81
+ case "bool": {
82
+ const lowerValue = rawValue.toLowerCase();
83
+ if (lowerValue === "true" || lowerValue === "1") return true;
84
+ if (lowerValue === "false" || lowerValue === "0") return false;
85
+ throw new EnvValidationError(`Environment variable "${varName}" must be a boolean (true/false, 1/0).\nGot: "${rawValue}"`, varName, definition);
86
+ }
87
+ case "json": try {
88
+ return JSON.parse(rawValue);
89
+ } catch {
90
+ throw new EnvValidationError(`Environment variable "${varName}" must be valid JSON.\nGot: "${rawValue}"`, varName, definition);
91
+ }
92
+ default: {
93
+ const _exhaustive = definition.type;
94
+ throw new Error(`Unknown type: ${_exhaustive}`);
95
+ }
96
+ }
97
+ }
98
+ /**
99
+ * Get the TypeScript type string for an environment variable type
100
+ */
101
+ function getTypeString(type) {
102
+ switch (type) {
103
+ case "string":
104
+ case "url": return "string";
105
+ case "int": return "number";
106
+ case "bool": return "boolean";
107
+ case "json": return "unknown";
108
+ default: throw new Error(`Unknown type: ${type}`);
109
+ }
110
+ }
111
+ //#endregion
112
+ //#region src/loader.ts
113
+ /**
114
+ * Configuration loader class
115
+ */
116
+ var ConfigLoader = class {
117
+ processEnv;
118
+ config;
119
+ envValues = {};
120
+ /**
121
+ * Direct access to environment variables as properties
122
+ * @example config.env.AUTH0_CLIENT_ID
123
+ */
124
+ env;
125
+ constructor(configObject, processEnv = process.env) {
126
+ this.processEnv = processEnv;
127
+ const result = appConfigSchema.safeParse(configObject);
128
+ if (!result.success) {
129
+ const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
130
+ throw new Error(`Invalid app.config.json:\n${issues}`);
131
+ }
132
+ this.config = result.data;
133
+ const isNextBuild = this.processEnv.NEXT_PHASE === "phase-production-build" || this.processEnv.NEXT_PHASE === "phase-development-server";
134
+ this.validateEnvironment(!isNextBuild);
135
+ this.env = new Proxy(this.envValues, {
136
+ get: (target, prop) => {
137
+ if (!(prop in target)) throw new Error(`Environment variable "${prop}" is not defined in app.config.json.\nAvailable variables: ${Object.keys(target).join(", ")}`);
138
+ return target[prop];
139
+ },
140
+ set: () => {
141
+ throw new Error("Cannot modify environment variables through config.env");
142
+ }
143
+ });
144
+ }
145
+ /**
146
+ * Validate all environment variables according to config
147
+ * @param strictRequired - Whether to throw errors for missing required vars (false during build)
148
+ */
149
+ validateEnvironment(strictRequired = true) {
150
+ const errors = [];
151
+ for (const [varName, definition] of Object.entries(this.config.env)) try {
152
+ const value = parseEnvValue(varName, this.processEnv[varName], definition);
153
+ this.envValues[varName] = value;
154
+ if (this.processEnv[varName] === void 0 && value !== void 0) this.processEnv[varName] = String(value);
155
+ } catch (error) {
156
+ if (error instanceof EnvValidationError) {
157
+ if (!strictRequired && error.message.includes("Required environment variable")) {
158
+ this.envValues[varName] = definition.default ?? "";
159
+ continue;
160
+ }
161
+ errors.push(error);
162
+ } else throw error;
163
+ }
164
+ if (errors.length > 0) {
165
+ const errorMessage = errors.map((e) => `\n❌ ${e.message}`).join("\n");
166
+ throw new Error(`Environment validation failed:${errorMessage}\n`);
167
+ }
168
+ }
169
+ /**
170
+ * Get a typed environment variable value
171
+ */
172
+ get(varName) {
173
+ if (!(varName in this.envValues)) throw new Error(`Environment variable "${varName}" is not defined in app.config.json.\nAvailable variables: ${Object.keys(this.envValues).join(", ")}`);
174
+ return this.envValues[varName];
175
+ }
176
+ /**
177
+ * Get the raw app configuration
178
+ */
179
+ getConfig() {
180
+ return this.config;
181
+ }
182
+ /**
183
+ * Get all environment variables as a typed object
184
+ */
185
+ getAllEnv() {
186
+ return { ...this.envValues };
187
+ }
188
+ /**
189
+ * Check if a variable exists
190
+ */
191
+ has(varName) {
192
+ return varName in this.envValues;
193
+ }
194
+ };
195
+ /**
196
+ * Create a config loader from a config object
197
+ */
198
+ function createConfig(configObject) {
199
+ return new ConfigLoader(configObject);
200
+ }
201
+ /**
202
+ * Validate app configuration and environment variables.
203
+ * This is useful for running validation explicitly during app initialization.
204
+ *
205
+ * @param configObject - App configuration object (parsed from app.config.json)
206
+ * @throws Error if configuration is invalid or required env vars are missing
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * // In your app initialization (e.g., layout.tsx or main.ts)
211
+ * import { validate } from '@eventuras/app-config';
212
+ * import appConfigJson from './app.config.json';
213
+ *
214
+ * validate(appConfigJson);
215
+ * console.log('✓ Environment validated successfully');
216
+ * ```
217
+ */
218
+ function validate(configObject) {
219
+ new ConfigLoader(configObject);
220
+ }
221
+ //#endregion
222
+ //#region src/next.ts
223
+ /**
224
+ * Create explicit getters for NEXT_PUBLIC_* environment variables.
225
+ *
226
+ * This is required for Next.js because it performs build-time replacement of
227
+ * process.env.NEXT_PUBLIC_* variables. We must access process.env directly,
228
+ * not through a runtime lookup.
229
+ *
230
+ * @param config - The app configuration
231
+ * @returns An object with explicit getters for each NEXT_PUBLIC_* variable
232
+ */
233
+ function createPublicEnvGetters(config) {
234
+ const getters = {};
235
+ for (const [varName, definition] of Object.entries(config.env)) if (definition.client && varName.startsWith("NEXT_PUBLIC_")) Object.defineProperty(getters, varName, {
236
+ get() {
237
+ return process.env[varName];
238
+ },
239
+ enumerable: true
240
+ });
241
+ return getters;
242
+ }
243
+ /**
244
+ * Create a complete Environment object with validation and explicit getters.
245
+ *
246
+ * This provides a drop-in replacement for the old Environment class pattern,
247
+ * with automatic validation and proper Next.js NEXT_PUBLIC_* support.
248
+ *
249
+ * @param configPath - Path to app.config.json
250
+ * @returns An object with validate(), get(), and explicit NEXT_PUBLIC_* getters
251
+ */
252
+ function createEnvironment(configPath) {
253
+ let configInstance = null;
254
+ function getConfigInstance() {
255
+ if (!configInstance) configInstance = new ConfigLoader(configPath);
256
+ return configInstance;
257
+ }
258
+ return {
259
+ /**
260
+ * Validate environment (happens automatically on first access)
261
+ */
262
+ validate: () => {
263
+ getConfigInstance();
264
+ },
265
+ /**
266
+ * Get a server-side environment variable
267
+ */
268
+ get: (varName) => {
269
+ return getConfigInstance().get(varName);
270
+ },
271
+ ...createPublicEnvGetters(getConfigInstance().getConfig())
272
+ };
273
+ }
274
+ //#endregion
275
+ export { ConfigLoader, EnvValidationError, appConfigSchema, createConfig, createEnvironment, createPublicEnvGetters, envVarDefinitionSchema, getTypeString, parseEnvValue, validate };
276
+
277
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/types.ts","../src/validator.ts","../src/loader.ts","../src/next.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Supported environment variable types\n */\nexport type EnvVarType = 'string' | 'url' | 'int' | 'bool' | 'json';\n\n/**\n * Environment variable definition\n */\nexport interface EnvVarDefinition {\n /** Whether this variable is required */\n required: boolean;\n /** Whether this variable is exposed to the client (e.g., NEXT_PUBLIC_*) */\n client: boolean;\n /** Expected type of the variable */\n type: EnvVarType;\n /** Human-readable description */\n description: string;\n /** Default value if not provided */\n default?: string | number | boolean | object;\n /** Regular expression pattern for validation */\n pattern?: string;\n /** Allowed values */\n enum?: string[];\n}\n\n/**\n * Application configuration schema\n */\nexport interface AppConfig {\n /** JSON Schema reference */\n $schema?: string;\n /** Application package name */\n name: string;\n /** Configuration type */\n type: 'app';\n /** Application description */\n description?: string;\n /** Environment variable definitions */\n env: Record<string, EnvVarDefinition>;\n /** Build configuration */\n build?: {\n outDir?: string;\n target?: string;\n };\n /** Runtime configuration */\n runtime?: {\n port?: number;\n };\n}\n\n/**\n * Zod schema for environment variable definition\n */\nexport const envVarDefinitionSchema = z.object({\n required: z.boolean(),\n client: z.boolean(),\n type: z.enum(['string', 'url', 'int', 'bool', 'json']),\n description: z.string(),\n default: z.union([z.string(), z.number(), z.boolean(), z.object({})]).optional(),\n pattern: z.string().optional(),\n enum: z.array(z.string()).optional(),\n});\n\n/**\n * Zod schema for app configuration\n */\nexport const appConfigSchema = z.object({\n $schema: z.string().optional(),\n name: z.string(),\n type: z.literal('app'),\n description: z.string().optional(),\n env: z.record(z.string(), envVarDefinitionSchema),\n build: z\n .object({\n outDir: z.string().optional(),\n target: z.string().optional(),\n })\n .optional(),\n runtime: z\n .object({\n port: z.number().optional(),\n })\n .optional(),\n});\n","import { EnvVarDefinition, EnvVarType } from './types.js';\n\n/**\n * Validation error class\n */\nexport class EnvValidationError extends Error {\n constructor(\n message: string,\n public varName: string,\n public definition?: EnvVarDefinition\n ) {\n super(message);\n this.name = 'EnvValidationError';\n }\n}\n\n/**\n * Parse and validate an environment variable value based on its type\n */\nexport function parseEnvValue(\n varName: string,\n rawValue: string | undefined,\n definition: EnvVarDefinition\n): unknown {\n // Handle missing values\n if (rawValue === undefined || rawValue === '') {\n if (definition.required && definition.default === undefined) {\n throw new EnvValidationError(\n `Required environment variable \"${varName}\" is not set.\\n` +\n `Description: ${definition.description}`,\n varName,\n definition\n );\n }\n return definition.default;\n }\n\n // Validate enum\n if (definition.enum && !definition.enum.includes(rawValue)) {\n throw new EnvValidationError(\n `Environment variable \"${varName}\" must be one of: ${definition.enum.join(', ')}.\\n` +\n `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n\n // Validate pattern\n if (definition.pattern) {\n const regex = new RegExp(definition.pattern);\n if (!regex.test(rawValue)) {\n throw new EnvValidationError(\n `Environment variable \"${varName}\" does not match pattern: ${definition.pattern}.\\n` +\n `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n }\n\n // Type conversion and validation\n switch (definition.type) {\n case 'string':\n return rawValue;\n\n case 'url':\n try {\n new URL(rawValue);\n return rawValue;\n } catch {\n throw new EnvValidationError(\n `Environment variable \"${varName}\" must be a valid URL.\\n` + `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n\n case 'int': {\n const intValue = Number.parseInt(rawValue, 10);\n if (Number.isNaN(intValue)) {\n throw new EnvValidationError(\n `Environment variable \"${varName}\" must be a valid integer.\\n` + `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n return intValue;\n }\n\n case 'bool': {\n const lowerValue = rawValue.toLowerCase();\n if (lowerValue === 'true' || lowerValue === '1') return true;\n if (lowerValue === 'false' || lowerValue === '0') return false;\n throw new EnvValidationError(\n `Environment variable \"${varName}\" must be a boolean (true/false, 1/0).\\n` +\n `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n\n case 'json':\n try {\n return JSON.parse(rawValue);\n } catch {\n throw new EnvValidationError(\n `Environment variable \"${varName}\" must be valid JSON.\\n` + `Got: \"${rawValue}\"`,\n varName,\n definition\n );\n }\n\n default: {\n const _exhaustive: never = definition.type;\n throw new Error(`Unknown type: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Get the TypeScript type string for an environment variable type\n */\nexport function getTypeString(type: EnvVarType): string {\n switch (type) {\n case 'string':\n case 'url':\n return 'string';\n case 'int':\n return 'number';\n case 'bool':\n return 'boolean';\n case 'json':\n return 'unknown';\n default: {\n const _exhaustive: never = type;\n throw new Error(`Unknown type: ${_exhaustive}`);\n }\n }\n}\n","import { AppConfig, appConfigSchema } from './types.js';\nimport { parseEnvValue, EnvValidationError } from './validator.js';\n\n/**\n * Configuration loader class\n */\nexport class ConfigLoader {\n private readonly config: AppConfig;\n private envValues: Record<string, unknown> = {};\n\n /**\n * Direct access to environment variables as properties\n * @example config.env.AUTH0_CLIENT_ID\n */\n public readonly env: Record<string, unknown>;\n\n constructor(\n configObject: unknown,\n private processEnv: NodeJS.ProcessEnv = process.env\n ) {\n // Validate schema\n const result = appConfigSchema.safeParse(configObject);\n if (!result.success) {\n const issues = result.error.issues.map(i => ` - ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new Error(\n `Invalid app.config.json:\\n${issues}`\n );\n }\n\n this.config = result.data;\n\n // Skip validation during Next.js build/compilation phases\n // During these phases, we still want to read the env vars, but not fail the build if they're missing\n // NEXT_PHASE is set by Next.js during build\n const isNextBuild =\n this.processEnv.NEXT_PHASE === 'phase-production-build' ||\n this.processEnv.NEXT_PHASE === 'phase-development-server';\n\n // Always try to validate/read environment variables\n // During build, we'll be lenient about missing required vars\n this.validateEnvironment(!isNextBuild);\n\n // Create readonly proxy for env access\n this.env = new Proxy(this.envValues, {\n get: (target, prop: string) => {\n if (!(prop in target)) {\n throw new Error(\n `Environment variable \"${prop}\" is not defined in app.config.json.\\n` +\n `Available variables: ${Object.keys(target).join(', ')}`\n );\n }\n return target[prop];\n },\n set: () => {\n throw new Error('Cannot modify environment variables through config.env');\n },\n });\n }\n\n /**\n * Validate all environment variables according to config\n * @param strictRequired - Whether to throw errors for missing required vars (false during build)\n */\n private validateEnvironment(strictRequired = true): void {\n const errors: EnvValidationError[] = [];\n\n for (const [varName, definition] of Object.entries(this.config.env)) {\n try {\n const value = parseEnvValue(varName, this.processEnv[varName], definition);\n this.envValues[varName] = value;\n\n // Set default values back to process.env if they were missing\n if (this.processEnv[varName] === undefined && value !== undefined) {\n this.processEnv[varName] = String(value);\n }\n } catch (error) {\n if (error instanceof EnvValidationError) {\n // During build (strictRequired=false), skip required validation errors but still collect type errors\n if (!strictRequired && error.message.includes('Required environment variable')) {\n // Use default value or empty string if required var is missing during build\n this.envValues[varName] = definition.default ?? '';\n continue;\n }\n errors.push(error);\n } else {\n throw error;\n }\n }\n }\n\n // Throw all errors at once\n if (errors.length > 0) {\n const errorMessage = errors.map(e => `\\n❌ ${e.message}`).join('\\n');\n throw new Error(`Environment validation failed:${errorMessage}\\n`);\n }\n }\n\n /**\n * Get a typed environment variable value\n */\n get<T = unknown>(varName: string): T {\n if (!(varName in this.envValues)) {\n throw new Error(\n `Environment variable \"${varName}\" is not defined in app.config.json.\\n` +\n `Available variables: ${Object.keys(this.envValues).join(', ')}`\n );\n }\n return this.envValues[varName] as T;\n }\n\n /**\n * Get the raw app configuration\n */\n getConfig(): Readonly<AppConfig> {\n return this.config;\n }\n\n /**\n * Get all environment variables as a typed object\n */\n getAllEnv(): Readonly<Record<string, unknown>> {\n return { ...this.envValues };\n }\n\n /**\n * Check if a variable exists\n */\n has(varName: string): boolean {\n return varName in this.envValues;\n }\n}\n\n/**\n * Create a config loader from a config object\n */\nexport function createConfig(configObject: unknown): ConfigLoader {\n return new ConfigLoader(configObject);\n}\n\n/**\n * Validate app configuration and environment variables.\n * This is useful for running validation explicitly during app initialization.\n *\n * @param configObject - App configuration object (parsed from app.config.json)\n * @throws Error if configuration is invalid or required env vars are missing\n *\n * @example\n * ```typescript\n * // In your app initialization (e.g., layout.tsx or main.ts)\n * import { validate } from '@eventuras/app-config';\n * import appConfigJson from './app.config.json';\n *\n * validate(appConfigJson);\n * console.log('✓ Environment validated successfully');\n * ```\n */\nexport function validate(configObject: unknown): void {\n // Simply creating the config will trigger validation\n // If validation fails, an error will be thrown\n new ConfigLoader(configObject);\n}\n","import { AppConfig } from './types.js';\nimport { ConfigLoader } from './loader.js';\n\n/**\n * Create explicit getters for NEXT_PUBLIC_* environment variables.\n *\n * This is required for Next.js because it performs build-time replacement of\n * process.env.NEXT_PUBLIC_* variables. We must access process.env directly,\n * not through a runtime lookup.\n *\n * @param config - The app configuration\n * @returns An object with explicit getters for each NEXT_PUBLIC_* variable\n */\nexport function createPublicEnvGetters(config: AppConfig) {\n const getters: Record<string, unknown> = {};\n\n for (const [varName, definition] of Object.entries(config.env)) {\n if (definition.client && varName.startsWith('NEXT_PUBLIC_')) {\n Object.defineProperty(getters, varName, {\n get() {\n return process.env[varName];\n },\n enumerable: true,\n });\n }\n }\n\n return getters;\n}\n\nexport interface EnvironmentObject {\n validate: () => void;\n get: <T = string>(varName: string) => T;\n [key: string]: unknown;\n}\n\n/**\n * Create a complete Environment object with validation and explicit getters.\n *\n * This provides a drop-in replacement for the old Environment class pattern,\n * with automatic validation and proper Next.js NEXT_PUBLIC_* support.\n *\n * @param configPath - Path to app.config.json\n * @returns An object with validate(), get(), and explicit NEXT_PUBLIC_* getters\n */\nexport function createEnvironment(configPath: string): EnvironmentObject {\n let configInstance: ConfigLoader | null = null;\n\n function getConfigInstance(): ConfigLoader {\n if (!configInstance) {\n configInstance = new ConfigLoader(configPath);\n }\n return configInstance;\n }\n\n const publicGetters = createPublicEnvGetters(getConfigInstance().getConfig());\n\n return {\n /**\n * Validate environment (happens automatically on first access)\n */\n validate: () => {\n getConfigInstance();\n },\n\n /**\n * Get a server-side environment variable\n */\n get: <T = string>(varName: string): T => {\n return getConfigInstance().get(varName) as T;\n },\n\n // Spread in all the NEXT_PUBLIC_* getters\n ...publicGetters,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { AppConfig } from './types.js';
2
+ /**
3
+ * Configuration loader class
4
+ */
5
+ export declare class ConfigLoader {
6
+ private processEnv;
7
+ private readonly config;
8
+ private envValues;
9
+ /**
10
+ * Direct access to environment variables as properties
11
+ * @example config.env.AUTH0_CLIENT_ID
12
+ */
13
+ readonly env: Record<string, unknown>;
14
+ constructor(configObject: unknown, processEnv?: NodeJS.ProcessEnv);
15
+ /**
16
+ * Validate all environment variables according to config
17
+ * @param strictRequired - Whether to throw errors for missing required vars (false during build)
18
+ */
19
+ private validateEnvironment;
20
+ /**
21
+ * Get a typed environment variable value
22
+ */
23
+ get<T = unknown>(varName: string): T;
24
+ /**
25
+ * Get the raw app configuration
26
+ */
27
+ getConfig(): Readonly<AppConfig>;
28
+ /**
29
+ * Get all environment variables as a typed object
30
+ */
31
+ getAllEnv(): Readonly<Record<string, unknown>>;
32
+ /**
33
+ * Check if a variable exists
34
+ */
35
+ has(varName: string): boolean;
36
+ }
37
+ /**
38
+ * Create a config loader from a config object
39
+ */
40
+ export declare function createConfig(configObject: unknown): ConfigLoader;
41
+ /**
42
+ * Validate app configuration and environment variables.
43
+ * This is useful for running validation explicitly during app initialization.
44
+ *
45
+ * @param configObject - App configuration object (parsed from app.config.json)
46
+ * @throws Error if configuration is invalid or required env vars are missing
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * // In your app initialization (e.g., layout.tsx or main.ts)
51
+ * import { validate } from '@eventuras/app-config';
52
+ * import appConfigJson from './app.config.json';
53
+ *
54
+ * validate(appConfigJson);
55
+ * console.log('✓ Environment validated successfully');
56
+ * ```
57
+ */
58
+ export declare function validate(configObject: unknown): void;
59
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmB,MAAM,YAAY,CAAC;AAGxD;;GAEG;AACH,qBAAa,YAAY;IAYrB,OAAO,CAAC,UAAU;IAXpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,SAAS,CAA+B;IAEhD;;;OAGG;IACH,SAAgB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAG3C,YAAY,EAAE,OAAO,EACb,UAAU,GAAE,MAAM,CAAC,UAAwB;IAyCrD;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;OAEG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC;IAUpC;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC;IAIhC;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI9C;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAG9B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,OAAO,GAAG,YAAY,CAEhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAIpD"}
package/dist/next.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { AppConfig } from './types.js';
2
+ /**
3
+ * Create explicit getters for NEXT_PUBLIC_* environment variables.
4
+ *
5
+ * This is required for Next.js because it performs build-time replacement of
6
+ * process.env.NEXT_PUBLIC_* variables. We must access process.env directly,
7
+ * not through a runtime lookup.
8
+ *
9
+ * @param config - The app configuration
10
+ * @returns An object with explicit getters for each NEXT_PUBLIC_* variable
11
+ */
12
+ export declare function createPublicEnvGetters(config: AppConfig): Record<string, unknown>;
13
+ export interface EnvironmentObject {
14
+ validate: () => void;
15
+ get: <T = string>(varName: string) => T;
16
+ [key: string]: unknown;
17
+ }
18
+ /**
19
+ * Create a complete Environment object with validation and explicit getters.
20
+ *
21
+ * This provides a drop-in replacement for the old Environment class pattern,
22
+ * with automatic validation and proper Next.js NEXT_PUBLIC_* support.
23
+ *
24
+ * @param configPath - Path to app.config.json
25
+ * @returns An object with validate(), get(), and explicit NEXT_PUBLIC_* getters
26
+ */
27
+ export declare function createEnvironment(configPath: string): EnvironmentObject;
28
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,2BAevD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,CA8BvE"}
@@ -0,0 +1,98 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Supported environment variable types
4
+ */
5
+ export type EnvVarType = 'string' | 'url' | 'int' | 'bool' | 'json';
6
+ /**
7
+ * Environment variable definition
8
+ */
9
+ export interface EnvVarDefinition {
10
+ /** Whether this variable is required */
11
+ required: boolean;
12
+ /** Whether this variable is exposed to the client (e.g., NEXT_PUBLIC_*) */
13
+ client: boolean;
14
+ /** Expected type of the variable */
15
+ type: EnvVarType;
16
+ /** Human-readable description */
17
+ description: string;
18
+ /** Default value if not provided */
19
+ default?: string | number | boolean | object;
20
+ /** Regular expression pattern for validation */
21
+ pattern?: string;
22
+ /** Allowed values */
23
+ enum?: string[];
24
+ }
25
+ /**
26
+ * Application configuration schema
27
+ */
28
+ export interface AppConfig {
29
+ /** JSON Schema reference */
30
+ $schema?: string;
31
+ /** Application package name */
32
+ name: string;
33
+ /** Configuration type */
34
+ type: 'app';
35
+ /** Application description */
36
+ description?: string;
37
+ /** Environment variable definitions */
38
+ env: Record<string, EnvVarDefinition>;
39
+ /** Build configuration */
40
+ build?: {
41
+ outDir?: string;
42
+ target?: string;
43
+ };
44
+ /** Runtime configuration */
45
+ runtime?: {
46
+ port?: number;
47
+ };
48
+ }
49
+ /**
50
+ * Zod schema for environment variable definition
51
+ */
52
+ export declare const envVarDefinitionSchema: z.ZodObject<{
53
+ required: z.ZodBoolean;
54
+ client: z.ZodBoolean;
55
+ type: z.ZodEnum<{
56
+ string: "string";
57
+ url: "url";
58
+ int: "int";
59
+ bool: "bool";
60
+ json: "json";
61
+ }>;
62
+ description: z.ZodString;
63
+ default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodObject<{}, z.core.$strip>]>>;
64
+ pattern: z.ZodOptional<z.ZodString>;
65
+ enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
66
+ }, z.core.$strip>;
67
+ /**
68
+ * Zod schema for app configuration
69
+ */
70
+ export declare const appConfigSchema: z.ZodObject<{
71
+ $schema: z.ZodOptional<z.ZodString>;
72
+ name: z.ZodString;
73
+ type: z.ZodLiteral<"app">;
74
+ description: z.ZodOptional<z.ZodString>;
75
+ env: z.ZodRecord<z.ZodString, z.ZodObject<{
76
+ required: z.ZodBoolean;
77
+ client: z.ZodBoolean;
78
+ type: z.ZodEnum<{
79
+ string: "string";
80
+ url: "url";
81
+ int: "int";
82
+ bool: "bool";
83
+ json: "json";
84
+ }>;
85
+ description: z.ZodString;
86
+ default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodObject<{}, z.core.$strip>]>>;
87
+ pattern: z.ZodOptional<z.ZodString>;
88
+ enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
89
+ }, z.core.$strip>>;
90
+ build: z.ZodOptional<z.ZodObject<{
91
+ outDir: z.ZodOptional<z.ZodString>;
92
+ target: z.ZodOptional<z.ZodString>;
93
+ }, z.core.$strip>>;
94
+ runtime: z.ZodOptional<z.ZodObject<{
95
+ port: z.ZodOptional<z.ZodNumber>;
96
+ }, z.core.$strip>>;
97
+ }, z.core.$strip>;
98
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,MAAM,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC7C,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,KAAK,CAAC;IACZ,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACtC,0BAA0B;IAC1B,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,4BAA4B;IAC5B,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBAQjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiB1B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { EnvVarDefinition, EnvVarType } from './types.js';
2
+ /**
3
+ * Validation error class
4
+ */
5
+ export declare class EnvValidationError extends Error {
6
+ varName: string;
7
+ definition?: EnvVarDefinition | undefined;
8
+ constructor(message: string, varName: string, definition?: EnvVarDefinition | undefined);
9
+ }
10
+ /**
11
+ * Parse and validate an environment variable value based on its type
12
+ */
13
+ export declare function parseEnvValue(varName: string, rawValue: string | undefined, definition: EnvVarDefinition): unknown;
14
+ /**
15
+ * Get the TypeScript type string for an environment variable type
16
+ */
17
+ export declare function getTypeString(type: EnvVarType): string;
18
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAGlC,OAAO,EAAE,MAAM;IACf,UAAU,CAAC,EAAE,gBAAgB;gBAFpC,OAAO,EAAE,MAAM,EACR,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,gBAAgB,YAAA;CAKvC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CA8FT;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAgBtD"}