Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
nfkit
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
nfkit
Commits
ebd6039d
Commit
ebd6039d
authored
Feb 16, 2026
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add getJSON
parent
7a5176fb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
114 additions
and
7 deletions
+114
-7
src/configurer/configurer.ts
src/configurer/configurer.ts
+52
-6
tests/configurer.spec.ts
tests/configurer.spec.ts
+62
-1
No files found.
src/configurer/configurer.ts
View file @
ebd6039d
...
...
@@ -37,6 +37,23 @@ export class ConfigurerInstance<T extends Record<string, string>> {
const
defaultBoolean
=
parseConfigBoolean
(
this
.
defaultConfig
[
key
],
false
);
return
convertBooleanArray
(
this
.
getString
(
key
),
defaultBoolean
);
}
getJSON
<
R
=
unknown
,
K
extends
keyof
T
=
keyof
T
>
(
key
:
K
):
R
{
const
value
=
this
.
getString
(
key
);
const
jsonString
=
typeof
value
===
'
string
'
&&
!
value
.
trim
()
?
(
this
.
defaultConfig
[
key
]
as
string
)
:
value
;
try
{
return
JSON
.
parse
(
jsonString
)
as
R
;
}
catch
(
error
)
{
const
message
=
error
instanceof
Error
?
`:
${
error
.
message
}
`
:
''
;
throw
new
Error
(
`Failed to parse JSON config "
${
String
(
key
)}
"
${
message
}
`
,
);
}
}
}
export
class
Configurer
<
T
extends
Record
<
string
,
string
>>
{
...
...
@@ -62,19 +79,24 @@ export class Configurer<T extends Record<string, string>> {
);
}
generateExampleObject
():
Record
<
string
,
string
|
number
|
string
[]
|
number
[]
>
{
generateExampleObject
():
Record
<
string
,
unknown
>
{
return
Object
.
fromEntries
(
Object
.
entries
(
this
.
defaultConfig
).
map
(([
key
,
value
])
=>
{
const
typedValue
=
toTypedValue
(
value
);
if
(
typedValue
&&
typeof
typedValue
===
'
object
'
&&
!
Array
.
isArray
(
typedValue
)
)
{
return
[
toCamelCaseKey
(
key
),
typedValue
];
}
if
(
value
.
includes
(
'
,
'
))
{
return
[
toCamelCaseKey
(
key
),
value
.
split
(
'
,
'
).
map
((
v
)
=>
toTypedValue
(
v
)),
];
}
return
[
toCamelCaseKey
(
key
),
t
oTypedValue
(
value
)
];
return
[
toCamelCaseKey
(
key
),
t
ypedValue
];
}),
);
}
...
...
@@ -104,6 +126,9 @@ function normalizeConfigValue(value: unknown): string | undefined {
if
(
Array
.
isArray
(
value
))
{
return
value
.
map
((
item
)
=>
normalizeArrayItem
(
item
)).
join
(
'
,
'
);
}
if
(
typeof
value
===
'
object
'
)
{
return
JSON
.
stringify
(
value
);
}
return
String
(
value
);
}
...
...
@@ -205,10 +230,31 @@ function convertBooleanArray(str: string, defaultValue = false): boolean[] {
);
}
function
toTypedValue
(
value
:
string
):
string
|
number
{
function
toTypedValue
(
value
:
string
):
string
|
number
|
Record
<
string
,
unknown
>
{
const
trimmed
=
value
.
trim
();
if
(
/^
\d
+$/
.
test
(
trimmed
))
{
return
Number
.
parseInt
(
trimmed
,
10
);
}
const
jsonObject
=
parseJsonObjectString
(
trimmed
);
if
(
jsonObject
!==
undefined
)
{
return
jsonObject
;
}
return
trimmed
;
}
function
parseJsonObjectString
(
value
:
string
,
):
Record
<
string
,
unknown
>
|
undefined
{
if
(
!
value
.
startsWith
(
'
{
'
)
||
!
value
.
endsWith
(
'
}
'
))
{
return
undefined
;
}
try
{
const
parsed
=
JSON
.
parse
(
value
);
if
(
parsed
&&
typeof
parsed
===
'
object
'
&&
!
Array
.
isArray
(
parsed
))
{
return
parsed
as
Record
<
string
,
unknown
>
;
}
}
catch
{
return
undefined
;
}
return
undefined
;
}
tests/configurer.spec.ts
View file @
ebd6039d
...
...
@@ -8,6 +8,7 @@ type TestConfig = {
ALT_VERSIONS
:
string
;
FLOAT_VALUES
:
string
;
BOOL_VALUES
:
string
;
JSON_CONFIG
:
string
;
};
const
defaultConfig
:
TestConfig
=
{
...
...
@@ -18,6 +19,7 @@ const defaultConfig: TestConfig = {
ALT_VERSIONS
:
'
2330,2331
'
,
FLOAT_VALUES
:
'
1.5,2.75
'
,
BOOL_VALUES
:
'
1,0,true,false,null
'
,
JSON_CONFIG
:
'
{"mode":"default","retry":3}
'
,
};
describe
(
'
Configurer
'
,
()
=>
{
...
...
@@ -87,7 +89,65 @@ describe('Configurer', () => {
]);
});
test
(
'
generateExampleObject converts key to camelCase and parses number/array values
'
,
()
=>
{
test
(
'
getString keeps whitespace string value
'
,
()
=>
{
const
configurer
=
new
Configurer
(
defaultConfig
);
const
instance
=
configurer
.
loadConfig
({
env
:
{
HOST
:
'
'
,
},
});
expect
(
instance
.
getString
(
'
HOST
'
)).
toBe
(
'
'
);
});
test
(
'
getJSON parses JSON and falls back to default for empty value
'
,
()
=>
{
const
configurer
=
new
Configurer
(
defaultConfig
);
const
withCustom
=
configurer
.
loadConfig
({
env
:
{
JSON_CONFIG
:
'
{"mode":"custom","retry":1}
'
,
},
});
const
withEmpty
=
configurer
.
loadConfig
({
env
:
{
JSON_CONFIG
:
'
'
,
},
});
expect
(
withCustom
.
getJSON
<
{
mode
:
string
;
retry
:
number
}
>
(
'
JSON_CONFIG
'
)).
toEqual
({
mode
:
'
custom
'
,
retry
:
1
,
});
expect
(
withEmpty
.
getJSON
<
{
mode
:
string
;
retry
:
number
}
>
(
'
JSON_CONFIG
'
)).
toEqual
({
mode
:
'
default
'
,
retry
:
3
,
});
});
test
(
'
getJSON throws when JSON parse fails
'
,
()
=>
{
const
configurer
=
new
Configurer
(
defaultConfig
);
const
instance
=
configurer
.
loadConfig
({
env
:
{
JSON_CONFIG
:
'
{invalid json}
'
,
},
});
expect
(()
=>
instance
.
getJSON
(
'
JSON_CONFIG
'
)).
toThrow
(
'
Failed to parse JSON config "JSON_CONFIG"
'
,
);
});
test
(
'
normalizeConfigValue treats object as JSON string
'
,
()
=>
{
const
configurer
=
new
Configurer
(
defaultConfig
);
const
instance
=
configurer
.
loadConfig
({
obj
:
{
jsonConfig
:
{
mode
:
'
obj
'
,
retry
:
8
},
},
});
expect
(
instance
.
getString
(
'
JSON_CONFIG
'
)).
toBe
(
'
{"mode":"obj","retry":8}
'
);
});
test
(
'
generateExampleObject converts key to camelCase and parses number/array/json-object values
'
,
()
=>
{
const
configurer
=
new
Configurer
(
defaultConfig
);
const
example
=
configurer
.
generateExampleObject
();
...
...
@@ -95,5 +155,6 @@ describe('Configurer', () => {
expect
(
example
.
port
).
toBe
(
7911
);
expect
(
example
.
altVersions
).
toEqual
([
2330
,
2331
]);
expect
(
example
.
floatValues
).
toEqual
([
'
1.5
'
,
'
2.75
'
]);
expect
(
example
.
jsonConfig
).
toEqual
({
mode
:
'
default
'
,
retry
:
3
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment