@smooai/config 2.1.4 → 2.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.
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-safe feature flag utilities.
|
|
3
|
+
*
|
|
4
|
+
* These functions read feature flags from build-time environment variables
|
|
5
|
+
* (NEXT_PUBLIC_FEATURE_FLAG_* or VITE_FEATURE_FLAG_*) and can be used
|
|
6
|
+
* in both server and client components.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // In your .smooai-config/config.ts:
|
|
11
|
+
* const config = defineConfig({
|
|
12
|
+
* featureFlagSchema: {
|
|
13
|
+
* aboutPage: BooleanSchema,
|
|
14
|
+
* contactPage: BooleanSchema,
|
|
15
|
+
* },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // In your next.config.js, inject flags as env vars:
|
|
19
|
+
* // NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE=true
|
|
20
|
+
*
|
|
21
|
+
* // In any component (server or client):
|
|
22
|
+
* import { getClientFeatureFlag } from '@smooai/config/feature-flags';
|
|
23
|
+
*
|
|
24
|
+
* if (getClientFeatureFlag('aboutPage')) {
|
|
25
|
+
* // show the feature
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Get a feature flag value from build-time environment variables.
|
|
31
|
+
*
|
|
32
|
+
* Checks for:
|
|
33
|
+
* 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)
|
|
34
|
+
* 2. VITE_FEATURE_FLAG_{KEY} (Vite)
|
|
35
|
+
*
|
|
36
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
37
|
+
* e.g., "aboutPage" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE
|
|
38
|
+
*
|
|
39
|
+
* @param key - The camelCase feature flag key
|
|
40
|
+
* @returns true if the flag is explicitly set to "true", false otherwise
|
|
41
|
+
*/
|
|
42
|
+
declare function getClientFeatureFlag(key: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Create a typed feature flag checker from a config's FeatureFlagKeys.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import config, { FeatureFlagKeys } from '../.smooai-config/config';
|
|
49
|
+
* import { createFeatureFlagChecker } from '@smooai/config/feature-flags';
|
|
50
|
+
*
|
|
51
|
+
* export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();
|
|
52
|
+
*
|
|
53
|
+
* // Usage:
|
|
54
|
+
* getFeatureFlag('aboutPage') // typed to valid keys
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean;
|
|
58
|
+
|
|
59
|
+
export { createFeatureFlagChecker, getClientFeatureFlag };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-safe feature flag utilities.
|
|
3
|
+
*
|
|
4
|
+
* These functions read feature flags from build-time environment variables
|
|
5
|
+
* (NEXT_PUBLIC_FEATURE_FLAG_* or VITE_FEATURE_FLAG_*) and can be used
|
|
6
|
+
* in both server and client components.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // In your .smooai-config/config.ts:
|
|
11
|
+
* const config = defineConfig({
|
|
12
|
+
* featureFlagSchema: {
|
|
13
|
+
* aboutPage: BooleanSchema,
|
|
14
|
+
* contactPage: BooleanSchema,
|
|
15
|
+
* },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // In your next.config.js, inject flags as env vars:
|
|
19
|
+
* // NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE=true
|
|
20
|
+
*
|
|
21
|
+
* // In any component (server or client):
|
|
22
|
+
* import { getClientFeatureFlag } from '@smooai/config/feature-flags';
|
|
23
|
+
*
|
|
24
|
+
* if (getClientFeatureFlag('aboutPage')) {
|
|
25
|
+
* // show the feature
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Get a feature flag value from build-time environment variables.
|
|
31
|
+
*
|
|
32
|
+
* Checks for:
|
|
33
|
+
* 1. NEXT_PUBLIC_FEATURE_FLAG_{KEY} (Next.js)
|
|
34
|
+
* 2. VITE_FEATURE_FLAG_{KEY} (Vite)
|
|
35
|
+
*
|
|
36
|
+
* The key is converted from camelCase to UPPER_SNAKE_CASE.
|
|
37
|
+
* e.g., "aboutPage" checks NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE
|
|
38
|
+
*
|
|
39
|
+
* @param key - The camelCase feature flag key
|
|
40
|
+
* @returns true if the flag is explicitly set to "true", false otherwise
|
|
41
|
+
*/
|
|
42
|
+
declare function getClientFeatureFlag(key: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Create a typed feature flag checker from a config's FeatureFlagKeys.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import config, { FeatureFlagKeys } from '../.smooai-config/config';
|
|
49
|
+
* import { createFeatureFlagChecker } from '@smooai/config/feature-flags';
|
|
50
|
+
*
|
|
51
|
+
* export const getFeatureFlag = createFeatureFlagChecker<typeof FeatureFlagKeys>();
|
|
52
|
+
*
|
|
53
|
+
* // Usage:
|
|
54
|
+
* getFeatureFlag('aboutPage') // typed to valid keys
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function createFeatureFlagChecker<T extends Record<string, string>>(): (key: T[keyof T]) => boolean;
|
|
58
|
+
|
|
59
|
+
export { createFeatureFlagChecker, getClientFeatureFlag };
|
|
@@ -0,0 +1,54 @@
|
|
|
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/feature-flags/index.ts
|
|
21
|
+
var feature_flags_exports = {};
|
|
22
|
+
__export(feature_flags_exports, {
|
|
23
|
+
createFeatureFlagChecker: () => createFeatureFlagChecker,
|
|
24
|
+
getClientFeatureFlag: () => getClientFeatureFlag
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(feature_flags_exports);
|
|
27
|
+
function toUpperSnakeCase(key) {
|
|
28
|
+
return key.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
29
|
+
}
|
|
30
|
+
function getClientFeatureFlag(key) {
|
|
31
|
+
const envKey = toUpperSnakeCase(key);
|
|
32
|
+
const nextValue = typeof process !== "undefined" ? process.env?.[`NEXT_PUBLIC_FEATURE_FLAG_${envKey}`] : void 0;
|
|
33
|
+
if (nextValue !== void 0) {
|
|
34
|
+
return nextValue === "true" || nextValue === "1";
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const viteEnv = globalThis.__VITE_ENV__;
|
|
38
|
+
const viteValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];
|
|
39
|
+
if (viteValue !== void 0) {
|
|
40
|
+
return viteValue === "true" || viteValue === "1";
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
function createFeatureFlagChecker() {
|
|
47
|
+
return (key) => getClientFeatureFlag(key);
|
|
48
|
+
}
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
createFeatureFlagChecker,
|
|
52
|
+
getClientFeatureFlag
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/feature-flags/index.ts"],"sourcesContent":["/**\n * Client-safe feature flag utilities.\n *\n * These functions read feature flags from build-time environment variables\n * (NEXT_PUBLIC_FEATURE_FLAG_* or VITE_FEATURE_FLAG_*) and can be used\n * in both server and client components.\n *\n * @example\n * ```tsx\n * // In your .smooai-config/config.ts:\n * const config = defineConfig({\n * featureFlagSchema: {\n * aboutPage: BooleanSchema,\n * contactPage: BooleanSchema,\n * },\n * });\n *\n * // In your next.config.js, inject flags as env vars:\n * // NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE=true\n *\n * // In any component (server or client):\n * import { getClientFeatureFlag } from '@smooai/config/feature-flags';\n *\n * if (getClientFeatureFlag('aboutPage')) {\n * // show the feature\n * }\n * ```\n */\n\n/**\n * Convert a camelCase feature flag 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 * 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 (available via import.meta.env in Vite)\n // At build time, Vite replaces import.meta.env.VITE_* with literal values\n // We use a dynamic approach for runtime compatibility\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];\n if (viteValue !== undefined) {\n return viteValue === 'true' || viteValue === '1';\n }\n } catch {\n // Vite env not available\n }\n\n return false;\n}\n\n/**\n * Create a typed feature flag checker from a config's FeatureFlagKeys.\n *\n * @example\n * ```tsx\n * import config, { FeatureFlagKeys } from '../.smooai-config/config';\n * import { createFeatureFlagChecker } from '@smooai/config/feature-flags';\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;AAiCA,SAAS,iBAAiB,KAAqB;AAC3C,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;AAKA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,YAAY,UAAU,qBAAqB,MAAM,EAAE;AACzD,QAAI,cAAc,QAAW;AACzB,aAAO,cAAc,UAAU,cAAc;AAAA,IACjD;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAgBO,SAAS,2BAA2F;AACvG,SAAO,CAAC,QAAoB,qBAAqB,GAAa;AAClE;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
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
|
+
export {
|
|
27
|
+
createFeatureFlagChecker,
|
|
28
|
+
getClientFeatureFlag
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/feature-flags/index.ts"],"sourcesContent":["/**\n * Client-safe feature flag utilities.\n *\n * These functions read feature flags from build-time environment variables\n * (NEXT_PUBLIC_FEATURE_FLAG_* or VITE_FEATURE_FLAG_*) and can be used\n * in both server and client components.\n *\n * @example\n * ```tsx\n * // In your .smooai-config/config.ts:\n * const config = defineConfig({\n * featureFlagSchema: {\n * aboutPage: BooleanSchema,\n * contactPage: BooleanSchema,\n * },\n * });\n *\n * // In your next.config.js, inject flags as env vars:\n * // NEXT_PUBLIC_FEATURE_FLAG_ABOUT_PAGE=true\n *\n * // In any component (server or client):\n * import { getClientFeatureFlag } from '@smooai/config/feature-flags';\n *\n * if (getClientFeatureFlag('aboutPage')) {\n * // show the feature\n * }\n * ```\n */\n\n/**\n * Convert a camelCase feature flag 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 * 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 (available via import.meta.env in Vite)\n // At build time, Vite replaces import.meta.env.VITE_* with literal values\n // We use a dynamic approach for runtime compatibility\n try {\n const viteEnv = (globalThis as Record<string, unknown>).__VITE_ENV__ as Record<string, string> | undefined;\n const viteValue = viteEnv?.[`VITE_FEATURE_FLAG_${envKey}`];\n if (viteValue !== undefined) {\n return viteValue === 'true' || viteValue === '1';\n }\n } catch {\n // Vite env not available\n }\n\n return false;\n}\n\n/**\n * Create a typed feature flag checker from a config's FeatureFlagKeys.\n *\n * @example\n * ```tsx\n * import config, { FeatureFlagKeys } from '../.smooai-config/config';\n * import { createFeatureFlagChecker } from '@smooai/config/feature-flags';\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":";;;AAiCA,SAAS,iBAAiB,KAAqB;AAC3C,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;AAKA,MAAI;AACA,UAAM,UAAW,WAAuC;AACxD,UAAM,YAAY,UAAU,qBAAqB,MAAM,EAAE;AACzD,QAAI,cAAc,QAAW;AACzB,aAAO,cAAc,UAAU,cAAc;AAAA,IACjD;AAAA,EACJ,QAAQ;AAAA,EAER;AAEA,SAAO;AACX;AAgBO,SAAS,2BAA2F;AACvG,SAAO,CAAC,QAAoB,qBAAqB,GAAa;AAClE;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smooai/config",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "Type-safe multi-language configuration management with schema validation, three-tier config (public, secret, feature flags), and runtime client support for TypeScript, Python, Rust, and Go.",
|
|
5
5
|
"homepage": "https://github.com/SmooAI/config#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
"import": "./dist/nextjs/getConfig.mjs",
|
|
48
48
|
"require": "./dist/nextjs/getConfig.js"
|
|
49
49
|
},
|
|
50
|
+
"./feature-flags": {
|
|
51
|
+
"types": "./dist/feature-flags/index.d.ts",
|
|
52
|
+
"import": "./dist/feature-flags/index.mjs",
|
|
53
|
+
"require": "./dist/feature-flags/index.js"
|
|
54
|
+
},
|
|
50
55
|
"./react": {
|
|
51
56
|
"types": "./dist/react/index.d.ts",
|
|
52
57
|
"import": "./dist/react/index.mjs",
|