monorepo-config 0.1.4 → 0.2.1

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/README.md CHANGED
@@ -35,44 +35,39 @@ Actually setting the config happens in yet another place. Using `setConfig(confi
35
35
 
36
36
  ## Profile-based usage
37
37
 
38
- This allows you to replace the mess of untyped, unchecked env vars across packages with something more manageable (inspired by [Django](https://docs.djangoproject.com/en/6.0/topics/settings/)).
38
+ **Still being worked on! Typescript imports may lead to dependency cycles, which breaks some tools.**
39
39
 
40
- First you can (optionally) set `profileDir` on your configuration definition:
41
-
42
- ```ts
43
- export const configDef = makeConfig({
44
- package: 'your-package',
45
- schema: z.object({
46
- foobar: z.string(),
47
- }),
48
- depedencies: [ otherConfigDef ],
49
- profileDir: import.meta.dirname,
50
- });
51
- ```
52
-
53
- You can then load the chosen configuration based on a single environment variable like so:
40
+ This allows you to replace the mess of untyped, unchecked env vars across packages with something more manageable (inspired by [Django](https://docs.djangoproject.com/en/6.0/topics/settings/)). You can load the chosen configuration based on a single environment variable like so:
54
41
 
55
42
  ```ts
56
43
  import { loadConfigProfile } from "monorepo-config";
57
44
  import { configDef } from "./config-def.ts";
58
45
 
59
- export const FOOBAR_CONFIG = await loadConfigProfile(configDef, 'FOOBAR_CONFIG');
46
+ export const loader = loadProfileByEnvVar('FOOBAR_CONFIG', (profile) => import(`./${profile}.js`).then(x => x.default))
47
+
48
+ export const FOOBAR_CONFIG = await loadConfigProfile(configDef, loader);
60
49
  ```
61
50
 
62
51
  Profiles are just typescript files like this:
63
52
 
64
53
  ```ts
54
+ import type { MergeConfigTypes } from "monorepo-config";
65
55
  import type { configDef } from "./config-def.ts";
56
+ import type { otherConfigDef } from "other-package/config-def.ts";
57
+
58
+ type Config = MergeConfigTypes<[
59
+ typeof configDef, typeof otherConfig, ...
60
+ ]>;
66
61
 
67
62
  export default {
68
63
  'your-package': {
69
64
  foobar: 'quuz'
70
65
  },
71
66
  'other-config': { ... }
72
- } satisfies typeof configDef.input;
67
+ } satisfies Config;
73
68
  ```
74
69
 
75
- You can choose, like the example, to use the same name the configuration object as the environment variable. The idea is to use the same environment variable for all packages in your monorepo (this mirrors `DJANGO_SETTINGS_MODULE`).
70
+ You can split up the above as you wish. You can choose, like the example, to use the same name for the configuration object as the environment variable. The idea is to use the same environment variable for all packages in your monorepo (this mirrors `DJANGO_SETTINGS_MODULE`).
76
71
 
77
72
 
78
73
  ## Which to use?
@@ -80,6 +75,13 @@ You can choose, like the example, to use the same name the configuration object
80
75
  You can mix both in your monorepo! Packages representing reusable libraries probably want to stick with the basic usage and let other packages define their config. Packages that represent apps probably want to define their own config using profiles.
81
76
 
82
77
 
78
+ ## Common errors
79
+
80
+ ### Package name '...' is used for two different config definitions
81
+
82
+ Your package manager may have included two different copies of the same code. Run `pnpm dedupe`, or manually inspect your lockfile to verify this. If not, add `console.trace()` calls to the `defineConfig` function to figure out exactly where the configs are defined.
83
+
84
+
83
85
  ## TODO
84
86
 
85
87
  - [ ] Vite plugin
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { defineConfig, setConfig, getConfig } from "./basic.js";
2
2
  export type { MergeConfigTypes } from "./basic.js";
3
- export { loadConfigProfile } from "./profile.js";
3
+ export { loadConfigProfile, loadProfileByEnvVar } from "./profile.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { defineConfig, setConfig, getConfig } from "./basic.js";
2
- export { loadConfigProfile } from "./profile.js";
2
+ export { loadConfigProfile, loadProfileByEnvVar } from "./profile.js";
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
package/dist/profile.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import type { output, ZodObject } from "zod";
2
2
  import { ConfigDefinition } from "./basic.js";
3
+ export type ProfileLoader = (profile: string) => Promise<object>;
4
+ export declare function loadProfileByEnvVar(envVar: string, importer: ProfileLoader): () => Promise<object>;
3
5
  export declare function loadConfigProfile<PackageName extends string, ConfigSchema extends ZodObject, SubSchemas extends Record<string, ZodObject>>(config: ConfigDefinition<PackageName, ConfigSchema, SubSchemas> & {
4
- profileDir: string;
5
- profileSuffix?: string;
6
- }, envVar: string, profileDir?: string): Promise<output<ConfigSchema>>;
7
- export declare function loadConfigProfile<PackageName extends string, ConfigSchema extends ZodObject, SubSchemas extends Record<string, ZodObject>>(config: ConfigDefinition<PackageName, ConfigSchema, SubSchemas> & {
8
- profileSuffix?: string;
9
- }, envVar: string, profileDir: string): Promise<output<ConfigSchema>>;
6
+ loader: () => Promise<object>;
7
+ }, loader?: () => Promise<object>): Promise<output<ConfigSchema>>;
8
+ export declare function loadConfigProfile<PackageName extends string, ConfigSchema extends ZodObject, SubSchemas extends Record<string, ZodObject>>(config: ConfigDefinition<PackageName, ConfigSchema, SubSchemas>, loader: () => Promise<object>): Promise<output<ConfigSchema>>;
10
9
  //# sourceMappingURL=profile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAC7C,OAAO,EAAe,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAGtE,wBAAsB,iBAAiB,CACrC,WAAW,SAAS,MAAM,EAC1B,YAAY,SAAS,SAAS,EAC9B,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAE5C,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EAChH,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;AAEhC,wBAAsB,iBAAiB,CACrC,WAAW,SAAS,MAAM,EAC1B,YAAY,SAAS,SAAS,EAC9B,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAE5C,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5F,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAC7C,OAAO,EAAe,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAIjE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAWlG;AAED,wBAAsB,iBAAiB,CACrC,WAAW,SAAS,MAAM,EAC1B,YAAY,SAAS,SAAS,EAC9B,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAE5C,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,EACnG,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;AAEhC,wBAAsB,iBAAiB,CACrC,WAAW,SAAS,MAAM,EAC1B,YAAY,SAAS,SAAS,EAC9B,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAE5C,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,EAC/D,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA"}
package/dist/profile.js CHANGED
@@ -1,19 +1,28 @@
1
1
  import { ConfigError, setConfig } from "./basic.js";
2
- import { join } from "path";
3
- export async function loadConfigProfile(config, envVar, profileDir) {
4
- const configName = process.env[envVar];
5
- if (configName === undefined) {
6
- throw new ConfigError(`Please set the environment variable ${envVar}`);
7
- }
8
- profileDir = profileDir ?? config.profileDir;
9
- if (profileDir === undefined) {
10
- throw new ConfigError(`Either give profileDir as an argument or set profileDir in the config metadata`);
2
+ const ProfileName = Symbol('monorepo-config:ProfileName');
3
+ export function loadProfileByEnvVar(envVar, importer) {
4
+ return async () => {
5
+ const profileName = process.env[envVar];
6
+ if (profileName === undefined) {
7
+ throw new ConfigError(`Please set the environment variable ${envVar}`);
8
+ }
9
+ const res = await importer(profileName);
10
+ res[ProfileName] = profileName;
11
+ return res;
12
+ };
13
+ }
14
+ export async function loadConfigProfile(config, loader) {
15
+ loader = loader ?? config.loader;
16
+ if (loader === undefined) {
17
+ throw new ConfigError(`Either give loader as an argument or set loader in the config metadata`);
11
18
  }
12
- const path = join(profileDir, `${configName}.${config.profileSuffix ?? 'js'}`);
13
- const data = (await import(path)).default;
19
+ console.debug("LOADER IS", loader);
20
+ //const path = join(loader, `${configName}.${config.profileSuffix ?? 'js'}`);
21
+ const data = await loader();
14
22
  setConfig(config, data);
15
23
  if (!config.isLoaded) {
16
- console.warn(`WARNING: Imported ${path} into ${config.package} but config was still not marked as set`);
24
+ const profileName = data[ProfileName];
25
+ console.warn(`WARNING: Imported config (profile ${profileName}) for ${config.package} but config was still not marked as set`);
17
26
  }
18
27
  return config.output;
19
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAoB,SAAS,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAsB5B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAKrC,MAAiH,EACjH,MAAc,EACd,UAAmB;IAEnB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,WAAW,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,UAAU,GAAG,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC;IAC7C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,WAAW,CAAC,gFAAgF,CAAC,CAAC;IAC1G,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,UAAU,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1C,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAExB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,qBAAqB,IAAI,SAAS,MAAM,CAAC,OAAO,yCAAyC,CAAC,CAAC;IAC1G,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAoB,SAAS,EAAE,MAAM,YAAY,CAAC;AAItE,MAAM,WAAW,GAAkB,MAAM,CAAC,6BAA6B,CAAC,CAAC;AAEzE,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,QAAuB;IACzE,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,WAAW,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC;QACvC,GAAW,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;QACxC,OAAO,GAAG,CAAC;IACb,CAAC,CAAA;AACH,CAAC;AAoBD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAKrC,MAAoG,EACpG,MAA8B;IAE9B,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,WAAW,CAAC,wEAAwE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnC,6EAA6E;IAC7E,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,EAAE,IAAW,CAAC,CAAC;IAE/B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,WAAW,GAAI,IAAY,CAAC,WAAW,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,qCAAqC,WAAW,SAAS,MAAM,CAAC,OAAO,yCAAyC,CAAC,CAAC;IACjI,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monorepo-config",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "description": "Managed and validated configs across packages (no deps, but bring your own zod)",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",