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.
@@ -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
@@ -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): ConfigManager<T>;
8
+ static getInstance<T>(appName: string, configHost?: string, options?: {
9
+ loadLocalConfig?: boolean;
10
+ }): ConfigManager<T>;
8
11
  loadConfig(): Promise<T>;
9
12
  }
@@ -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 key = `${appName}-${configHost || 'default'}`;
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;
@@ -1 +1,3 @@
1
- export declare function useConfig<T>(appName: string): [T | null, Error | null];
1
+ export declare function useConfig<T>(appName: string, configHost?: string, options?: {
2
+ loadLocalConfig?: boolean;
3
+ }): [T | null, Error | null];
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.0",
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",
@@ -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(appName: string, configHost: string = 'https://config.envdomain.com') {
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>(appName: string, configHost?: string): ConfigManager<T> {
15
- const key = `${appName}-${configHost || 'default'}`;
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>(appName: string): [T | null, Error | null] {
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
  }