supaapps-config-fetcher 1.2.0 → 1.3.2
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/.github/workflows/publish-to-npm.yml +4 -3
- package/README.md +25 -1
- package/dist/ConfigManager.d.ts +4 -1
- package/dist/ConfigManager.js +17 -4
- package/dist/useConfig.d.ts +3 -1
- package/dist/useConfig.js +3 -3
- package/package.json +5 -1
- package/src/ConfigManager.ts +25 -4
- package/src/useConfig.ts +8 -4
|
@@ -8,6 +8,9 @@ on:
|
|
|
8
8
|
jobs:
|
|
9
9
|
build:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: read
|
|
11
14
|
steps:
|
|
12
15
|
- name: Checkout code
|
|
13
16
|
uses: actions/checkout@v2
|
|
@@ -25,6 +28,4 @@ jobs:
|
|
|
25
28
|
run: npm run build
|
|
26
29
|
|
|
27
30
|
- name: Publish to npm
|
|
28
|
-
run: npm publish
|
|
29
|
-
env:
|
|
30
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
31
|
+
run: npm publish --provenance --access public
|
package/README.md
CHANGED
|
@@ -65,8 +65,32 @@ const customHostManager = ConfigManager.getInstance<MyAppConfig>('example-app@v1
|
|
|
65
65
|
|
|
66
66
|
This will load the file from https://example.com/example-app@v1/localhost.json when the app is loaded from localhost
|
|
67
67
|
|
|
68
|
+
## Local development config
|
|
69
|
+
|
|
70
|
+
In development, you can opt in to load a local JSON file first. Place `config.local.json` in your app's public folder so it is served at `/config.local.json`.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const configManager = ConfigManager.getInstance<MyAppConfig>(
|
|
74
|
+
'example-app@v1',
|
|
75
|
+
undefined,
|
|
76
|
+
{ loadLocalConfig: true }
|
|
77
|
+
);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
When `loadLocalConfig` is `true`, the fetcher will try `/config.local.json` first and fall back to the hosted config if the local file is missing.
|
|
81
|
+
|
|
82
|
+
If you use the React hook, you can pass the same options:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const [config, error] = useConfig<MyAppConfig>(
|
|
86
|
+
'example-app@v1',
|
|
87
|
+
undefined,
|
|
88
|
+
{ loadLocalConfig: true }
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
68
92
|
## License
|
|
69
93
|
|
|
70
94
|
Notice: While this software is open-source under the MIT License, the "Supaapps" name, branding, and logo are proprietary and copyrighted by Supaapps GmbH. Any use, reproduction, or distribution of the "Supaapps" brand assets without explicit permission is strictly prohibited.
|
|
71
95
|
|
|
72
|
-
MIT License
|
|
96
|
+
MIT License
|
package/dist/ConfigManager.d.ts
CHANGED
|
@@ -3,7 +3,10 @@ export declare class ConfigManager<T> {
|
|
|
3
3
|
private config;
|
|
4
4
|
private appName;
|
|
5
5
|
private configHost;
|
|
6
|
+
private loadLocalConfig;
|
|
6
7
|
private constructor();
|
|
7
|
-
static getInstance<T>(appName: string, configHost?: string
|
|
8
|
+
static getInstance<T>(appName: string, configHost?: string, options?: {
|
|
9
|
+
loadLocalConfig?: boolean;
|
|
10
|
+
}): ConfigManager<T>;
|
|
8
11
|
loadConfig(): Promise<T>;
|
|
9
12
|
}
|
package/dist/ConfigManager.js
CHANGED
|
@@ -12,15 +12,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.ConfigManager = void 0;
|
|
13
13
|
const axios_1 = require("axios");
|
|
14
14
|
class ConfigManager {
|
|
15
|
-
constructor(appName, configHost = 'https://config.envdomain.com') {
|
|
15
|
+
constructor(appName, configHost = 'https://config.envdomain.com', loadLocalConfig = false) {
|
|
16
16
|
this.config = null;
|
|
17
17
|
this.appName = appName;
|
|
18
18
|
this.configHost = configHost;
|
|
19
|
+
this.loadLocalConfig = loadLocalConfig;
|
|
19
20
|
}
|
|
20
|
-
static getInstance(appName, configHost) {
|
|
21
|
-
const
|
|
21
|
+
static getInstance(appName, configHost, options) {
|
|
22
|
+
const loadLocalConfig = (options === null || options === void 0 ? void 0 : options.loadLocalConfig) === true;
|
|
23
|
+
const key = `${appName}-${configHost || 'default'}-${loadLocalConfig ? 'local' : 'remote'}`;
|
|
22
24
|
if (!ConfigManager.instances[key]) {
|
|
23
|
-
ConfigManager.instances[key] = new ConfigManager(appName, configHost);
|
|
25
|
+
ConfigManager.instances[key] = new ConfigManager(appName, configHost, loadLocalConfig);
|
|
24
26
|
}
|
|
25
27
|
return ConfigManager.instances[key];
|
|
26
28
|
}
|
|
@@ -29,6 +31,17 @@ class ConfigManager {
|
|
|
29
31
|
if (this.config)
|
|
30
32
|
return this.config;
|
|
31
33
|
try {
|
|
34
|
+
const isBrowser = typeof window !== 'undefined';
|
|
35
|
+
if (this.loadLocalConfig && isBrowser) {
|
|
36
|
+
try {
|
|
37
|
+
const localResponse = yield axios_1.default.get('/config.local.json');
|
|
38
|
+
this.config = localResponse.data;
|
|
39
|
+
return this.config;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.warn('Local config not found, falling back to remote config.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
32
45
|
const host = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
|
|
33
46
|
const response = yield axios_1.default.get(`${this.configHost}/${this.appName}/${host}.json`);
|
|
34
47
|
this.config = response.data;
|
package/dist/useConfig.d.ts
CHANGED
package/dist/useConfig.js
CHANGED
|
@@ -12,13 +12,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.useConfig = void 0;
|
|
13
13
|
const react_1 = require("react");
|
|
14
14
|
const ConfigManager_1 = require("./ConfigManager");
|
|
15
|
-
function useConfig(appName) {
|
|
15
|
+
function useConfig(appName, configHost, options) {
|
|
16
16
|
const [config, setConfig] = (0, react_1.useState)(null);
|
|
17
17
|
const [error, setError] = (0, react_1.useState)(null);
|
|
18
18
|
(0, react_1.useEffect)(() => {
|
|
19
19
|
const fetchConfig = () => __awaiter(this, void 0, void 0, function* () {
|
|
20
20
|
try {
|
|
21
|
-
const cfg = yield ConfigManager_1.ConfigManager.getInstance(appName).loadConfig();
|
|
21
|
+
const cfg = yield ConfigManager_1.ConfigManager.getInstance(appName, configHost, options).loadConfig();
|
|
22
22
|
setConfig(cfg);
|
|
23
23
|
}
|
|
24
24
|
catch (err) {
|
|
@@ -26,7 +26,7 @@ function useConfig(appName) {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
fetchConfig();
|
|
29
|
-
}, [appName]);
|
|
29
|
+
}, [appName, configHost, options]);
|
|
30
30
|
return [config, error];
|
|
31
31
|
}
|
|
32
32
|
exports.useConfig = useConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supaapps-config-fetcher",
|
|
3
|
-
"version": "1.2
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
9
|
"build": "tsc"
|
|
10
10
|
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/supaapps/supaapps-config-fetcher.git"
|
|
14
|
+
},
|
|
11
15
|
"keywords": [],
|
|
12
16
|
"author": "",
|
|
13
17
|
"license": "ISC",
|
package/src/ConfigManager.ts
CHANGED
|
@@ -5,16 +5,27 @@ export class ConfigManager<T> {
|
|
|
5
5
|
private config: T | null = null;
|
|
6
6
|
private appName: string;
|
|
7
7
|
private configHost: string;
|
|
8
|
+
private loadLocalConfig: boolean;
|
|
8
9
|
|
|
9
|
-
private constructor(
|
|
10
|
+
private constructor(
|
|
11
|
+
appName: string,
|
|
12
|
+
configHost: string = 'https://config.envdomain.com',
|
|
13
|
+
loadLocalConfig: boolean = false
|
|
14
|
+
) {
|
|
10
15
|
this.appName = appName;
|
|
11
16
|
this.configHost = configHost;
|
|
17
|
+
this.loadLocalConfig = loadLocalConfig;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
public static getInstance<T>(
|
|
15
|
-
|
|
20
|
+
public static getInstance<T>(
|
|
21
|
+
appName: string,
|
|
22
|
+
configHost?: string,
|
|
23
|
+
options?: { loadLocalConfig?: boolean }
|
|
24
|
+
): ConfigManager<T> {
|
|
25
|
+
const loadLocalConfig = options?.loadLocalConfig === true;
|
|
26
|
+
const key = `${appName}-${configHost || 'default'}-${loadLocalConfig ? 'local' : 'remote'}`;
|
|
16
27
|
if (!ConfigManager.instances[key]) {
|
|
17
|
-
ConfigManager.instances[key] = new ConfigManager<T>(appName, configHost);
|
|
28
|
+
ConfigManager.instances[key] = new ConfigManager<T>(appName, configHost, loadLocalConfig);
|
|
18
29
|
}
|
|
19
30
|
return ConfigManager.instances[key] as ConfigManager<T>;
|
|
20
31
|
}
|
|
@@ -22,6 +33,16 @@ export class ConfigManager<T> {
|
|
|
22
33
|
public async loadConfig(): Promise<T> {
|
|
23
34
|
if (this.config) return this.config;
|
|
24
35
|
try {
|
|
36
|
+
const isBrowser = typeof window !== 'undefined';
|
|
37
|
+
if (this.loadLocalConfig && isBrowser) {
|
|
38
|
+
try {
|
|
39
|
+
const localResponse = await axios.get('/config.local.json');
|
|
40
|
+
this.config = localResponse.data;
|
|
41
|
+
return this.config;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.warn('Local config not found, falling back to remote config.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
25
46
|
const host = typeof window !== 'undefined' ? window.location.hostname : 'localhost';
|
|
26
47
|
const response = await axios.get(`${this.configHost}/${this.appName}/${host}.json`);
|
|
27
48
|
this.config = response.data;
|
package/src/useConfig.ts
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import { ConfigManager } from './ConfigManager';
|
|
3
3
|
|
|
4
|
-
export function useConfig<T>(
|
|
4
|
+
export function useConfig<T>(
|
|
5
|
+
appName: string,
|
|
6
|
+
configHost?: string,
|
|
7
|
+
options?: { loadLocalConfig?: boolean }
|
|
8
|
+
): [T | null, Error | null] {
|
|
5
9
|
const [config, setConfig] = useState<T | null>(null);
|
|
6
10
|
const [error, setError] = useState<Error | null>(null);
|
|
7
11
|
|
|
8
12
|
useEffect(() => {
|
|
9
13
|
const fetchConfig = async () => {
|
|
10
14
|
try {
|
|
11
|
-
const cfg = await ConfigManager.getInstance<T>(appName).loadConfig();
|
|
15
|
+
const cfg = await ConfigManager.getInstance<T>(appName, configHost, options).loadConfig();
|
|
12
16
|
setConfig(cfg);
|
|
13
17
|
} catch (err) {
|
|
14
|
-
setError(err);
|
|
18
|
+
setError(err as Error);
|
|
15
19
|
}
|
|
16
20
|
};
|
|
17
21
|
fetchConfig();
|
|
18
|
-
}, [appName]);
|
|
22
|
+
}, [appName, configHost, options]);
|
|
19
23
|
|
|
20
24
|
return [config, error];
|
|
21
25
|
}
|