@dsmrt/axiom-config 0.2.3 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @dsmrt/axiom-config
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b1a56bc: adding debug logging to the cli and config packages
8
+
9
+ ## 1.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - d767a0e: Making loadConfig return a promise; adding typescript config support and better esm/mjs/mts support; better docs
14
+
3
15
  ## 0.2.3
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -38,8 +38,8 @@ interface LoadConfigInput {
38
38
  */
39
39
  cwd?: string;
40
40
  }
41
- declare const importConfigFromPath: (path: string) => Config;
42
- declare const loadConfig: <T extends object>(input?: LoadConfigInput) => ConfigContainer & T;
41
+ declare const importConfigFromPath: (path: string) => Promise<Config>;
42
+ declare const loadConfig: <T extends object>(input?: LoadConfigInput) => Promise<ConfigContainer & T>;
43
43
  /**
44
44
  * Simple object check.
45
45
  */
package/dist/index.d.ts CHANGED
@@ -38,8 +38,8 @@ interface LoadConfigInput {
38
38
  */
39
39
  cwd?: string;
40
40
  }
41
- declare const importConfigFromPath: (path: string) => Config;
42
- declare const loadConfig: <T extends object>(input?: LoadConfigInput) => ConfigContainer & T;
41
+ declare const importConfigFromPath: (path: string) => Promise<Config>;
42
+ declare const loadConfig: <T extends object>(input?: LoadConfigInput) => Promise<ConfigContainer & T>;
43
43
  /**
44
44
  * Simple object check.
45
45
  */
package/dist/index.js CHANGED
@@ -28,8 +28,14 @@ __export(index_exports, {
28
28
  mergeDeep: () => mergeDeep
29
29
  });
30
30
  module.exports = __toCommonJS(index_exports);
31
- var import_fs = require("fs");
32
- var import_find_up = require("find-up");
31
+ var import_node_fs = require("fs");
32
+ var import_glob = require("glob");
33
+ var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
34
+ var debug = (message, ...args) => {
35
+ if (isDebugEnabled()) {
36
+ console.error(`[axiom:config] ${message}`, ...args);
37
+ }
38
+ };
33
39
  var ConfigContainer = class {
34
40
  name;
35
41
  env;
@@ -45,33 +51,83 @@ var ConfigContainer = class {
45
51
  }
46
52
  }
47
53
  isProd() {
48
- return this.env == this.prodEnvName;
54
+ return this.env === this.prodEnvName;
49
55
  }
50
56
  asParameterPath(name) {
51
- return this.aws.baseParameterPath.replace(new RegExp("/+$"), "") + `/${name}`;
57
+ return `${this.aws.baseParameterPath.replace(/\/+$/, "")}/${name}`;
52
58
  }
53
59
  };
54
- var importConfigFromPath = (path) => {
60
+ var importConfigFromPath = async (path) => {
61
+ debug(`Attempting to import config from: ${path}`);
55
62
  if (/\.json$/.test(path)) {
56
- return JSON.parse((0, import_fs.readFileSync)(path).toString());
63
+ debug(`Loading JSON config file: ${path}`);
64
+ try {
65
+ const config = JSON.parse((0, import_node_fs.readFileSync)(path).toString());
66
+ debug(`Successfully loaded JSON config with name: ${config.name}`);
67
+ return config;
68
+ } catch (error) {
69
+ debug(`Failed to parse JSON config: ${error}`);
70
+ throw error;
71
+ }
57
72
  }
58
- if (/\.(m)?[j|t]s$/.test(path)) {
59
- return require(path);
73
+ if (/\.((m)?ts|mjs)$/.test(path)) {
74
+ debug(`Loading TypeScript/ESM config file: ${path}`);
75
+ try {
76
+ const loaded = await import(path);
77
+ const config = loaded.default || loaded;
78
+ debug(`Successfully loaded TS/ESM config with name: ${config.name}`);
79
+ return config;
80
+ } catch (error) {
81
+ debug(`Failed to import TS/ESM config: ${error}`);
82
+ throw error;
83
+ }
84
+ }
85
+ if (/\.(m)?js$/.test(path)) {
86
+ debug(`Loading JavaScript config file: ${path}`);
87
+ try {
88
+ const loaded = require(path);
89
+ const config = loaded.default || loaded;
90
+ debug(`Successfully loaded JS config with name: ${config.name}`);
91
+ return config;
92
+ } catch (error) {
93
+ debug(`Failed to require JS config: ${error}`);
94
+ throw error;
95
+ }
60
96
  }
61
- throw new Error(`Path not found: {path}`);
97
+ debug(`Unsupported file type: ${path}`);
98
+ throw new Error(`Unsupported file type or path not found: ${path}`);
62
99
  };
63
- var loadConfig = (input) => {
100
+ var loadConfig = async (input) => {
101
+ debug(
102
+ `Loading config with options:`,
103
+ JSON.stringify({
104
+ env: input?.env,
105
+ cwd: input?.cwd,
106
+ hasOverrides: !!input?.overrides
107
+ })
108
+ );
109
+ debug(`Looking for base config file...`);
64
110
  const baseConfigFile = configPath({
65
111
  ...input,
66
112
  env: void 0
67
113
  });
68
- const baseConfig = importConfigFromPath(baseConfigFile);
114
+ debug(`Loading base config from: ${baseConfigFile}`);
115
+ const baseConfig = await importConfigFromPath(baseConfigFile);
116
+ debug(`Base config loaded: ${baseConfig.name} (env: ${baseConfig.env})`);
69
117
  let overrides = input?.overrides || {};
70
118
  if (input?.env) {
71
- const devConfig = importConfigFromPath(configPath(input));
119
+ debug(`Looking for environment-specific config for: ${input.env}`);
120
+ const envConfigPath = configPath(input);
121
+ debug(`Loading env config from: ${envConfigPath}`);
122
+ const devConfig = await importConfigFromPath(envConfigPath);
123
+ debug(`Env config loaded: ${devConfig.name} (env: ${devConfig.env})`);
72
124
  overrides = mergeDeep(devConfig, overrides);
125
+ debug(`Merged env config with overrides`);
73
126
  }
74
127
  const configObject = mergeDeep(baseConfig, overrides);
128
+ debug(
129
+ `Final config: ${configObject.name} (env: ${configObject.env}, isProd: ${configObject.env === (configObject.prodEnvName || "prod")})`
130
+ );
75
131
  return new ConfigContainer(configObject);
76
132
  };
77
133
  function isObject(item) {
@@ -94,21 +150,39 @@ function mergeDeep(target, ...sources) {
94
150
  }
95
151
  var configPath = (input) => {
96
152
  const envIndicator = input?.env ? `.${input.env}` : "";
97
- const p = (0, import_find_up.sync)(
98
- [
99
- `.axiom${envIndicator}.json`,
100
- `.axiom${envIndicator}.js`,
101
- `.axiom${envIndicator}.mjs`,
102
- `.axiom${envIndicator}.ts`,
103
- `.axiom${envIndicator}.mts`
104
- ],
105
- { cwd: input?.cwd }
153
+ const extensions = ["json", "js", "mjs", "ts", "mts"];
154
+ const pattern = `.axiom${envIndicator}.{${extensions.join(",")}}`;
155
+ debug(
156
+ `Searching for config files with pattern: ${pattern}`,
157
+ input?.cwd ? `from ${input.cwd}` : "from current directory"
106
158
  );
107
- if (p === void 0)
159
+ const cwd = input?.cwd || process.cwd();
160
+ let currentDir = cwd;
161
+ let found;
162
+ while (true) {
163
+ const matches = (0, import_glob.globSync)(pattern, {
164
+ cwd: currentDir,
165
+ absolute: true,
166
+ nodir: true
167
+ });
168
+ if (matches.length > 0) {
169
+ found = matches[0];
170
+ break;
171
+ }
172
+ const parent = require("path").dirname(currentDir);
173
+ if (parent === currentDir) {
174
+ break;
175
+ }
176
+ currentDir = parent;
177
+ }
178
+ if (found === void 0) {
179
+ debug(`Config file not found! Searched for pattern: ${pattern}`);
108
180
  throw new Error(
109
181
  `Axiom config files not found: .axiom${envIndicator}.json, .axiom${envIndicator}.js .axiom${envIndicator}.ts`
110
182
  );
111
- return p;
183
+ }
184
+ debug(`Found config file: ${found}`);
185
+ return found;
112
186
  };
113
187
  // Annotate the CommonJS export names for ESM import in node:
114
188
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -7,7 +7,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
 
8
8
  // src/index.ts
9
9
  import { readFileSync } from "fs";
10
- import { sync as findUpSync } from "find-up";
10
+ import { globSync } from "glob";
11
+ var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
12
+ var debug = (message, ...args) => {
13
+ if (isDebugEnabled()) {
14
+ console.error(`[axiom:config] ${message}`, ...args);
15
+ }
16
+ };
11
17
  var ConfigContainer = class {
12
18
  name;
13
19
  env;
@@ -23,33 +29,83 @@ var ConfigContainer = class {
23
29
  }
24
30
  }
25
31
  isProd() {
26
- return this.env == this.prodEnvName;
32
+ return this.env === this.prodEnvName;
27
33
  }
28
34
  asParameterPath(name) {
29
- return this.aws.baseParameterPath.replace(new RegExp("/+$"), "") + `/${name}`;
35
+ return `${this.aws.baseParameterPath.replace(/\/+$/, "")}/${name}`;
30
36
  }
31
37
  };
32
- var importConfigFromPath = (path) => {
38
+ var importConfigFromPath = async (path) => {
39
+ debug(`Attempting to import config from: ${path}`);
33
40
  if (/\.json$/.test(path)) {
34
- return JSON.parse(readFileSync(path).toString());
41
+ debug(`Loading JSON config file: ${path}`);
42
+ try {
43
+ const config = JSON.parse(readFileSync(path).toString());
44
+ debug(`Successfully loaded JSON config with name: ${config.name}`);
45
+ return config;
46
+ } catch (error) {
47
+ debug(`Failed to parse JSON config: ${error}`);
48
+ throw error;
49
+ }
35
50
  }
36
- if (/\.(m)?[j|t]s$/.test(path)) {
37
- return __require(path);
51
+ if (/\.((m)?ts|mjs)$/.test(path)) {
52
+ debug(`Loading TypeScript/ESM config file: ${path}`);
53
+ try {
54
+ const loaded = await import(path);
55
+ const config = loaded.default || loaded;
56
+ debug(`Successfully loaded TS/ESM config with name: ${config.name}`);
57
+ return config;
58
+ } catch (error) {
59
+ debug(`Failed to import TS/ESM config: ${error}`);
60
+ throw error;
61
+ }
62
+ }
63
+ if (/\.(m)?js$/.test(path)) {
64
+ debug(`Loading JavaScript config file: ${path}`);
65
+ try {
66
+ const loaded = __require(path);
67
+ const config = loaded.default || loaded;
68
+ debug(`Successfully loaded JS config with name: ${config.name}`);
69
+ return config;
70
+ } catch (error) {
71
+ debug(`Failed to require JS config: ${error}`);
72
+ throw error;
73
+ }
38
74
  }
39
- throw new Error(`Path not found: {path}`);
75
+ debug(`Unsupported file type: ${path}`);
76
+ throw new Error(`Unsupported file type or path not found: ${path}`);
40
77
  };
41
- var loadConfig = (input) => {
78
+ var loadConfig = async (input) => {
79
+ debug(
80
+ `Loading config with options:`,
81
+ JSON.stringify({
82
+ env: input?.env,
83
+ cwd: input?.cwd,
84
+ hasOverrides: !!input?.overrides
85
+ })
86
+ );
87
+ debug(`Looking for base config file...`);
42
88
  const baseConfigFile = configPath({
43
89
  ...input,
44
90
  env: void 0
45
91
  });
46
- const baseConfig = importConfigFromPath(baseConfigFile);
92
+ debug(`Loading base config from: ${baseConfigFile}`);
93
+ const baseConfig = await importConfigFromPath(baseConfigFile);
94
+ debug(`Base config loaded: ${baseConfig.name} (env: ${baseConfig.env})`);
47
95
  let overrides = input?.overrides || {};
48
96
  if (input?.env) {
49
- const devConfig = importConfigFromPath(configPath(input));
97
+ debug(`Looking for environment-specific config for: ${input.env}`);
98
+ const envConfigPath = configPath(input);
99
+ debug(`Loading env config from: ${envConfigPath}`);
100
+ const devConfig = await importConfigFromPath(envConfigPath);
101
+ debug(`Env config loaded: ${devConfig.name} (env: ${devConfig.env})`);
50
102
  overrides = mergeDeep(devConfig, overrides);
103
+ debug(`Merged env config with overrides`);
51
104
  }
52
105
  const configObject = mergeDeep(baseConfig, overrides);
106
+ debug(
107
+ `Final config: ${configObject.name} (env: ${configObject.env}, isProd: ${configObject.env === (configObject.prodEnvName || "prod")})`
108
+ );
53
109
  return new ConfigContainer(configObject);
54
110
  };
55
111
  function isObject(item) {
@@ -72,21 +128,39 @@ function mergeDeep(target, ...sources) {
72
128
  }
73
129
  var configPath = (input) => {
74
130
  const envIndicator = input?.env ? `.${input.env}` : "";
75
- const p = findUpSync(
76
- [
77
- `.axiom${envIndicator}.json`,
78
- `.axiom${envIndicator}.js`,
79
- `.axiom${envIndicator}.mjs`,
80
- `.axiom${envIndicator}.ts`,
81
- `.axiom${envIndicator}.mts`
82
- ],
83
- { cwd: input?.cwd }
131
+ const extensions = ["json", "js", "mjs", "ts", "mts"];
132
+ const pattern = `.axiom${envIndicator}.{${extensions.join(",")}}`;
133
+ debug(
134
+ `Searching for config files with pattern: ${pattern}`,
135
+ input?.cwd ? `from ${input.cwd}` : "from current directory"
84
136
  );
85
- if (p === void 0)
137
+ const cwd = input?.cwd || process.cwd();
138
+ let currentDir = cwd;
139
+ let found;
140
+ while (true) {
141
+ const matches = globSync(pattern, {
142
+ cwd: currentDir,
143
+ absolute: true,
144
+ nodir: true
145
+ });
146
+ if (matches.length > 0) {
147
+ found = matches[0];
148
+ break;
149
+ }
150
+ const parent = __require("path").dirname(currentDir);
151
+ if (parent === currentDir) {
152
+ break;
153
+ }
154
+ currentDir = parent;
155
+ }
156
+ if (found === void 0) {
157
+ debug(`Config file not found! Searched for pattern: ${pattern}`);
86
158
  throw new Error(
87
159
  `Axiom config files not found: .axiom${envIndicator}.json, .axiom${envIndicator}.js .axiom${envIndicator}.ts`
88
160
  );
89
- return p;
161
+ }
162
+ debug(`Found config file: ${found}`);
163
+ return found;
90
164
  };
91
165
  export {
92
166
  ConfigContainer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsmrt/axiom-config",
3
- "version": "0.2.3",
3
+ "version": "1.1.0",
4
4
  "description": "Config library for axiom cli",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -24,26 +24,23 @@
24
24
  },
25
25
  "license": "MIT",
26
26
  "devDependencies": {
27
+ "@biomejs/biome": "^2.3.8",
27
28
  "@changesets/cli": "^2.27.11",
28
- "@types/node": "^20.17.10",
29
+ "@types/node": "^22.12.0",
29
30
  "@types/yargs": "^17.0.33",
30
- "@typescript-eslint/eslint-plugin": "^6.21.0",
31
- "@typescript-eslint/parser": "^6.21.0",
32
- "@vitest/coverage-v8": "^1.6.0",
33
- "eslint": "^8.57.1",
34
- "prettier": "^3.4.2",
31
+ "@vitest/coverage-v8": "^4.0.0",
35
32
  "ts-node": "^10.9.2",
36
33
  "tsup": "^8.3.5",
37
34
  "typescript": "^5.7.2",
38
- "vitest": "^1.6.0"
35
+ "vitest": "^4.0.0"
39
36
  },
40
37
  "dependencies": {
41
- "find-up": "^5.0.0",
38
+ "glob": "^10.5.0",
42
39
  "yargs": "^17.7.2"
43
40
  },
44
41
  "scripts": {
45
- "lint": "eslint ./src/ --ext .ts",
46
- "lint:fix": "eslint ./src/ --ext .ts --fix",
42
+ "lint": "biome lint",
43
+ "lint:fix": "biome lint --fix",
47
44
  "test": "vitest run --coverage",
48
45
  "watch": "vitest watch --coverage",
49
46
  "build": "tsup --entry ./src/bin/axiom.ts --entry ./src/index.ts --format cjs,esm --dts --clean",
package/tsconfig.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "module": "commonjs",
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "noEmit": true
10
- },
11
- "include": ["src/index.ts"]
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "noEmit": true
10
+ },
11
+ "include": ["src/index.ts"]
12
12
  }
package/vitest.config.mts CHANGED
@@ -2,13 +2,13 @@
2
2
  import { defineConfig } from "vitest/config";
3
3
 
4
4
  export default defineConfig({
5
- test: {
6
- include: ["src/**/*.test.ts"],
7
- coverage: {
8
- provider: "v8",
9
- all: true,
10
- exclude: ["lib/**/*", "src/__mocks__/**/*"],
11
- reporter: ["text-summary", "json-summary"],
12
- },
13
- },
5
+ test: {
6
+ include: ["src/**/*.test.ts"],
7
+ coverage: {
8
+ provider: "v8",
9
+ all: true,
10
+ exclude: ["lib/**/*", "src/__mocks__/**/*"],
11
+ reporter: ["text-summary", "json-summary"],
12
+ },
13
+ },
14
14
  });