@smooai/config 3.0.0 → 3.1.0
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/browser/chunk-YMNAMX6Y.mjs +55 -0
- package/dist/browser/chunk-YMNAMX6Y.mjs.map +1 -0
- package/dist/browser/client/index.mjs +14 -0
- package/dist/browser/client/index.mjs.map +1 -0
- package/dist/browser/feature-flags/index.mjs +4 -24
- package/dist/browser/feature-flags/index.mjs.map +1 -1
- package/dist/{chunk-2DYBQ6SF.mjs → chunk-43SVVFYE.mjs} +3 -3
- package/dist/{chunk-PCXGCPWC.mjs → chunk-6XDO5B2T.mjs} +8 -8
- package/dist/{chunk-7CCXEKIK.mjs → chunk-H4YT7JJJ.mjs} +4 -4
- package/dist/{chunk-JAEJOSH5.mjs → chunk-NF7JF2UP.mjs} +2 -2
- package/dist/{chunk-7GMXNAVA.mjs → chunk-PD2SHA7M.mjs} +11 -11
- package/dist/{chunk-2CD4ZQFH.mjs → chunk-R7NMFJFJ.mjs} +2 -2
- package/dist/chunk-SAX775JO.mjs +40 -0
- package/dist/chunk-SAX775JO.mjs.map +1 -0
- package/dist/chunk-UCFP2MA2.mjs +55 -0
- package/dist/chunk-UCFP2MA2.mjs.map +1 -0
- package/dist/{chunk-4RYDS2HX.mjs → chunk-UEIVAJKL.mjs} +2 -2
- package/dist/client/index.d.mts +66 -0
- package/dist/client/index.d.ts +66 -0
- package/dist/client/index.js +82 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +14 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/config/config.mjs +2 -2
- package/dist/config/findAndProcessEnvConfig.mjs +5 -5
- package/dist/config/findAndProcessFileConfig.mjs +6 -6
- package/dist/config/index.mjs +6 -6
- package/dist/config/parseConfigSchema.mjs +3 -3
- package/dist/config/server.mjs +9 -9
- package/dist/feature-flags/index.d.mts +1 -59
- package/dist/feature-flags/index.d.ts +1 -59
- package/dist/feature-flags/index.js +9 -3
- package/dist/feature-flags/index.js.map +1 -1
- package/dist/feature-flags/index.mjs +4 -24
- package/dist/feature-flags/index.mjs.map +1 -1
- package/dist/integration-tests/1/smooai-config/config.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/default.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/development.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/production.aws.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/production.mjs +3 -3
- package/dist/integration-tests/1/smooai-config/staging.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/config.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/default.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/development.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/production.aws.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.mjs +3 -3
- package/dist/integration-tests/2/smooai-config/production.mjs +3 -3
- package/dist/nextjs/index.mjs +3 -3
- package/dist/nextjs/withFeatureFlags.d.mts +41 -0
- package/dist/nextjs/withFeatureFlags.d.ts +41 -0
- package/dist/nextjs/withFeatureFlags.js +79 -0
- package/dist/nextjs/withFeatureFlags.js.map +1 -0
- package/dist/nextjs/withFeatureFlags.mjs +20 -0
- package/dist/nextjs/withFeatureFlags.mjs.map +1 -0
- package/dist/nextjs/withSmooConfig.d.mts +63 -0
- package/dist/nextjs/withSmooConfig.d.ts +63 -0
- package/dist/nextjs/withSmooConfig.js +64 -0
- package/dist/nextjs/withSmooConfig.js.map +1 -0
- package/dist/nextjs/withSmooConfig.mjs +8 -0
- package/dist/nextjs/withSmooConfig.mjs.map +1 -0
- package/dist/platform/server/server.async.mjs +8 -8
- package/dist/platform/server/server.featureFlag.sync.mjs +8 -8
- package/dist/platform/server/server.publicConfig.sync.mjs +8 -8
- package/dist/platform/server/server.secretConfig.sync.mjs +8 -8
- package/dist/platform/server.mjs +8 -8
- package/dist/vite/smooConfigPlugin.d.mts +47 -0
- package/dist/vite/smooConfigPlugin.d.ts +47 -0
- package/dist/vite/smooConfigPlugin.js +60 -0
- package/dist/vite/smooConfigPlugin.js.map +1 -0
- package/dist/vite/smooConfigPlugin.mjs +37 -0
- package/dist/vite/smooConfigPlugin.mjs.map +1 -0
- package/package.json +25 -1
- /package/dist/{chunk-2DYBQ6SF.mjs.map → chunk-43SVVFYE.mjs.map} +0 -0
- /package/dist/{chunk-PCXGCPWC.mjs.map → chunk-6XDO5B2T.mjs.map} +0 -0
- /package/dist/{chunk-7CCXEKIK.mjs.map → chunk-H4YT7JJJ.mjs.map} +0 -0
- /package/dist/{chunk-JAEJOSH5.mjs.map → chunk-NF7JF2UP.mjs.map} +0 -0
- /package/dist/{chunk-7GMXNAVA.mjs.map → chunk-PD2SHA7M.mjs.map} +0 -0
- /package/dist/{chunk-2CD4ZQFH.mjs.map → chunk-R7NMFJFJ.mjs.map} +0 -0
- /package/dist/{chunk-4RYDS2HX.mjs.map → chunk-UEIVAJKL.mjs.map} +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/client/index.ts
|
|
2
|
+
function toUpperSnakeCase(key) {
|
|
3
|
+
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
4
|
+
}
|
|
5
|
+
function getClientFeatureFlag(key) {
|
|
6
|
+
const envKey = toUpperSnakeCase(key);
|
|
7
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : void 0;
|
|
8
|
+
if (nextValue !== void 0) {
|
|
9
|
+
return nextValue === "true" || nextValue === "1";
|
|
10
|
+
}
|
|
11
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : void 0;
|
|
12
|
+
if (viteValue !== void 0) {
|
|
13
|
+
return viteValue === "true" || viteValue === "1";
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
17
|
+
const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];
|
|
18
|
+
if (viteEnvValue !== void 0) {
|
|
19
|
+
return viteEnvValue === "true" || viteEnvValue === "1";
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function getClientPublicConfig(key) {
|
|
26
|
+
const envKey = toUpperSnakeCase(key);
|
|
27
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : void 0;
|
|
28
|
+
if (nextValue !== void 0) {
|
|
29
|
+
return nextValue;
|
|
30
|
+
}
|
|
31
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_CONFIG_${envKey}`] : void 0;
|
|
32
|
+
if (viteValue !== void 0) {
|
|
33
|
+
return viteValue;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
37
|
+
const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];
|
|
38
|
+
if (viteEnvValue !== void 0) {
|
|
39
|
+
return viteEnvValue;
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
function createFeatureFlagChecker() {
|
|
46
|
+
return (key) => getClientFeatureFlag(key);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
toUpperSnakeCase,
|
|
51
|
+
getClientFeatureFlag,
|
|
52
|
+
getClientPublicConfig,
|
|
53
|
+
createFeatureFlagChecker
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-YMNAMX6Y.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts"],"sourcesContent":["/**\n * Universal client-safe config readers.\n *\n * Reads from both `NEXT_PUBLIC_` and `VITE_` prefixed env vars,\n * allowing the same code to work in Next.js and Vite environments.\n *\n * @example\n * ```tsx\n * import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';\n *\n * if (getClientFeatureFlag('aboutPage')) {\n * // show the feature\n * }\n *\n * const apiUrl = getClientPublicConfig('apiBaseUrl');\n * ```\n */\n\n/**\n * Convert a camelCase key to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" → \"ABOUT_PAGE\"\n */\nexport function toUpperSnakeCase(key: string): string {\n return key.replace(/([A-Z])/g, '_$1').toUpperCase();\n}\n\n/**\n * Get a feature flag value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)\n * 2. VITE_FEATURE_FLAG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE\n *\n * @param key - The camelCase feature flag key\n * @returns true if the flag is explicitly set to \"true\", false otherwise\n */\nexport function getClientFeatureFlag(key: string): boolean {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue === 'true' || nextValue === '1';\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue === 'true' || viteValue === '1';\n }\n\n // Check Vite import.meta.env fallback (available via globalThis in some setups)\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue === 'true' || viteEnvValue === '1';\n }\n } catch {\n // Vite env not available\n }\n\n return false;\n}\n\n/**\n * Get a public config value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_CONFIG_{KEY} (Next.js)\n * 2. VITE_CONFIG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"apiBaseUrl\" checks NEXT_PUBLIC_CONFIG_API_BASE_URL\n *\n * @param key - The camelCase config key\n * @returns The config value as a string, or undefined if not set\n */\nexport function getClientPublicConfig(key: string): string | undefined {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue;\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_CONFIG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue;\n }\n\n // Check Vite import.meta.env fallback\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue;\n }\n } catch {\n // Vite env not available\n }\n\n return undefined;\n}\n\n/**\n * Create a typed feature flag checker from a config's FeatureFlagKeys.\n *\n * @example\n * ```tsx\n * import { createFeatureFlagChecker } from '@smooai/config/client';\n *\n * export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();\n *\n * // Usage:\n * getFeatureFlag('aboutPage') // typed to valid keys\n * ```\n */\nexport function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean {\n return (key: T[keyof T]) => getClientFeatureFlag(key as string);\n}\n"],"mappings":";AAsBO,SAAS,iBAAiB,KAAqB;AAClD,SAAO,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AACtD;AAeO,SAAS,qBAAqB,KAAsB;AACvD,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,4BAA4B,MAAM,EAAE,IAAI;AACzG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,qBAAqB,MAAM,EAAE,IAAI;AAClG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,qBAAqB,MAAM,EAAE;AAC5D,QAAI,iBAAiB,QAAW;AAC5B,aAAO,iBAAiB,UAAU,iBAAiB;AAAA,IACvD;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,sBAAsB,KAAiC;AACnE,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,sBAAsB,MAAM,EAAE,IAAI;AACnG,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,eAAe,MAAM,EAAE,IAAI;AAC5F,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,eAAe,MAAM,EAAE;AACtD,QAAI,iBAAiB,QAAW;AAC5B,aAAO;AAAA,IACX;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,2BAA2F;AACvG,SAAO,CAAC,QAAoB,qBAAqB,GAAa;AAClE;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createFeatureFlagChecker,
|
|
3
|
+
getClientFeatureFlag,
|
|
4
|
+
getClientPublicConfig,
|
|
5
|
+
toUpperSnakeCase
|
|
6
|
+
} from "../chunk-YMNAMX6Y.mjs";
|
|
7
|
+
import "../chunk-J5LGTIGS.mjs";
|
|
8
|
+
export {
|
|
9
|
+
createFeatureFlagChecker,
|
|
10
|
+
getClientFeatureFlag,
|
|
11
|
+
getClientPublicConfig,
|
|
12
|
+
toUpperSnakeCase
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,28 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createFeatureFlagChecker,
|
|
3
|
+
getClientFeatureFlag
|
|
4
|
+
} from "../chunk-YMNAMX6Y.mjs";
|
|
1
5
|
import "../chunk-J5LGTIGS.mjs";
|
|
2
|
-
|
|
3
|
-
// src/feature-flags/index.ts
|
|
4
|
-
function toUpperSnakeCase(key) {
|
|
5
|
-
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
6
|
-
}
|
|
7
|
-
function getClientFeatureFlag(key) {
|
|
8
|
-
const envKey = toUpperSnakeCase(key);
|
|
9
|
-
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : void 0;
|
|
10
|
-
if (nextValue !== void 0) {
|
|
11
|
-
return nextValue === "true" || nextValue === "1";
|
|
12
|
-
}
|
|
13
|
-
try {
|
|
14
|
-
const viteEnv = globalThis.__VITE_ENV__;
|
|
15
|
-
const viteValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];
|
|
16
|
-
if (viteValue !== void 0) {
|
|
17
|
-
return viteValue === "true" || viteValue === "1";
|
|
18
|
-
}
|
|
19
|
-
} catch {
|
|
20
|
-
}
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
function createFeatureFlagChecker() {
|
|
24
|
-
return (key) => getClientFeatureFlag(key);
|
|
25
|
-
}
|
|
26
6
|
export {
|
|
27
7
|
createFeatureFlagChecker,
|
|
28
8
|
getClientFeatureFlag
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findAndProcessEnvConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6XDO5B2T.mjs";
|
|
4
4
|
import {
|
|
5
5
|
findAndProcessFileConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PD2SHA7M.mjs";
|
|
7
7
|
|
|
8
8
|
// src/platform/server/server.async.ts
|
|
9
9
|
import TTLCache from "@isaacs/ttlcache";
|
|
@@ -115,4 +115,4 @@ function buildConfigObject(configSchema) {
|
|
|
115
115
|
export {
|
|
116
116
|
buildConfigObject
|
|
117
117
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-43SVVFYE.mjs.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
generateZodSchemas,
|
|
3
|
-
parseConfigKey
|
|
4
|
-
} from "./chunk-JAEJOSH5.mjs";
|
|
5
|
-
import {
|
|
6
|
-
PublicConfigKey
|
|
7
|
-
} from "./chunk-CASNDTCH.mjs";
|
|
8
1
|
import {
|
|
9
2
|
getCloudRegion
|
|
10
3
|
} from "./chunk-5J6U77AV.mjs";
|
|
4
|
+
import {
|
|
5
|
+
generateZodSchemas,
|
|
6
|
+
parseConfigKey
|
|
7
|
+
} from "./chunk-NF7JF2UP.mjs";
|
|
11
8
|
import {
|
|
12
9
|
envToUse,
|
|
13
10
|
initEsmUtils
|
|
14
11
|
} from "./chunk-UWV4ZGVI.mjs";
|
|
12
|
+
import {
|
|
13
|
+
PublicConfigKey
|
|
14
|
+
} from "./chunk-CASNDTCH.mjs";
|
|
15
15
|
|
|
16
16
|
// src/config/findAndProcessEnvConfig.ts
|
|
17
17
|
import Logger from "@smooai/logger/Logger";
|
|
@@ -68,4 +68,4 @@ function setBuiltInConfig(config, {
|
|
|
68
68
|
export {
|
|
69
69
|
findAndProcessEnvConfig
|
|
70
70
|
};
|
|
71
|
-
//# sourceMappingURL=chunk-
|
|
71
|
+
//# sourceMappingURL=chunk-6XDO5B2T.mjs.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
standardSchemaToJson
|
|
3
3
|
} from "./chunk-LPEA3TRJ.mjs";
|
|
4
|
-
import {
|
|
5
|
-
PublicConfigKey
|
|
6
|
-
} from "./chunk-CASNDTCH.mjs";
|
|
7
4
|
import {
|
|
8
5
|
SmooaiConfigError,
|
|
9
6
|
convertKeyToUpperSnakeCase
|
|
10
7
|
} from "./chunk-UWV4ZGVI.mjs";
|
|
8
|
+
import {
|
|
9
|
+
PublicConfigKey
|
|
10
|
+
} from "./chunk-CASNDTCH.mjs";
|
|
11
11
|
import {
|
|
12
12
|
__export
|
|
13
13
|
} from "./chunk-J5LGTIGS.mjs";
|
|
@@ -12191,4 +12191,4 @@ export {
|
|
|
12191
12191
|
generateConfigSchema,
|
|
12192
12192
|
defineConfig
|
|
12193
12193
|
};
|
|
12194
|
-
//# sourceMappingURL=chunk-
|
|
12194
|
+
//# sourceMappingURL=chunk-H4YT7JJJ.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deserializeConfigSchema,
|
|
3
3
|
generateConfigSchema
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-H4YT7JJJ.mjs";
|
|
5
5
|
|
|
6
6
|
// src/config/parseConfigSchema.ts
|
|
7
7
|
import { handleSchemaValidationSync } from "@smooai/utils/validation/standardSchema";
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
parseConfig,
|
|
31
31
|
parseConfigKey
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=chunk-
|
|
33
|
+
//# sourceMappingURL=chunk-NF7JF2UP.mjs.map
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mergeReplaceArrays
|
|
3
|
-
} from "./chunk-VLAIJ4S7.mjs";
|
|
4
1
|
import {
|
|
5
2
|
directoryExists,
|
|
6
3
|
importFile
|
|
7
4
|
} from "./chunk-XKVOJHYW.mjs";
|
|
8
5
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
parseConfigKey
|
|
12
|
-
} from "./chunk-JAEJOSH5.mjs";
|
|
13
|
-
import {
|
|
14
|
-
PublicConfigKey
|
|
15
|
-
} from "./chunk-CASNDTCH.mjs";
|
|
6
|
+
mergeReplaceArrays
|
|
7
|
+
} from "./chunk-VLAIJ4S7.mjs";
|
|
16
8
|
import {
|
|
17
9
|
getCloudRegion
|
|
18
10
|
} from "./chunk-5J6U77AV.mjs";
|
|
11
|
+
import {
|
|
12
|
+
generateZodSchemas,
|
|
13
|
+
parseConfig,
|
|
14
|
+
parseConfigKey
|
|
15
|
+
} from "./chunk-NF7JF2UP.mjs";
|
|
19
16
|
import {
|
|
20
17
|
SmooaiConfigError,
|
|
21
18
|
envToUse,
|
|
22
19
|
initEsmUtils
|
|
23
20
|
} from "./chunk-UWV4ZGVI.mjs";
|
|
21
|
+
import {
|
|
22
|
+
PublicConfigKey
|
|
23
|
+
} from "./chunk-CASNDTCH.mjs";
|
|
24
24
|
|
|
25
25
|
// src/config/findAndProcessFileConfig.ts
|
|
26
26
|
import { join } from "path";
|
|
@@ -170,4 +170,4 @@ export {
|
|
|
170
170
|
findConfigDirectory,
|
|
171
171
|
findAndProcessFileConfig
|
|
172
172
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-PD2SHA7M.mjs.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
StringSchema,
|
|
5
5
|
defineConfig,
|
|
6
6
|
external_exports
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-H4YT7JJJ.mjs";
|
|
8
8
|
|
|
9
9
|
// src/integration-tests/2/smooai-config/config.ts
|
|
10
10
|
var config_default = defineConfig({
|
|
@@ -34,4 +34,4 @@ var config_default = defineConfig({
|
|
|
34
34
|
export {
|
|
35
35
|
config_default
|
|
36
36
|
};
|
|
37
|
-
//# sourceMappingURL=chunk-
|
|
37
|
+
//# sourceMappingURL=chunk-R7NMFJFJ.mjs.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/nextjs/withSmooConfig.ts
|
|
2
|
+
function toUpperSnakeCase(key) {
|
|
3
|
+
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
4
|
+
}
|
|
5
|
+
function withSmooConfig(options, nextConfig = {}) {
|
|
6
|
+
const stage = process.env.NEXT_PUBLIC_SST_STAGE ?? (process.env.NODE_ENV === "production" ? "production" : "development");
|
|
7
|
+
const defaultValues = options.default ?? {};
|
|
8
|
+
const stageOverrides = options[stage] ?? {};
|
|
9
|
+
const resolvedFlags = {
|
|
10
|
+
...defaultValues.featureFlags,
|
|
11
|
+
...stageOverrides.featureFlags
|
|
12
|
+
};
|
|
13
|
+
const resolvedConfig = {
|
|
14
|
+
...defaultValues.publicConfig,
|
|
15
|
+
...stageOverrides.publicConfig
|
|
16
|
+
};
|
|
17
|
+
const env = {};
|
|
18
|
+
for (const [key, value] of Object.entries(resolvedFlags)) {
|
|
19
|
+
const envKey = `NEXT_PUBLIC_FEATURE_FLAG_${toUpperSnakeCase(key)}`;
|
|
20
|
+
env[envKey] = String(value);
|
|
21
|
+
process.env[envKey] = String(value);
|
|
22
|
+
}
|
|
23
|
+
for (const [key, value] of Object.entries(resolvedConfig)) {
|
|
24
|
+
const envKey = `NEXT_PUBLIC_CONFIG_${toUpperSnakeCase(key)}`;
|
|
25
|
+
env[envKey] = String(value);
|
|
26
|
+
process.env[envKey] = String(value);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
...nextConfig,
|
|
30
|
+
env: {
|
|
31
|
+
...nextConfig.env,
|
|
32
|
+
...env
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
withSmooConfig
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=chunk-SAX775JO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/nextjs/withSmooConfig.ts"],"sourcesContent":["/**\n * Next.js config helper that injects feature flags AND public config\n * as NEXT_PUBLIC_ environment variables.\n *\n * This is the unified replacement for `withFeatureFlags`, supporting both\n * feature flags (NEXT_PUBLIC_FEATURE_FLAG_*) and public config values\n * (NEXT_PUBLIC_CONFIG_*).\n *\n * @example\n * ```ts\n * // next.config.ts\n * import { withSmooConfig } from '@smooai/config/nextjs/withSmooConfig';\n *\n * const nextConfig = withSmooConfig({\n * default: {\n * featureFlags: { aboutPage: false, contactPage: true },\n * publicConfig: { apiBaseUrl: 'https://api.smooai.com', maxRetries: 3 },\n * },\n * development: {\n * featureFlags: { aboutPage: true },\n * publicConfig: { apiBaseUrl: 'http://localhost:3000' },\n * },\n * });\n *\n * export default nextConfig;\n * ```\n *\n * This will set environment variables like:\n * - NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE=true (in development)\n * - NEXT_PUBLIC_CONFIG_API_BASE_URL=http://localhost:3000 (in development)\n *\n * Then in any client component:\n * ```tsx\n * import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';\n * const isEnabled = getClientFeatureFlag('aboutPage');\n * const apiUrl = getClientPublicConfig('apiBaseUrl');\n * ```\n */\n\ntype NextConfig = Record<string, unknown>;\n\nexport interface SmooConfigValues {\n /** Feature flag values (boolean). */\n featureFlags?: Record<string, boolean>;\n /** Public config values (string, number, or boolean). */\n publicConfig?: Record<string, string | number | boolean>;\n}\n\nexport interface WithSmooConfigOptions {\n /** Default config values (used in production). */\n default: SmooConfigValues;\n /** Development overrides (merged with default). */\n development?: SmooConfigValues;\n /** Additional stage-specific overrides. Key is the stage name. */\n [stage: string]: SmooConfigValues | undefined;\n}\n\n/**\n * Convert a camelCase key to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" → \"ABOUT_PAGE\"\n */\nfunction toUpperSnakeCase(key: string): string {\n return key.replace(/([A-Z])/g, '_$1').toUpperCase();\n}\n\n/**\n * Wraps a Next.js config to inject feature flags and public config\n * as NEXT_PUBLIC_ environment variables.\n *\n * Reads `NEXT_PUBLIC_SST_STAGE` (or `NODE_ENV`) to determine which config to use.\n * Falls back to development config if stage is not 'production'.\n */\nexport function withSmooConfig(options: WithSmooConfigOptions, nextConfig: NextConfig = {}): NextConfig {\n const stage = process.env.NEXT_PUBLIC_SST_STAGE ?? (process.env.NODE_ENV === 'production' ? 'production' : 'development');\n\n // Merge default with stage-specific overrides\n const defaultValues = options.default ?? {};\n const stageOverrides = options[stage] ?? {};\n\n const resolvedFlags: Record<string, boolean> = {\n ...defaultValues.featureFlags,\n ...stageOverrides.featureFlags,\n };\n\n const resolvedConfig: Record<string, string | number | boolean> = {\n ...defaultValues.publicConfig,\n ...stageOverrides.publicConfig,\n };\n\n // Inject as NEXT_PUBLIC_ env vars\n const env: Record<string, string> = {};\n\n // Feature flags → NEXT_PUBLIC_FEATURE_FLAG_*\n for (const [key, value] of Object.entries(resolvedFlags)) {\n const envKey = `NEXT_PUBLIC_FEATURE_FLAG_${toUpperSnakeCase(key)}`;\n env[envKey] = String(value);\n // Also set in process.env for SSR\n process.env[envKey] = String(value);\n }\n\n // Public config → NEXT_PUBLIC_CONFIG_*\n for (const [key, value] of Object.entries(resolvedConfig)) {\n const envKey = `NEXT_PUBLIC_CONFIG_${toUpperSnakeCase(key)}`;\n env[envKey] = String(value);\n // Also set in process.env for SSR\n process.env[envKey] = String(value);\n }\n\n return {\n ...nextConfig,\n env: {\n ...(nextConfig.env as Record<string, string> | undefined),\n ...env,\n },\n };\n}\n"],"mappings":";AA6DA,SAAS,iBAAiB,KAAqB;AAC3C,SAAO,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AACtD;AASO,SAAS,eAAe,SAAgC,aAAyB,CAAC,GAAe;AACpG,QAAM,QAAQ,QAAQ,IAAI,0BAA0B,QAAQ,IAAI,aAAa,eAAe,eAAe;AAG3G,QAAM,gBAAgB,QAAQ,WAAW,CAAC;AAC1C,QAAM,iBAAiB,QAAQ,KAAK,KAAK,CAAC;AAE1C,QAAM,gBAAyC;AAAA,IAC3C,GAAG,cAAc;AAAA,IACjB,GAAG,eAAe;AAAA,EACtB;AAEA,QAAM,iBAA4D;AAAA,IAC9D,GAAG,cAAc;AAAA,IACjB,GAAG,eAAe;AAAA,EACtB;AAGA,QAAM,MAA8B,CAAC;AAGrC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACtD,UAAM,SAAS,4BAA4B,iBAAiB,GAAG,CAAC;AAChE,QAAI,MAAM,IAAI,OAAO,KAAK;AAE1B,YAAQ,IAAI,MAAM,IAAI,OAAO,KAAK;AAAA,EACtC;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACvD,UAAM,SAAS,sBAAsB,iBAAiB,GAAG,CAAC;AAC1D,QAAI,MAAM,IAAI,OAAO,KAAK;AAE1B,YAAQ,IAAI,MAAM,IAAI,OAAO,KAAK;AAAA,EACtC;AAEA,SAAO;AAAA,IACH,GAAG;AAAA,IACH,KAAK;AAAA,MACD,GAAI,WAAW;AAAA,MACf,GAAG;AAAA,IACP;AAAA,EACJ;AACJ;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/client/index.ts
|
|
2
|
+
function toUpperSnakeCase(key) {
|
|
3
|
+
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
4
|
+
}
|
|
5
|
+
function getClientFeatureFlag(key) {
|
|
6
|
+
const envKey = toUpperSnakeCase(key);
|
|
7
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : void 0;
|
|
8
|
+
if (nextValue !== void 0) {
|
|
9
|
+
return nextValue === "true" || nextValue === "1";
|
|
10
|
+
}
|
|
11
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : void 0;
|
|
12
|
+
if (viteValue !== void 0) {
|
|
13
|
+
return viteValue === "true" || viteValue === "1";
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
17
|
+
const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];
|
|
18
|
+
if (viteEnvValue !== void 0) {
|
|
19
|
+
return viteEnvValue === "true" || viteEnvValue === "1";
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function getClientPublicConfig(key) {
|
|
26
|
+
const envKey = toUpperSnakeCase(key);
|
|
27
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : void 0;
|
|
28
|
+
if (nextValue !== void 0) {
|
|
29
|
+
return nextValue;
|
|
30
|
+
}
|
|
31
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_CONFIG_${envKey}`] : void 0;
|
|
32
|
+
if (viteValue !== void 0) {
|
|
33
|
+
return viteValue;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
37
|
+
const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];
|
|
38
|
+
if (viteEnvValue !== void 0) {
|
|
39
|
+
return viteEnvValue;
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
function createFeatureFlagChecker() {
|
|
46
|
+
return (key) => getClientFeatureFlag(key);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
toUpperSnakeCase,
|
|
51
|
+
getClientFeatureFlag,
|
|
52
|
+
getClientPublicConfig,
|
|
53
|
+
createFeatureFlagChecker
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-UCFP2MA2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/index.ts"],"sourcesContent":["/**\n * Universal client-safe config readers.\n *\n * Reads from both `NEXT_PUBLIC_` and `VITE_` prefixed env vars,\n * allowing the same code to work in Next.js and Vite environments.\n *\n * @example\n * ```tsx\n * import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';\n *\n * if (getClientFeatureFlag('aboutPage')) {\n * // show the feature\n * }\n *\n * const apiUrl = getClientPublicConfig('apiBaseUrl');\n * ```\n */\n\n/**\n * Convert a camelCase key to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" → \"ABOUT_PAGE\"\n */\nexport function toUpperSnakeCase(key: string): string {\n return key.replace(/([A-Z])/g, '_$1').toUpperCase();\n}\n\n/**\n * Get a feature flag value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)\n * 2. VITE_FEATURE_FLAG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE\n *\n * @param key - The camelCase feature flag key\n * @returns true if the flag is explicitly set to \"true\", false otherwise\n */\nexport function getClientFeatureFlag(key: string): boolean {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue === 'true' || nextValue === '1';\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue === 'true' || viteValue === '1';\n }\n\n // Check Vite import.meta.env fallback (available via globalThis in some setups)\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue === 'true' || viteEnvValue === '1';\n }\n } catch {\n // Vite env not available\n }\n\n return false;\n}\n\n/**\n * Get a public config value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_CONFIG_{KEY} (Next.js)\n * 2. VITE_CONFIG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"apiBaseUrl\" checks NEXT_PUBLIC_CONFIG_API_BASE_URL\n *\n * @param key - The camelCase config key\n * @returns The config value as a string, or undefined if not set\n */\nexport function getClientPublicConfig(key: string): string | undefined {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue;\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_CONFIG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue;\n }\n\n // Check Vite import.meta.env fallback\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue;\n }\n } catch {\n // Vite env not available\n }\n\n return undefined;\n}\n\n/**\n * Create a typed feature flag checker from a config's FeatureFlagKeys.\n *\n * @example\n * ```tsx\n * import { createFeatureFlagChecker } from '@smooai/config/client';\n *\n * export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();\n *\n * // Usage:\n * getFeatureFlag('aboutPage') // typed to valid keys\n * ```\n */\nexport function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean {\n return (key: T[keyof T]) => getClientFeatureFlag(key as string);\n}\n"],"mappings":";AAsBO,SAAS,iBAAiB,KAAqB;AAClD,SAAO,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AACtD;AAeO,SAAS,qBAAqB,KAAsB;AACvD,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,4BAA4B,MAAM,EAAE,IAAI;AACzG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,qBAAqB,MAAM,EAAE,IAAI;AAClG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,qBAAqB,MAAM,EAAE;AAC5D,QAAI,iBAAiB,QAAW;AAC5B,aAAO,iBAAiB,UAAU,iBAAiB;AAAA,IACvD;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,sBAAsB,KAAiC;AACnE,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,sBAAsB,MAAM,EAAE,IAAI;AACnG,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,eAAe,MAAM,EAAE,IAAI;AAC5F,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,eAAe,MAAM,EAAE;AACtD,QAAI,iBAAiB,QAAW;AAC5B,aAAO;AAAA,IACX;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,2BAA2F;AACvG,SAAO,CAAC,QAAoB,qBAAqB,GAAa;AAClE;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
StringSchema,
|
|
5
5
|
defineConfig,
|
|
6
6
|
external_exports
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-H4YT7JJJ.mjs";
|
|
8
8
|
|
|
9
9
|
// src/integration-tests/1/smooai-config/config.ts
|
|
10
10
|
var config_default = defineConfig({
|
|
@@ -86,4 +86,4 @@ var config_default = defineConfig({
|
|
|
86
86
|
export {
|
|
87
87
|
config_default
|
|
88
88
|
};
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
89
|
+
//# sourceMappingURL=chunk-UEIVAJKL.mjs.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal client-safe config readers.
|
|
3
|
+
*
|
|
4
|
+
* Reads from both `NEXT_PUBLIC_` and `VITE_` prefixed env vars,
|
|
5
|
+
* allowing the same code to work in Next.js and Vite environments.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';
|
|
10
|
+
*
|
|
11
|
+
* if (getClientFeatureFlag('aboutPage')) {
|
|
12
|
+
* // show the feature
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* const apiUrl = getClientPublicConfig('apiBaseUrl');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Convert a camelCase key to UPPER_SNAKE_CASE.
|
|
20
|
+
* e.g., "aboutPage" → "ABOUT_PAGE"
|
|
21
|
+
*/
|
|
22
|
+
declare function toUpperSnakeCase(key: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get a feature flag value from build-time environment variables.
|
|
25
|
+
*
|
|
26
|
+
* Checks for:
|
|
27
|
+
* 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)
|
|
28
|
+
* 2. VITE_FEATURE_FLAG_{KEY} (Vite)
|
|
29
|
+
*
|
|
30
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
31
|
+
* e.g., "aboutPage" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE
|
|
32
|
+
*
|
|
33
|
+
* @param key - The camelCase feature flag key
|
|
34
|
+
* @returns true if the flag is explicitly set to "true", false otherwise
|
|
35
|
+
*/
|
|
36
|
+
declare function getClientFeatureFlag(key: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get a public config value from build-time environment variables.
|
|
39
|
+
*
|
|
40
|
+
* Checks for:
|
|
41
|
+
* 1. NEXT_PUBLIC_CONFIG_{KEY} (Next.js)
|
|
42
|
+
* 2. VITE_CONFIG_{KEY} (Vite)
|
|
43
|
+
*
|
|
44
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
45
|
+
* e.g., "apiBaseUrl" checks NEXT_PUBLIC_CONFIG_API_BASE_URL
|
|
46
|
+
*
|
|
47
|
+
* @param key - The camelCase config key
|
|
48
|
+
* @returns The config value as a string, or undefined if not set
|
|
49
|
+
*/
|
|
50
|
+
declare function getClientPublicConfig(key: string): string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Create a typed feature flag checker from a config's FeatureFlagKeys.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* import { createFeatureFlagChecker } from '@smooai/config/client';
|
|
57
|
+
*
|
|
58
|
+
* export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();
|
|
59
|
+
*
|
|
60
|
+
* // Usage:
|
|
61
|
+
* getFeatureFlag('aboutPage') // typed to valid keys
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean;
|
|
65
|
+
|
|
66
|
+
export { createFeatureFlagChecker, getClientFeatureFlag, getClientPublicConfig, toUpperSnakeCase };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal client-safe config readers.
|
|
3
|
+
*
|
|
4
|
+
* Reads from both `NEXT_PUBLIC_` and `VITE_` prefixed env vars,
|
|
5
|
+
* allowing the same code to work in Next.js and Vite environments.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';
|
|
10
|
+
*
|
|
11
|
+
* if (getClientFeatureFlag('aboutPage')) {
|
|
12
|
+
* // show the feature
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* const apiUrl = getClientPublicConfig('apiBaseUrl');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Convert a camelCase key to UPPER_SNAKE_CASE.
|
|
20
|
+
* e.g., "aboutPage" → "ABOUT_PAGE"
|
|
21
|
+
*/
|
|
22
|
+
declare function toUpperSnakeCase(key: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get a feature flag value from build-time environment variables.
|
|
25
|
+
*
|
|
26
|
+
* Checks for:
|
|
27
|
+
* 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)
|
|
28
|
+
* 2. VITE_FEATURE_FLAG_{KEY} (Vite)
|
|
29
|
+
*
|
|
30
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
31
|
+
* e.g., "aboutPage" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE
|
|
32
|
+
*
|
|
33
|
+
* @param key - The camelCase feature flag key
|
|
34
|
+
* @returns true if the flag is explicitly set to "true", false otherwise
|
|
35
|
+
*/
|
|
36
|
+
declare function getClientFeatureFlag(key: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get a public config value from build-time environment variables.
|
|
39
|
+
*
|
|
40
|
+
* Checks for:
|
|
41
|
+
* 1. NEXT_PUBLIC_CONFIG_{KEY} (Next.js)
|
|
42
|
+
* 2. VITE_CONFIG_{KEY} (Vite)
|
|
43
|
+
*
|
|
44
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
45
|
+
* e.g., "apiBaseUrl" checks NEXT_PUBLIC_CONFIG_API_BASE_URL
|
|
46
|
+
*
|
|
47
|
+
* @param key - The camelCase config key
|
|
48
|
+
* @returns The config value as a string, or undefined if not set
|
|
49
|
+
*/
|
|
50
|
+
declare function getClientPublicConfig(key: string): string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Create a typed feature flag checker from a config's FeatureFlagKeys.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* import { createFeatureFlagChecker } from '@smooai/config/client';
|
|
57
|
+
*
|
|
58
|
+
* export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();
|
|
59
|
+
*
|
|
60
|
+
* // Usage:
|
|
61
|
+
* getFeatureFlag('aboutPage') // typed to valid keys
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean;
|
|
65
|
+
|
|
66
|
+
export { createFeatureFlagChecker, getClientFeatureFlag, getClientPublicConfig, toUpperSnakeCase };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/client/index.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
createFeatureFlagChecker: () => createFeatureFlagChecker,
|
|
24
|
+
getClientFeatureFlag: () => getClientFeatureFlag,
|
|
25
|
+
getClientPublicConfig: () => getClientPublicConfig,
|
|
26
|
+
toUpperSnakeCase: () => toUpperSnakeCase
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(client_exports);
|
|
29
|
+
function toUpperSnakeCase(key) {
|
|
30
|
+
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
31
|
+
}
|
|
32
|
+
function getClientFeatureFlag(key) {
|
|
33
|
+
const envKey = toUpperSnakeCase(key);
|
|
34
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : void 0;
|
|
35
|
+
if (nextValue !== void 0) {
|
|
36
|
+
return nextValue === "true" || nextValue === "1";
|
|
37
|
+
}
|
|
38
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : void 0;
|
|
39
|
+
if (viteValue !== void 0) {
|
|
40
|
+
return viteValue === "true" || viteValue === "1";
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
44
|
+
const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];
|
|
45
|
+
if (viteEnvValue !== void 0) {
|
|
46
|
+
return viteEnvValue === "true" || viteEnvValue === "1";
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
function getClientPublicConfig(key) {
|
|
53
|
+
const envKey = toUpperSnakeCase(key);
|
|
54
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : void 0;
|
|
55
|
+
if (nextValue !== void 0) {
|
|
56
|
+
return nextValue;
|
|
57
|
+
}
|
|
58
|
+
const viteValue = typeof process !== "undefined" ? process.env?.[`VITE_CONFIG_${envKey}`] : void 0;
|
|
59
|
+
if (viteValue !== void 0) {
|
|
60
|
+
return viteValue;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
64
|
+
const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];
|
|
65
|
+
if (viteEnvValue !== void 0) {
|
|
66
|
+
return viteEnvValue;
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
return void 0;
|
|
71
|
+
}
|
|
72
|
+
function createFeatureFlagChecker() {
|
|
73
|
+
return (key) => getClientFeatureFlag(key);
|
|
74
|
+
}
|
|
75
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
76
|
+
0 && (module.exports = {
|
|
77
|
+
createFeatureFlagChecker,
|
|
78
|
+
getClientFeatureFlag,
|
|
79
|
+
getClientPublicConfig,
|
|
80
|
+
toUpperSnakeCase
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts"],"sourcesContent":["/**\n * Universal client-safe config readers.\n *\n * Reads from both `NEXT_PUBLIC_` and `VITE_` prefixed env vars,\n * allowing the same code to work in Next.js and Vite environments.\n *\n * @example\n * ```tsx\n * import { getClientFeatureFlag, getClientPublicConfig } from '@smooai/config/client';\n *\n * if (getClientFeatureFlag('aboutPage')) {\n * // show the feature\n * }\n *\n * const apiUrl = getClientPublicConfig('apiBaseUrl');\n * ```\n */\n\n/**\n * Convert a camelCase key to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" → \"ABOUT_PAGE\"\n */\nexport function toUpperSnakeCase(key: string): string {\n return key.replace(/([A-Z])/g, '_$1').toUpperCase();\n}\n\n/**\n * Get a feature flag value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)\n * 2. VITE_FEATURE_FLAG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"aboutPage\" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE\n *\n * @param key - The camelCase feature flag key\n * @returns true if the flag is explicitly set to \"true\", false otherwise\n */\nexport function getClientFeatureFlag(key: string): boolean {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue === 'true' || nextValue === '1';\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_FEATURE_FLAG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue === 'true' || viteValue === '1';\n }\n\n // Check Vite import.meta.env fallback (available via globalThis in some setups)\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue === 'true' || viteEnvValue === '1';\n }\n } catch {\n // Vite env not available\n }\n\n return false;\n}\n\n/**\n * Get a public config value from build-time environment variables.\n *\n * Checks for:\n * 1. NEXT_PUBLIC_CONFIG_{KEY} (Next.js)\n * 2. VITE_CONFIG_{KEY} (Vite)\n *\n * The key is converted from camelCase to UPPER_SNAKE_CASE.\n * e.g., \"apiBaseUrl\" checks NEXT_PUBLIC_CONFIG_API_BASE_URL\n *\n * @param key - The camelCase config key\n * @returns The config value as a string, or undefined if not set\n */\nexport function getClientPublicConfig(key: string): string | undefined {\n const envKey = toUpperSnakeCase(key);\n\n // Check Next.js env var\n const nextValue = typeof process !== 'undefined' ? process.env?.[`NEXT_PUBLIC_CONFIG_${envKey}`] : undefined;\n if (nextValue !== undefined) {\n return nextValue;\n }\n\n // Check Vite env var\n const viteValue = typeof process !== 'undefined' ? process.env?.[`VITE_CONFIG_${envKey}`] : undefined;\n if (viteValue !== undefined) {\n return viteValue;\n }\n\n // Check Vite import.meta.env fallback\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteEnvValue = viteEnv?.[`VITE_CONFIG_${envKey}`];\n if (viteEnvValue !== undefined) {\n return viteEnvValue;\n }\n } catch {\n // Vite env not available\n }\n\n return undefined;\n}\n\n/**\n * Create a typed feature flag checker from a config's FeatureFlagKeys.\n *\n * @example\n * ```tsx\n * import { createFeatureFlagChecker } from '@smooai/config/client';\n *\n * export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();\n *\n * // Usage:\n * getFeatureFlag('aboutPage') // typed to valid keys\n * ```\n */\nexport function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean {\n return (key: T[keyof T]) => getClientFeatureFlag(key as string);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,SAAS,iBAAiB,KAAqB;AAClD,SAAO,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AACtD;AAeO,SAAS,qBAAqB,KAAsB;AACvD,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,4BAA4B,MAAM,EAAE,IAAI;AACzG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,qBAAqB,MAAM,EAAE,IAAI;AAClG,MAAI,cAAc,QAAW;AACzB,WAAO,cAAc,UAAU,cAAc;AAAA,EACjD;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,qBAAqB,MAAM,EAAE;AAC5D,QAAI,iBAAiB,QAAW;AAC5B,aAAO,iBAAiB,UAAU,iBAAiB;AAAA,IACvD;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,sBAAsB,KAAiC;AACnE,QAAM,SAAS,iBAAiB,GAAG;AAGnC,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,sBAAsB,MAAM,EAAE,IAAI;AACnG,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,QAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,MAAM,eAAe,MAAM,EAAE,IAAI;AAC5F,MAAI,cAAc,QAAW;AACzB,WAAO;AAAA,EACX;AAGA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,eAAe,UAAU,eAAe,MAAM,EAAE;AACtD,QAAI,iBAAiB,QAAW;AAC5B,aAAO;AAAA,IACX;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAeO,SAAS,2BAA2F;AACvG,SAAO,CAAC,QAAoB,qBAAqB,GAAa;AAClE;","names":[]}
|