@smooai/config 2.0.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/LICENSE +21 -0
- package/README.md +430 -0
- package/dist/chunk-3SU3SMKN.mjs +73 -0
- package/dist/chunk-3SU3SMKN.mjs.map +1 -0
- package/dist/chunk-CASNDTCH.mjs +12 -0
- package/dist/chunk-CASNDTCH.mjs.map +1 -0
- package/dist/chunk-GLLYQ6FK.mjs +173 -0
- package/dist/chunk-GLLYQ6FK.mjs.map +1 -0
- package/dist/chunk-HPSOF46N.mjs +71 -0
- package/dist/chunk-HPSOF46N.mjs.map +1 -0
- package/dist/chunk-HPXCKD6M.mjs +118 -0
- package/dist/chunk-HPXCKD6M.mjs.map +1 -0
- package/dist/chunk-J5LGTIGS.mjs +10 -0
- package/dist/chunk-J5LGTIGS.mjs.map +1 -0
- package/dist/chunk-LKV73SD2.mjs +25 -0
- package/dist/chunk-LKV73SD2.mjs.map +1 -0
- package/dist/chunk-MJ52ZIWV.mjs +98 -0
- package/dist/chunk-MJ52ZIWV.mjs.map +1 -0
- package/dist/chunk-O7BSFCCY.mjs +89 -0
- package/dist/chunk-O7BSFCCY.mjs.map +1 -0
- package/dist/chunk-QBM74JB5.mjs +47 -0
- package/dist/chunk-QBM74JB5.mjs.map +1 -0
- package/dist/chunk-QGMLTMB5.mjs +37 -0
- package/dist/chunk-QGMLTMB5.mjs.map +1 -0
- package/dist/chunk-SKX7CPGS.mjs +73 -0
- package/dist/chunk-SKX7CPGS.mjs.map +1 -0
- package/dist/chunk-VPKO6D4W.mjs +33 -0
- package/dist/chunk-VPKO6D4W.mjs.map +1 -0
- package/dist/chunk-YQWYYS7P.mjs +12194 -0
- package/dist/chunk-YQWYYS7P.mjs.map +1 -0
- package/dist/chunk-Z3CZGNU5.mjs +99 -0
- package/dist/chunk-Z3CZGNU5.mjs.map +1 -0
- package/dist/chunk-ZOKHXR5I.mjs +33 -0
- package/dist/chunk-ZOKHXR5I.mjs.map +1 -0
- package/dist/cli.mjs +1562 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/config/FeatureFlagKey.d.mts +24 -0
- package/dist/config/FeatureFlagKey.d.ts +24 -0
- package/dist/config/FeatureFlagKey.js +31 -0
- package/dist/config/FeatureFlagKey.js.map +1 -0
- package/dist/config/FeatureFlagKey.mjs +8 -0
- package/dist/config/FeatureFlagKey.mjs.map +1 -0
- package/dist/config/PublicConfigKey.d.mts +22 -0
- package/dist/config/PublicConfigKey.d.ts +22 -0
- package/dist/config/PublicConfigKey.js +36 -0
- package/dist/config/PublicConfigKey.js.map +1 -0
- package/dist/config/PublicConfigKey.mjs +8 -0
- package/dist/config/PublicConfigKey.mjs.map +1 -0
- package/dist/config/SecretConfigKey.d.mts +22 -0
- package/dist/config/SecretConfigKey.d.ts +22 -0
- package/dist/config/SecretConfigKey.js +31 -0
- package/dist/config/SecretConfigKey.js.map +1 -0
- package/dist/config/SecretConfigKey.mjs +8 -0
- package/dist/config/SecretConfigKey.mjs.map +1 -0
- package/dist/config/config.d.mts +178 -0
- package/dist/config/config.d.ts +178 -0
- package/dist/config/config.js +12364 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/config.mjs +23 -0
- package/dist/config/config.mjs.map +1 -0
- package/dist/config/findAndProcessEnvConfig.d.mts +17 -0
- package/dist/config/findAndProcessEnvConfig.d.ts +17 -0
- package/dist/config/findAndProcessEnvConfig.js +12290 -0
- package/dist/config/findAndProcessEnvConfig.js.map +1 -0
- package/dist/config/findAndProcessEnvConfig.mjs +14 -0
- package/dist/config/findAndProcessEnvConfig.mjs.map +1 -0
- package/dist/config/findAndProcessFileConfig.d.mts +38 -0
- package/dist/config/findAndProcessFileConfig.d.ts +38 -0
- package/dist/config/findAndProcessFileConfig.js +12431 -0
- package/dist/config/findAndProcessFileConfig.js.map +1 -0
- package/dist/config/findAndProcessFileConfig.mjs +18 -0
- package/dist/config/findAndProcessFileConfig.mjs.map +1 -0
- package/dist/config/getCloudRegion.d.mts +8 -0
- package/dist/config/getCloudRegion.d.ts +8 -0
- package/dist/config/getCloudRegion.js +92 -0
- package/dist/config/getCloudRegion.js.map +1 -0
- package/dist/config/getCloudRegion.mjs +9 -0
- package/dist/config/getCloudRegion.mjs.map +1 -0
- package/dist/config/index.d.mts +5 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +12638 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +33 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/config/parseConfigSchema.d.mts +13 -0
- package/dist/config/parseConfigSchema.d.ts +13 -0
- package/dist/config/parseConfigSchema.js +12177 -0
- package/dist/config/parseConfigSchema.js.map +1 -0
- package/dist/config/parseConfigSchema.mjs +16 -0
- package/dist/config/parseConfigSchema.mjs.map +1 -0
- package/dist/config/standardSchemaToJson.d.mts +6 -0
- package/dist/config/standardSchemaToJson.d.ts +6 -0
- package/dist/config/standardSchemaToJson.js +138 -0
- package/dist/config/standardSchemaToJson.js.map +1 -0
- package/dist/config/standardSchemaToJson.mjs +9 -0
- package/dist/config/standardSchemaToJson.mjs.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/config.d.mts +4108 -0
- package/dist/integration-tests/1/smooai-config/config.d.ts +4108 -0
- package/dist/integration-tests/1/smooai-config/config.js +12353 -0
- package/dist/integration-tests/1/smooai-config/config.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/config.mjs +12 -0
- package/dist/integration-tests/1/smooai-config/config.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/default.d.mts +55 -0
- package/dist/integration-tests/1/smooai-config/default.d.ts +55 -0
- package/dist/integration-tests/1/smooai-config/default.js +12419 -0
- package/dist/integration-tests/1/smooai-config/default.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/default.mjs +78 -0
- package/dist/integration-tests/1/smooai-config/default.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/development.d.mts +41 -0
- package/dist/integration-tests/1/smooai-config/development.d.ts +41 -0
- package/dist/integration-tests/1/smooai-config/development.js +12403 -0
- package/dist/integration-tests/1/smooai-config/development.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/development.mjs +62 -0
- package/dist/integration-tests/1/smooai-config/development.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.d.mts +128 -0
- package/dist/integration-tests/1/smooai-config/production.aws.d.ts +128 -0
- package/dist/integration-tests/1/smooai-config/production.aws.js +12371 -0
- package/dist/integration-tests/1/smooai-config/production.aws.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.mjs +30 -0
- package/dist/integration-tests/1/smooai-config/production.aws.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.d.mts +64 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.d.ts +64 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.js +12364 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.mjs +23 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-1.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.d.mts +64 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.d.ts +64 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.js +12364 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.mjs +23 -0
- package/dist/integration-tests/1/smooai-config/production.aws.us-east-2.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.d.mts +42 -0
- package/dist/integration-tests/1/smooai-config/production.d.ts +42 -0
- package/dist/integration-tests/1/smooai-config/production.js +12399 -0
- package/dist/integration-tests/1/smooai-config/production.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/production.mjs +58 -0
- package/dist/integration-tests/1/smooai-config/production.mjs.map +1 -0
- package/dist/integration-tests/1/smooai-config/staging.d.mts +129 -0
- package/dist/integration-tests/1/smooai-config/staging.d.ts +129 -0
- package/dist/integration-tests/1/smooai-config/staging.js +12377 -0
- package/dist/integration-tests/1/smooai-config/staging.js.map +1 -0
- package/dist/integration-tests/1/smooai-config/staging.mjs +36 -0
- package/dist/integration-tests/1/smooai-config/staging.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/config.d.mts +1262 -0
- package/dist/integration-tests/2/smooai-config/config.d.ts +1262 -0
- package/dist/integration-tests/2/smooai-config/config.js +12301 -0
- package/dist/integration-tests/2/smooai-config/config.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/config.mjs +12 -0
- package/dist/integration-tests/2/smooai-config/config.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/default.d.mts +19 -0
- package/dist/integration-tests/2/smooai-config/default.d.ts +19 -0
- package/dist/integration-tests/2/smooai-config/default.js +12321 -0
- package/dist/integration-tests/2/smooai-config/default.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/default.mjs +32 -0
- package/dist/integration-tests/2/smooai-config/default.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/development.d.mts +9 -0
- package/dist/integration-tests/2/smooai-config/development.d.ts +9 -0
- package/dist/integration-tests/2/smooai-config/development.js +12311 -0
- package/dist/integration-tests/2/smooai-config/development.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/development.mjs +22 -0
- package/dist/integration-tests/2/smooai-config/development.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.aws.d.mts +26 -0
- package/dist/integration-tests/2/smooai-config/production.aws.d.ts +26 -0
- package/dist/integration-tests/2/smooai-config/production.aws.js +12311 -0
- package/dist/integration-tests/2/smooai-config/production.aws.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.aws.mjs +22 -0
- package/dist/integration-tests/2/smooai-config/production.aws.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.d.mts +25 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.d.ts +25 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.js +12310 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.mjs +21 -0
- package/dist/integration-tests/2/smooai-config/production.aws.us-east-1.mjs.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.d.mts +19 -0
- package/dist/integration-tests/2/smooai-config/production.d.ts +19 -0
- package/dist/integration-tests/2/smooai-config/production.js +12321 -0
- package/dist/integration-tests/2/smooai-config/production.js.map +1 -0
- package/dist/integration-tests/2/smooai-config/production.mjs +32 -0
- package/dist/integration-tests/2/smooai-config/production.mjs.map +1 -0
- package/dist/platform/client.d.mts +49 -0
- package/dist/platform/client.d.ts +49 -0
- package/dist/platform/client.js +123 -0
- package/dist/platform/client.js.map +1 -0
- package/dist/platform/client.mjs +8 -0
- package/dist/platform/client.mjs.map +1 -0
- package/dist/platform/server/server.async.d.mts +12 -0
- package/dist/platform/server/server.async.d.ts +12 -0
- package/dist/platform/server/server.async.js +12586 -0
- package/dist/platform/server/server.async.js.map +1 -0
- package/dist/platform/server/server.async.mjs +18 -0
- package/dist/platform/server/server.async.mjs.map +1 -0
- package/dist/platform/server/server.featureFlag.sync.d.mts +2 -0
- package/dist/platform/server/server.featureFlag.sync.d.ts +2 -0
- package/dist/platform/server/server.featureFlag.sync.js +12589 -0
- package/dist/platform/server/server.featureFlag.sync.js.map +1 -0
- package/dist/platform/server/server.featureFlag.sync.mjs +24 -0
- package/dist/platform/server/server.featureFlag.sync.mjs.map +1 -0
- package/dist/platform/server/server.publicConfig.sync.d.mts +2 -0
- package/dist/platform/server/server.publicConfig.sync.d.ts +2 -0
- package/dist/platform/server/server.publicConfig.sync.js +12589 -0
- package/dist/platform/server/server.publicConfig.sync.js.map +1 -0
- package/dist/platform/server/server.publicConfig.sync.mjs +24 -0
- package/dist/platform/server/server.publicConfig.sync.mjs.map +1 -0
- package/dist/platform/server/server.secretConfig.sync.d.mts +2 -0
- package/dist/platform/server/server.secretConfig.sync.d.ts +2 -0
- package/dist/platform/server/server.secretConfig.sync.js +12589 -0
- package/dist/platform/server/server.secretConfig.sync.js.map +1 -0
- package/dist/platform/server/server.secretConfig.sync.mjs +24 -0
- package/dist/platform/server/server.secretConfig.sync.mjs.map +1 -0
- package/dist/platform/server.d.mts +21 -0
- package/dist/platform/server.d.ts +21 -0
- package/dist/platform/server.js +12626 -0
- package/dist/platform/server.js.map +1 -0
- package/dist/platform/server.mjs +58 -0
- package/dist/platform/server.mjs.map +1 -0
- package/dist/react/hooks.d.mts +36 -0
- package/dist/react/hooks.d.ts +36 -0
- package/dist/react/hooks.js +90 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/hooks.mjs +14 -0
- package/dist/react/hooks.mjs.map +1 -0
- package/dist/react/index.d.mts +28 -0
- package/dist/react/index.d.ts +28 -0
- package/dist/react/index.js +194 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +17 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/schema-spec/smooai-config-schema-spec.d.mts +25 -0
- package/dist/schema-spec/smooai-config-schema-spec.d.ts +25 -0
- package/dist/schema-spec/smooai-config-schema-spec.js +177 -0
- package/dist/schema-spec/smooai-config-schema-spec.js.map +1 -0
- package/dist/schema-spec/smooai-config-schema-spec.mjs +154 -0
- package/dist/schema-spec/smooai-config-schema-spec.mjs.map +1 -0
- package/dist/utils/fs.d.mts +10 -0
- package/dist/utils/fs.d.ts +10 -0
- package/dist/utils/fs.js +74 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/fs.mjs +11 -0
- package/dist/utils/fs.mjs.map +1 -0
- package/dist/utils/index.d.mts +29 -0
- package/dist/utils/index.d.ts +29 -0
- package/dist/utils/index.js +113 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +18 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/mergeReplaceArrays.d.mts +9 -0
- package/dist/utils/mergeReplaceArrays.d.ts +9 -0
- package/dist/utils/mergeReplaceArrays.js +63 -0
- package/dist/utils/mergeReplaceArrays.js.map +1 -0
- package/dist/utils/mergeReplaceArrays.mjs +9 -0
- package/dist/utils/mergeReplaceArrays.mjs.map +1 -0
- package/package.json +133 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Smoo AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
|
|
2
|
+
|
|
3
|
+
<a name="readme-top"></a>
|
|
4
|
+
|
|
5
|
+
<!-- PROJECT LOGO -->
|
|
6
|
+
<br />
|
|
7
|
+
<div align="center">
|
|
8
|
+
<a href="https://smoo.ai">
|
|
9
|
+
<img src="images/logo.png" alt="SmooAI Logo" />
|
|
10
|
+
</a>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<!-- ABOUT THE PROJECT -->
|
|
14
|
+
|
|
15
|
+
## About SmooAI
|
|
16
|
+
|
|
17
|
+
SmooAI is an AI-powered platform for helping businesses multiply their customer, employee, and developer experience.
|
|
18
|
+
|
|
19
|
+
Learn more on [smoo.ai](https://smoo.ai)
|
|
20
|
+
|
|
21
|
+
## SmooAI Packages
|
|
22
|
+
|
|
23
|
+
Check out other SmooAI packages at [smoo.ai/open-source](https://smoo.ai/open-source)
|
|
24
|
+
|
|
25
|
+
## About @smooai/config
|
|
26
|
+
|
|
27
|
+
**Type-safe configuration management for every layer of your stack** - Define configuration schemas once, validate everywhere, and manage public settings, secrets, and feature flags across TypeScript, Python, Rust, and Go.
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+
|
|
33
|
+

|
|
34
|
+

|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
### Why @smooai/config?
|
|
38
|
+
|
|
39
|
+
Ever scattered configuration values across environment variables, JSON files, and hardcoded strings? Or struggled to keep configuration consistent across microservices written in different languages? Traditional config management gives you the values, but not the safety.
|
|
40
|
+
|
|
41
|
+
**@smooai/config provides:**
|
|
42
|
+
|
|
43
|
+
- **Three configuration tiers** - Separate public config, secrets, and feature flags with distinct schemas
|
|
44
|
+
- **Schema-agnostic validation** - Works with Zod, Valibot, ArkType, Effect Schema, or any StandardSchema-compliant library
|
|
45
|
+
- **Type-safe keys** - Automatic camelCase-to-UPPER_SNAKE_CASE mapping with full TypeScript inference
|
|
46
|
+
- **JSON Schema serialization** - Convert any schema to JSON Schema for cross-language interoperability
|
|
47
|
+
- **Runtime client** - Fetch configuration from a centralized config server with local caching
|
|
48
|
+
- **Multi-language support** - Native implementations in TypeScript, Python, Rust, and Go
|
|
49
|
+
|
|
50
|
+
### Install
|
|
51
|
+
|
|
52
|
+
#### TypeScript / JavaScript
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pnpm add @smooai/config
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Python
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
pip install smooai-config
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
or with [uv](https://docs.astral.sh/uv/):
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
uv add smooai-config
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### Rust
|
|
71
|
+
|
|
72
|
+
```toml
|
|
73
|
+
[dependencies]
|
|
74
|
+
smooai-config = { git = "https://github.com/SmooAI/config", package = "smooai-config" }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Go
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
go get github.com/SmooAI/config/go/config
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
### TypeScript - Define Configuration Schemas
|
|
86
|
+
|
|
87
|
+
Use any StandardSchema-compliant validation library to define your configuration:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { defineConfig, StringSchema, BooleanSchema, NumberSchema } from '@smooai/config';
|
|
91
|
+
import { z } from 'zod';
|
|
92
|
+
|
|
93
|
+
const config = defineConfig({
|
|
94
|
+
publicConfigSchema: {
|
|
95
|
+
apiUrl: z.string().url(),
|
|
96
|
+
maxRetries: NumberSchema,
|
|
97
|
+
enableDebug: BooleanSchema,
|
|
98
|
+
},
|
|
99
|
+
secretConfigSchema: {
|
|
100
|
+
databaseUrl: z.string().url(),
|
|
101
|
+
apiKey: StringSchema,
|
|
102
|
+
},
|
|
103
|
+
featureFlagSchema: {
|
|
104
|
+
enableNewUI: BooleanSchema,
|
|
105
|
+
betaFeatures: BooleanSchema,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Supports Zod, Valibot, ArkType, Effect Schema, and built-in schema types - see [SCHEMA_USAGE.md](SCHEMA_USAGE.md) for examples with each library.
|
|
111
|
+
|
|
112
|
+
### Python - Define and Fetch Configuration
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from pydantic import BaseModel
|
|
116
|
+
from smooai_config import define_config, ConfigTier
|
|
117
|
+
from smooai_config.client import ConfigClient
|
|
118
|
+
|
|
119
|
+
# Define schemas using Pydantic models
|
|
120
|
+
class PublicConfig(BaseModel):
|
|
121
|
+
api_url: str = "https://api.example.com"
|
|
122
|
+
max_retries: int = 3
|
|
123
|
+
|
|
124
|
+
class SecretConfig(BaseModel):
|
|
125
|
+
database_url: str
|
|
126
|
+
api_key: str
|
|
127
|
+
|
|
128
|
+
config = define_config(
|
|
129
|
+
public=PublicConfig,
|
|
130
|
+
secret=SecretConfig,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Fetch values at runtime
|
|
134
|
+
with ConfigClient(
|
|
135
|
+
base_url="https://config.smooai.dev",
|
|
136
|
+
api_key="your-api-key",
|
|
137
|
+
org_id="your-org-id",
|
|
138
|
+
) as client:
|
|
139
|
+
value = client.get_value("API_URL", environment="production")
|
|
140
|
+
all_values = client.get_all_values(environment="production")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Rust - Define and Fetch Configuration
|
|
144
|
+
|
|
145
|
+
```rust
|
|
146
|
+
use smooai_config::{define_config, ConfigTier};
|
|
147
|
+
use smooai_config::client::ConfigClient;
|
|
148
|
+
|
|
149
|
+
// Define configuration tiers
|
|
150
|
+
let config = define_config(
|
|
151
|
+
Some(vec![("api_url", "https://api.example.com")]),
|
|
152
|
+
Some(vec![("database_url", "postgres://...")]),
|
|
153
|
+
None,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// Fetch values at runtime
|
|
157
|
+
let client = ConfigClient::new(
|
|
158
|
+
"https://config.smooai.dev",
|
|
159
|
+
"your-api-key",
|
|
160
|
+
"your-org-id",
|
|
161
|
+
);
|
|
162
|
+
let value = client.get_value("API_URL", Some("production")).await?;
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Go - Define and Fetch Configuration
|
|
166
|
+
|
|
167
|
+
```go
|
|
168
|
+
import "github.com/SmooAI/config/go/config"
|
|
169
|
+
|
|
170
|
+
// Define configuration
|
|
171
|
+
cfg := config.DefineConfig(
|
|
172
|
+
map[string]interface{}{"apiUrl": "https://api.example.com"},
|
|
173
|
+
map[string]interface{}{"databaseUrl": "postgres://..."},
|
|
174
|
+
nil,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
// Fetch values at runtime
|
|
178
|
+
client := config.NewConfigClient(
|
|
179
|
+
"https://config.smooai.dev",
|
|
180
|
+
"your-api-key",
|
|
181
|
+
"your-org-id",
|
|
182
|
+
)
|
|
183
|
+
defer client.Close()
|
|
184
|
+
value, err := client.GetValue("API_URL", "production")
|
|
185
|
+
allValues, err := client.GetAllValues("production")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## SDK Runtime Client
|
|
189
|
+
|
|
190
|
+
All language implementations include a runtime client for fetching configuration values from the Smoo AI config server. Each client supports local caching and environment variable configuration.
|
|
191
|
+
|
|
192
|
+
### Environment Variables
|
|
193
|
+
|
|
194
|
+
All clients read from the same set of environment variables:
|
|
195
|
+
|
|
196
|
+
| Variable | Description | Required |
|
|
197
|
+
| ----------------------- | ------------------------------------------------------ | -------- |
|
|
198
|
+
| `SMOOAI_CONFIG_API_URL` | Base URL of the config API | Yes |
|
|
199
|
+
| `SMOOAI_CONFIG_API_KEY` | Bearer token for authentication | Yes |
|
|
200
|
+
| `SMOOAI_CONFIG_ORG_ID` | Organization ID | Yes |
|
|
201
|
+
| `SMOOAI_CONFIG_ENV` | Default environment name (defaults to `"development"`) | No |
|
|
202
|
+
|
|
203
|
+
Set these in your environment and the client will use them automatically:
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
export SMOOAI_CONFIG_API_URL="https://config.smooai.dev"
|
|
207
|
+
export SMOOAI_CONFIG_API_KEY="your-api-key"
|
|
208
|
+
export SMOOAI_CONFIG_ORG_ID="your-org-id"
|
|
209
|
+
export SMOOAI_CONFIG_ENV="production"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### TypeScript SDK Client
|
|
213
|
+
|
|
214
|
+
The TypeScript client works in any JavaScript runtime (Node.js, browsers, edge runtimes):
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { ConfigClient } from '@smooai/config/platform/client';
|
|
218
|
+
|
|
219
|
+
// Option 1: Use environment variables (zero-config)
|
|
220
|
+
const client = new ConfigClient();
|
|
221
|
+
|
|
222
|
+
// Option 2: Explicit configuration (overrides env vars)
|
|
223
|
+
const client = new ConfigClient({
|
|
224
|
+
baseUrl: 'https://config.smooai.dev',
|
|
225
|
+
apiKey: 'your-api-key',
|
|
226
|
+
orgId: 'your-org-id',
|
|
227
|
+
environment: 'production',
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Fetch a single value (uses default environment)
|
|
231
|
+
const apiUrl = await client.getValue('API_URL');
|
|
232
|
+
|
|
233
|
+
// Fetch a value for a specific environment
|
|
234
|
+
const stagingUrl = await client.getValue('API_URL', 'staging');
|
|
235
|
+
|
|
236
|
+
// Fetch all values
|
|
237
|
+
const allValues = await client.getAllValues();
|
|
238
|
+
|
|
239
|
+
// Clear the local cache
|
|
240
|
+
client.invalidateCache();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### React Hooks
|
|
244
|
+
|
|
245
|
+
For React applications, use the built-in hooks with `ConfigProvider`:
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { ConfigProvider, usePublicConfig, useSecretConfig, useFeatureFlag } from '@smooai/config/react';
|
|
249
|
+
|
|
250
|
+
// Wrap your app with ConfigProvider
|
|
251
|
+
function App() {
|
|
252
|
+
return (
|
|
253
|
+
<ConfigProvider baseUrl="https://config.smooai.dev" apiKey="your-api-key" orgId="your-org-id" environment="production">
|
|
254
|
+
<MyComponent />
|
|
255
|
+
</ConfigProvider>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Use hooks in any child component
|
|
260
|
+
function MyComponent() {
|
|
261
|
+
const { value: apiUrl, isLoading, error } = usePublicConfig<string>('API_URL');
|
|
262
|
+
const { value: dbUrl } = useSecretConfig<string>('DATABASE_URL');
|
|
263
|
+
const { value: enableNewUI, refetch } = useFeatureFlag<boolean>('ENABLE_NEW_UI');
|
|
264
|
+
|
|
265
|
+
if (isLoading) return <div>Loading...</div>;
|
|
266
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
267
|
+
|
|
268
|
+
return <div>API URL: {apiUrl}</div>;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Python SDK Client
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from smooai_config.client import ConfigClient
|
|
276
|
+
|
|
277
|
+
# Option 1: Use environment variables (zero-config)
|
|
278
|
+
with ConfigClient() as client:
|
|
279
|
+
value = client.get_value("API_URL")
|
|
280
|
+
all_values = client.get_all_values()
|
|
281
|
+
|
|
282
|
+
# Option 2: Explicit configuration
|
|
283
|
+
with ConfigClient(
|
|
284
|
+
base_url="https://config.smooai.dev",
|
|
285
|
+
api_key="your-api-key",
|
|
286
|
+
org_id="your-org-id",
|
|
287
|
+
environment="production",
|
|
288
|
+
) as client:
|
|
289
|
+
value = client.get_value("API_URL")
|
|
290
|
+
value = client.get_value("API_URL", environment="staging") # Override environment
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Rust SDK Client
|
|
294
|
+
|
|
295
|
+
```rust
|
|
296
|
+
use smooai_config::client::ConfigClient;
|
|
297
|
+
|
|
298
|
+
// Option 1: Use environment variables (zero-config)
|
|
299
|
+
let mut client = ConfigClient::from_env();
|
|
300
|
+
|
|
301
|
+
// Option 2: Explicit configuration
|
|
302
|
+
let mut client = ConfigClient::new(
|
|
303
|
+
"https://config.smooai.dev",
|
|
304
|
+
"your-api-key",
|
|
305
|
+
"your-org-id",
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// Option 3: Explicit with default environment
|
|
309
|
+
let mut client = ConfigClient::with_environment(
|
|
310
|
+
"https://config.smooai.dev",
|
|
311
|
+
"your-api-key",
|
|
312
|
+
"your-org-id",
|
|
313
|
+
"production",
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
// Fetch values (None uses default environment)
|
|
317
|
+
let value = client.get_value("API_URL", None).await?;
|
|
318
|
+
let value = client.get_value("API_URL", Some("staging")).await?;
|
|
319
|
+
let all = client.get_all_values(None).await?;
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Go SDK Client
|
|
323
|
+
|
|
324
|
+
```go
|
|
325
|
+
import "github.com/SmooAI/config/go/config"
|
|
326
|
+
|
|
327
|
+
// Option 1: Use environment variables (zero-config)
|
|
328
|
+
client := config.NewConfigClientFromEnv()
|
|
329
|
+
defer client.Close()
|
|
330
|
+
|
|
331
|
+
// Option 2: Explicit configuration (empty strings fall back to env vars)
|
|
332
|
+
client := config.NewConfigClient(
|
|
333
|
+
"https://config.smooai.dev",
|
|
334
|
+
"your-api-key",
|
|
335
|
+
"your-org-id",
|
|
336
|
+
)
|
|
337
|
+
defer client.Close()
|
|
338
|
+
|
|
339
|
+
// Fetch values (empty string uses default environment)
|
|
340
|
+
value, err := client.GetValue("API_URL", "")
|
|
341
|
+
value, err := client.GetValue("API_URL", "staging")
|
|
342
|
+
allValues, err := client.GetAllValues("")
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Configuration Tiers
|
|
346
|
+
|
|
347
|
+
| Tier | Purpose | Examples |
|
|
348
|
+
| ----------------- | ----------------------- | ---------------------------------------- |
|
|
349
|
+
| **Public** | Client-visible settings | API URLs, feature toggles, UI config |
|
|
350
|
+
| **Secret** | Server-side only | Database URLs, API keys, JWT secrets |
|
|
351
|
+
| **Feature Flags** | Runtime toggles | A/B tests, gradual rollouts, beta access |
|
|
352
|
+
|
|
353
|
+
Each tier gets its own schema, validation, and JSON Schema output for cross-language consumption.
|
|
354
|
+
|
|
355
|
+
## Development
|
|
356
|
+
|
|
357
|
+
### Prerequisites
|
|
358
|
+
|
|
359
|
+
- Node.js 22+, pnpm 10+
|
|
360
|
+
- Python 3.13+ with uv
|
|
361
|
+
- Rust toolchain (rustup)
|
|
362
|
+
- Go 1.22+
|
|
363
|
+
|
|
364
|
+
### Commands
|
|
365
|
+
|
|
366
|
+
```sh
|
|
367
|
+
pnpm install # Install dependencies
|
|
368
|
+
pnpm build # Build all packages (TS, Python, Rust, Go)
|
|
369
|
+
pnpm test # Run all tests (Vitest, pytest, cargo test, go test)
|
|
370
|
+
pnpm lint # Lint all code (oxlint, ruff, clippy, go vet)
|
|
371
|
+
pnpm format # Format all code (oxfmt, ruff, cargo fmt, gofmt)
|
|
372
|
+
pnpm typecheck # Type check (tsc, basedpyright, cargo check)
|
|
373
|
+
pnpm check-all # Full CI parity check
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Built With
|
|
377
|
+
|
|
378
|
+
- **TypeScript** - Core implementation with StandardSchema support
|
|
379
|
+
- **Python** - Pydantic-based schemas with httpx runtime client
|
|
380
|
+
- **Rust** - Serde-based schemas with reqwest async client
|
|
381
|
+
- **Go** - Native schemas with net/http client and local caching
|
|
382
|
+
- [StandardSchema](https://github.com/standard-schema/standard-schema) - Schema-agnostic validation
|
|
383
|
+
- [Zod](https://zod.dev/), [Valibot](https://valibot.dev/), [ArkType](https://arktype.io/), [Effect](https://effect.website/) - Supported validation libraries
|
|
384
|
+
|
|
385
|
+
## Contributing
|
|
386
|
+
|
|
387
|
+
Contributions are welcome! This project uses [changesets](https://github.com/changesets/changesets) to manage versions and releases.
|
|
388
|
+
|
|
389
|
+
### Development Workflow
|
|
390
|
+
|
|
391
|
+
1. Fork the repository
|
|
392
|
+
2. Create your branch (`git checkout -b amazing-feature`)
|
|
393
|
+
3. Make your changes
|
|
394
|
+
4. Add a changeset to document your changes:
|
|
395
|
+
|
|
396
|
+
```sh
|
|
397
|
+
pnpm changeset
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
This will prompt you to:
|
|
401
|
+
- Choose the type of version bump (patch, minor, or major)
|
|
402
|
+
- Provide a description of the changes
|
|
403
|
+
|
|
404
|
+
5. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
405
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
406
|
+
7. Open a Pull Request
|
|
407
|
+
|
|
408
|
+
### Pull Request Guidelines
|
|
409
|
+
|
|
410
|
+
- Reference any related issues in your PR description
|
|
411
|
+
|
|
412
|
+
The maintainers will review your PR and may request changes before merging.
|
|
413
|
+
|
|
414
|
+
<!-- CONTACT -->
|
|
415
|
+
|
|
416
|
+
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
417
|
+
|
|
418
|
+
## Contact
|
|
419
|
+
|
|
420
|
+
Brent Rager
|
|
421
|
+
|
|
422
|
+
- [Email](mailto:brent@smoo.ai)
|
|
423
|
+
- [LinkedIn](https://www.linkedin.com/in/brentrager/)
|
|
424
|
+
- [BlueSky](https://bsky.app/profile/brentragertech.bsky.social)
|
|
425
|
+
- [TikTok](https://www.tiktok.com/@brentragertech)
|
|
426
|
+
- [Instagram](https://www.instagram.com/brentragertech/)
|
|
427
|
+
|
|
428
|
+
Smoo Github: [https://github.com/SmooAI](https://github.com/SmooAI)
|
|
429
|
+
|
|
430
|
+
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/utils/index.ts
|
|
2
|
+
import createEsmUtils from "esm-utils";
|
|
3
|
+
function initEsmUtils() {
|
|
4
|
+
if (!global.__dirname || !global.__filename) {
|
|
5
|
+
const { __dirname, __filename } = import.meta.url ? createEsmUtils({ url: import.meta.url, resolve: import.meta.resolve }) : { __dirname: "", __filename: "" };
|
|
6
|
+
global.__dirname = global.__dirname ? global.__dirname : __dirname;
|
|
7
|
+
global.__filename = global.__filename ? global.__filename : __filename;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function isEmpty(obj) {
|
|
11
|
+
for (const prop in obj) {
|
|
12
|
+
if (Object.hasOwn(obj, prop)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
var envToUse = () => !isEmpty(process?.env) ? process.env : import.meta.env;
|
|
19
|
+
function isPlainObject(obj) {
|
|
20
|
+
return !!obj && typeof obj === "object" && !Array.isArray(obj);
|
|
21
|
+
}
|
|
22
|
+
var SmooaiConfigError = class extends Error {
|
|
23
|
+
constructor(message, options) {
|
|
24
|
+
super(`[Smooai Config] ${message}`, options);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function snakecase(input) {
|
|
28
|
+
if (/^[A-Z0-9]+(?:_[A-Z0-9]+)*$/.test(input)) {
|
|
29
|
+
return input;
|
|
30
|
+
}
|
|
31
|
+
let out = "";
|
|
32
|
+
const len = input.length;
|
|
33
|
+
for (let i = 0; i < len; i++) {
|
|
34
|
+
const ch = input[i];
|
|
35
|
+
if (ch === "_" || ch === " ") continue;
|
|
36
|
+
const code = input.charCodeAt(i);
|
|
37
|
+
const isUpper = code >= 65 && code <= 90;
|
|
38
|
+
const isLower = code >= 97 && code <= 122;
|
|
39
|
+
const isDigit = code >= 48 && code <= 57;
|
|
40
|
+
if (isUpper) {
|
|
41
|
+
if (i > 0) {
|
|
42
|
+
const prev = input.charCodeAt(i - 1);
|
|
43
|
+
const prevIsLower = prev >= 97 && prev <= 122;
|
|
44
|
+
const next = i + 1 < len ? input.charCodeAt(i + 1) : NaN;
|
|
45
|
+
const nextIsLower = next >= 97 && next <= 122;
|
|
46
|
+
if (prevIsLower || nextIsLower) {
|
|
47
|
+
out += "_";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
out += ch;
|
|
51
|
+
} else if (isLower) {
|
|
52
|
+
out += String.fromCharCode(code - 32);
|
|
53
|
+
} else if (isDigit) {
|
|
54
|
+
out += ch;
|
|
55
|
+
} else {
|
|
56
|
+
out += ch;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
function convertKeyToUpperSnakeCase(key) {
|
|
62
|
+
return snakecase(key).toUpperCase();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
initEsmUtils,
|
|
67
|
+
envToUse,
|
|
68
|
+
isPlainObject,
|
|
69
|
+
SmooaiConfigError,
|
|
70
|
+
snakecase,
|
|
71
|
+
convertKeyToUpperSnakeCase
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=chunk-3SU3SMKN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- ok */\nimport createEsmUtils from 'esm-utils';\n\n/**\n * Initialize global __dirname and __filename if not already set.\n */\nexport function initEsmUtils() {\n if (!global.__dirname || !global.__filename) {\n const { __dirname, __filename } = import.meta.url\n ? createEsmUtils({ url: import.meta.url, resolve: import.meta.resolve } as any)\n : { __dirname: '', __filename: '' };\n global.__dirname = global.__dirname ? global.__dirname : __dirname;\n global.__filename = global.__filename ? global.__filename : __filename;\n }\n}\n\n/**\n * Check if an object is empty.\n */\nfunction isEmpty(obj: any): boolean {\n for (const prop in obj) {\n if (Object.hasOwn(obj, prop)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Get the environment variables. Works in Node and Various React Runtimes.\n */\nexport const envToUse = (): NodeJS.ProcessEnv => (!isEmpty(process?.env) ? process.env : (import.meta as unknown as { env: NodeJS.ProcessEnv }).env);\n\n/**\n * Minimal utility to detect an object (excludes arrays).\n */\nexport function isPlainObject(obj: unknown): obj is Record<string, unknown> {\n return !!obj && typeof obj === 'object' && !Array.isArray(obj);\n}\n\nexport class SmooaiConfigError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(`[Smooai Config] ${message}`, options);\n }\n}\n\n// ——— helper: single-char step, always recursing into SnakeCase<> ———\ntype _SnakeCaseChar<S extends string> = S extends `${infer First}${infer Rest}`\n ? First extends '_' | ' '\n ? SnakeCase<Rest> // drop \"_\" or \" \"\n : Rest extends Uncapitalize<Rest>\n ? `${Lowercase<First>}${SnakeCase<Rest>}` // next is lower/non-letter → no underscore\n : First extends Lowercase<First>\n ? `${Lowercase<First>}_${SnakeCase<Rest>}` // lower→upper → underscore\n : `${Lowercase<First>}${SnakeCase<Rest>}` // upper→upper → no underscore\n : S; // empty or single character\n\n// ——— your public SnakeCase<> with 3-char look-ahead for acronyms ———\nexport type SnakeCase<S extends string> =\n // 1⃣ Acronym boundary: Upper + Upper + lower (e.g. \"IKey\" → \"i_key\")\n S extends `${infer A}${infer B}${infer C}${infer Rest}`\n ? A extends Uppercase<A>\n ? B extends Uppercase<B>\n ? C extends Lowercase<C>\n ? `${Lowercase<A>}_${SnakeCase<`${B}${C}${Rest}`>}`\n : _SnakeCaseChar<S>\n : _SnakeCaseChar<S>\n : _SnakeCaseChar<S>\n : // 2⃣ If we don’t even have 3 chars to peek, fall back to the single-char step\n _SnakeCaseChar<S>;\n\nexport type UpperSnakeCase<S extends string> =\n S extends Uppercase<S>\n ? S extends `${string} ${string}`\n ? // if it had a space, rerun SnakeCase to turn that into \" \"\n Uppercase<SnakeCase<S>>\n : S\n : Uppercase<SnakeCase<S>>;\n\nexport type UnionToUpperSnake<U> = U extends string ? UpperSnakeCase<U> : never;\n\n/**\n * One-pass, no-regex UPPER_SNAKE_CASE converter.\n * - Early exit if already UPPER_SNAKE_CASE.\n * - Drops spaces/underscores.\n * - Splits on lower→Upper and Acronym→Word\n */\nexport function snakecase(input: string): string {\n // Early return if it’s already UPPER_SNAKE_CASE\n if (/^[A-Z0-9]+(?:_[A-Z0-9]+)*$/.test(input)) {\n return input;\n }\n\n let out = '';\n const len = input.length;\n\n for (let i = 0; i < len; i++) {\n const ch = input[i];\n if (ch === '_' || ch === ' ') continue; // drop underscores/spaces\n\n const code = input.charCodeAt(i);\n const isUpper = code >= 65 && code <= 90; // A–Z\n const isLower = code >= 97 && code <= 122; // a–z\n const isDigit = code >= 48 && code <= 57; // 0–9\n\n if (isUpper) {\n // split on lower→upper or acronym→word\n if (i > 0) {\n const prev = input.charCodeAt(i - 1);\n const prevIsLower = prev >= 97 && prev <= 122;\n const next = i + 1 < len ? input.charCodeAt(i + 1) : NaN;\n const nextIsLower = next >= 97 && next <= 122;\n if (prevIsLower || nextIsLower) {\n out += '_';\n }\n }\n out += ch; // keep uppercase\n } else if (isLower) {\n // lowercase → uppercase\n out += String.fromCharCode(code - 32);\n } else if (isDigit) {\n // digit → append as-is\n out += ch;\n } else {\n // any other character: append or drop as you see fit\n out += ch;\n }\n }\n\n return out;\n}\n\nexport function convertKeyToUpperSnakeCase(key: string): string {\n return snakecase(key).toUpperCase();\n}\n"],"mappings":";AACA,OAAO,oBAAoB;AAKpB,SAAS,eAAe;AAC3B,MAAI,CAAC,OAAO,aAAa,CAAC,OAAO,YAAY;AACzC,UAAM,EAAE,WAAW,WAAW,IAAI,YAAY,MACxC,eAAe,EAAE,KAAK,YAAY,KAAK,SAAS,YAAY,QAAQ,CAAQ,IAC5E,EAAE,WAAW,IAAI,YAAY,GAAG;AACtC,WAAO,YAAY,OAAO,YAAY,OAAO,YAAY;AACzD,WAAO,aAAa,OAAO,aAAa,OAAO,aAAa;AAAA,EAChE;AACJ;AAKA,SAAS,QAAQ,KAAmB;AAChC,aAAW,QAAQ,KAAK;AACpB,QAAI,OAAO,OAAO,KAAK,IAAI,GAAG;AAC1B,aAAO;AAAA,IACX;AAAA,EACJ;AACA,SAAO;AACX;AAKO,IAAM,WAAW,MAA0B,CAAC,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAO,YAAsD;AAKzI,SAAS,cAAc,KAA8C;AACxE,SAAO,CAAC,CAAC,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG;AACjE;AAEO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EACzC,YAAY,SAAiB,SAAwB;AACjD,UAAM,mBAAmB,OAAO,IAAI,OAAO;AAAA,EAC/C;AACJ;AA2CO,SAAS,UAAU,OAAuB;AAE7C,MAAI,6BAA6B,KAAK,KAAK,GAAG;AAC1C,WAAO;AAAA,EACX;AAEA,MAAI,MAAM;AACV,QAAM,MAAM,MAAM;AAElB,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,OAAO,OAAO,OAAO,IAAK;AAE9B,UAAM,OAAO,MAAM,WAAW,CAAC;AAC/B,UAAM,UAAU,QAAQ,MAAM,QAAQ;AACtC,UAAM,UAAU,QAAQ,MAAM,QAAQ;AACtC,UAAM,UAAU,QAAQ,MAAM,QAAQ;AAEtC,QAAI,SAAS;AAET,UAAI,IAAI,GAAG;AACP,cAAM,OAAO,MAAM,WAAW,IAAI,CAAC;AACnC,cAAM,cAAc,QAAQ,MAAM,QAAQ;AAC1C,cAAM,OAAO,IAAI,IAAI,MAAM,MAAM,WAAW,IAAI,CAAC,IAAI;AACrD,cAAM,cAAc,QAAQ,MAAM,QAAQ;AAC1C,YAAI,eAAe,aAAa;AAC5B,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,aAAO;AAAA,IACX,WAAW,SAAS;AAEhB,aAAO,OAAO,aAAa,OAAO,EAAE;AAAA,IACxC,WAAW,SAAS;AAEhB,aAAO;AAAA,IACX,OAAO;AAEH,aAAO;AAAA,IACX;AAAA,EACJ;AAEA,SAAO;AACX;AAEO,SAAS,2BAA2B,KAAqB;AAC5D,SAAO,UAAU,GAAG,EAAE,YAAY;AACtC;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/PublicConfigKey.ts"],"sourcesContent":["/**\n * Extendable enum representing public config keys.\n *\n * This class is used to define the public config keys that are available to the application.\n *\n * An example of public confg keys is configurable values that you don't mind being exposed to the user, like a public API key for accessing a headless CMS.\n *\n * @example\n * ```typescript\n * export class MyPublicConfigKey extends PublicConfigKey {\n * static readonly MY_PUBLIC_API_KEY = 'MY_PUBLIC_API_KEY';\n * }\n */\nexport const PublicConfigKey = {\n ENV: 'ENV',\n IS_LOCAL: 'IS_LOCAL',\n REGION: 'REGION',\n CLOUD_PROVIDER: 'CLOUD_PROVIDER',\n} as const;\n\nexport type PublicConfigKey = (typeof PublicConfigKey)[keyof typeof PublicConfigKey];\n"],"mappings":";AAaO,IAAM,kBAAkB;AAAA,EAC3B,KAAK;AAAA,EACL,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,gBAAgB;AACpB;","names":[]}
|