Skip to content

Commit f62337a

Browse files
author
infodusha
committed
feat: add json mode
1 parent ca9602c commit f62337a

File tree

4 files changed

+80
-21
lines changed

4 files changed

+80
-21
lines changed

README.MD

+16-7
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,29 @@ Use in your app:
3939
```javascript
4040
console.log(CONFIG.PARAM); // Equals to VALUE or can be overriten in the env
4141
```
42+
## JSON mode
4243

44+
If you run the app with `--json` flag, it will return json instead of script.
45+
So you can use it in your app like this:
46+
```javascript
47+
fetch('config.json')
48+
.then(response => response.json())
49+
.then(config => console.log(config.PARAM));
50+
```
4351

4452
## CLI arguments
4553

4654
Each argument can be passed as a flag or as a value (e.g. `--port 8080` or `--port=8080`).
4755
Arguments have short aliases (e.g. `-p 8080`)
4856

49-
| Parameter | Type | Default | Description |
50-
|:-----------|:----------|:---------|:------------------------------------|
51-
| `port` | `string` | `8080` | Port where app is serverd |
52-
| `file` | `string` | `.env` | Env filename to read |
53-
| `variable` | `string` | `CONFIG` | Name of variable in global script |
54-
| `window` | `boolean` | `false` | If variable should be set to window |
55-
| `compress` | `boolean` | `false` | If script should be one-line |
57+
| Parameter | Type | Default | Description |
58+
|:-----------|:----------|:---------|:------------------------------------------------------------------|
59+
| `port` | `string` | `8080` | Port where app is serverd |
60+
| `file` | `string` | `.env` | Env filename to read |
61+
| `variable` | `string` | `CONFIG` | Name of variable in global script |
62+
| `window` | `boolean` | `false` | If variable should be set to window |
63+
| `compress` | `boolean` | `false` | If script should be one-line |
64+
| `json` | `boolean` | `false` | Response as json instead of script. (`-v` and `-w` are forbidden) |
5665

5766
## Contributing
5867

lib/config.js

+5
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@ export const argsOptions = {
2626
short: 'c',
2727
default: false,
2828
},
29+
json: {
30+
type: 'boolean',
31+
short: 'j',
32+
default: false,
33+
},
2934
};

lib/main.js

+22-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ import http from 'node:http';
44
import { argsOptions, TBD_SYMBOL } from './config.js';
55

66
function getArgs() {
7-
return parseArgs({ options: argsOptions }).values;
7+
const { values, tokens } = parseArgs({ options: argsOptions, tokens: true });
8+
if (values.json) {
9+
const hasWindow = tokens.find((token) => token.name === 'window');
10+
const hasVariable = tokens.find((token) => token.name === 'variable');
11+
if (hasWindow || hasVariable) {
12+
throw new Error('Cannot use --json with --window or --variable');
13+
}
14+
}
15+
return values;
816
}
917

1018
async function getEnvFromFile(filename) {
@@ -44,19 +52,25 @@ function checkNoTBDValues(env) {
4452
}
4553
}
4654

47-
function buildScript(env, variable, isWindow, isCompress) {
48-
const json = JSON.stringify(env, undefined, isCompress ? undefined : 2);
55+
function buildJson(env, isCompress) {
56+
return JSON.stringify(env, undefined, isCompress ? undefined : 2);
57+
}
58+
59+
function buildScript(json, variable, isWindow) {
4960
if (isWindow) {
5061
return `window.${variable} = ${json};`;
5162
}
5263
return `const ${variable} = ${json};`;
5364
}
5465

55-
function createRequestHandler(script) {
66+
function createRequestHandler(env, args) {
67+
const json = buildJson(env, args.compress);
68+
const contentType = args.json ? 'application/json' : 'application/javascript';
69+
const content = args.json ? json : buildScript(json, args.variable, args.window);
5670
return (req, res) => {
5771
res.statusCode = 200;
58-
res.setHeader('Content-Type', 'application/javascript');
59-
res.end(script);
72+
res.setHeader('Content-Type', contentType);
73+
res.end(content);
6074
}
6175
}
6276

@@ -65,8 +79,8 @@ export async function main() {
6579
const envFromFile = await getEnvFromFile(args.file);
6680
const env = overrideWithProcessValues(envFromFile);
6781
checkNoTBDValues(env);
68-
const script = buildScript(env, args.variable, args.window, args.compress);
69-
const server = http.createServer(createRequestHandler(script));
82+
const handler = createRequestHandler(env, args);
83+
const server = http.createServer(handler);
7084
server.listen(args.port, () => {
7185
console.log(`Server is listening on port ${args.port}`);
7286
});

test.js

+37-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('tests', () => {
1818
return res;
1919
}
2020

21-
function getScript() {
21+
function getResponseData() {
2222
const res = getResponse();
2323
return res.end.mock.calls[0].arguments[0];
2424
}
@@ -48,7 +48,7 @@ describe('tests', () => {
4848
await assert.doesNotReject(main);
4949
assert.strictEqual(listenMock.mock.calls[0].arguments[0], '8080'); // Port
5050
assert.strictEqual(fs.readFile.mock.calls[0].arguments[0], '.env'); // File
51-
assert.match(getScript(), /^const CONFIG = \{\n/); // Variable & Window & Compress
51+
assert.match(getResponseData(), /^const CONFIG = \{\n/); // Variable & Window & Compress
5252
});
5353

5454
it('Serves with correct content type', async () => {
@@ -67,20 +67,20 @@ describe('tests', () => {
6767
it('Can do compression', async () => {
6868
setArgs(['-c']);
6969
await main();
70-
assert.strictEqual(getScript(), `const CONFIG = {"FOO":"BAR"};`);
70+
assert.strictEqual(getResponseData(), `const CONFIG = {"FOO":"BAR"};`);
7171
});
7272

7373
it('Can set as window', async () => {
7474
setArgs(['-w']);
7575
await main();
76-
assert.match(getScript(), /^window\.CONFIG = \{\n/);
76+
assert.match(getResponseData(), /^window\.CONFIG = \{\n/);
7777
});
7878

7979
it('Overrides with process values', async () => {
8080
process.env.FOO = 'BAZ';
8181
setArgs(['-c']);
8282
await main();
83-
assert.strictEqual(getScript(), `const CONFIG = {"FOO":"BAZ"};`);
83+
assert.strictEqual(getResponseData(), `const CONFIG = {"FOO":"BAZ"};`);
8484
});
8585

8686
it('Throws if TBD values', async () => {
@@ -95,6 +95,37 @@ describe('tests', () => {
9595
process.env.HI = 'HELLO';
9696
setArgs(['-c']);
9797
await main();
98-
assert.strictEqual(getScript(), `const CONFIG = {"FOO":"BAR"};`);
98+
assert.strictEqual(getResponseData(), `const CONFIG = {"FOO":"BAR"};`);
99+
});
100+
101+
describe('json mode', () => {
102+
it('Serves json', async () => {
103+
setArgs(['-j', '-c']);
104+
await main();
105+
assert.strictEqual(getResponseData(), `{"FOO":"BAR"}`);
106+
});
107+
108+
it('Serves with correct content type', async () => {
109+
setArgs(['-j']);
110+
await main();
111+
assert.strictEqual(getResponse().setHeader.mock.calls[0].arguments[0], 'Content-Type');
112+
assert.strictEqual(getResponse().setHeader.mock.calls[0].arguments[1], 'application/json');
113+
});
114+
115+
it('Throws when --window', async () => {
116+
setArgs(['-j', '-w']);
117+
await assert.rejects(main, {
118+
name: 'Error',
119+
message: `Cannot use --json with --window or --variable`,
120+
});
121+
});
122+
123+
it('Throws when --variable', async () => {
124+
setArgs(['-j', '-v', 'key']);
125+
await assert.rejects(main, {
126+
name: 'Error',
127+
message: `Cannot use --json with --window or --variable`,
128+
});
129+
});
99130
});
100131
});

0 commit comments

Comments
 (0)