Skip to content

Commit 582c2a4

Browse files
committed
feat: improves deduplication across code generation modules
1 parent 98eaec8 commit 582c2a4

File tree

13 files changed

+111
-87
lines changed

13 files changed

+111
-87
lines changed

app-config-config/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
EnvironmentAliases,
1717
EnvironmentSource,
1818
asEnvOptions,
19+
currentEnvironment,
1920
} from '@app-config/node';
2021
import { markAllValuesAsSecret } from '@app-config/extensions';
2122
import { defaultExtensions, defaultEnvExtensions } from '@app-config/default-extensions';
@@ -44,6 +45,8 @@ export interface LoadedConfiguration {
4445
parsed: ParsedValue;
4546
parsedSecrets?: ParsedValue;
4647
parsedNonSecrets?: ParsedValue;
48+
/** the current environment that was loaded from given options */
49+
environment?: string;
4750
/** non-exhaustive list of files that were read (useful for reloading in plugins) */
4851
filePaths?: string[];
4952
/** if loadValidatedConfig, this is the normalized JSON schema that was used for validation */
@@ -186,6 +189,7 @@ export async function loadUnvalidatedConfig({
186189
parsed,
187190
parsedSecrets: secrets,
188191
parsedNonSecrets: mainConfig.cloneWhere((v) => !v.meta.fromSecrets),
192+
environment: currentEnvironment(environmentOptions),
189193
fullConfig: parsed.toJSON(),
190194
filePaths: Array.from(filePaths),
191195
};

app-config-esbuild/src/index.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
import type { Plugin } from 'esbuild';
2-
import { loadValidatedConfig } from '@app-config/config';
3-
import { currentEnvironment } from '@app-config/node';
2+
import { ConfigLoadingOptions, loadValidatedConfig } from '@app-config/config';
43
import { generateModuleText, packageNameRegex } from '@app-config/utils';
4+
import type { SchemaLoadingOptions } from '@app-config/schema';
55

6-
const plugin: Plugin = {
7-
name: 'app-config',
6+
export interface Options {
7+
useGlobalNamespace?: boolean;
8+
loadingOptions?: ConfigLoadingOptions;
9+
schemaLoadingOptions?: SchemaLoadingOptions;
10+
injectValidationFunction?: boolean;
11+
}
12+
13+
export const createPlugin = ({
14+
useGlobalNamespace = true,
15+
loadingOptions,
16+
schemaLoadingOptions,
17+
injectValidationFunction = true,
18+
}: Options = {}): Plugin => ({
19+
name: '@app-config/esbuild',
820
setup(build) {
921
build.onResolve({ filter: packageNameRegex }, (args) => ({
1022
path: args.path,
11-
namespace: 'app-config-ns',
23+
namespace: '@app-config/esbuild',
1224
}));
1325

14-
build.onLoad({ filter: /.*/, namespace: 'app-config-ns' }, async () => {
15-
const { fullConfig, validationFunctionCode } = await loadValidatedConfig();
26+
build.onLoad({ filter: /.*/, namespace: '@app-config/esbuild' }, async () => {
27+
const { fullConfig, environment, validationFunctionCode } = await loadValidatedConfig(
28+
loadingOptions,
29+
schemaLoadingOptions,
30+
);
1631

1732
const code = generateModuleText(fullConfig, {
18-
esm: true,
19-
noGlobal: false,
20-
currentEnvironment: currentEnvironment(),
21-
validationFunctionCode,
33+
environment,
34+
useGlobalNamespace,
35+
validationFunctionCode: injectValidationFunction ? validationFunctionCode : undefined,
36+
esmValidationCode: true,
2237
});
2338

2439
return {
@@ -27,6 +42,6 @@ const plugin: Plugin = {
2742
};
2843
});
2944
},
30-
};
45+
});
3146

32-
export default plugin;
47+
export default createPlugin;

app-config-rollup/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
},
3636
"dependencies": {
3737
"@app-config/config": "^2.7.2",
38-
"@app-config/node": "^2.7.2",
3938
"@app-config/utils": "^2.7.2"
4039
},
4140
"peerDependencies": {},

app-config-rollup/src/index.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
import type { Plugin } from 'rollup';
22
import { generateModuleText, packageNameRegex } from '@app-config/utils';
33
import { ConfigLoadingOptions, loadValidatedConfig } from '@app-config/config';
4-
import { asEnvOptions, currentEnvironment } from '@app-config/node';
54
import type { SchemaLoadingOptions } from '@app-config/schema';
65

76
export interface Options {
8-
readGlobal?: boolean;
9-
injectValidationFunction?: boolean;
7+
useGlobalNamespace?: boolean;
108
loadingOptions?: ConfigLoadingOptions;
119
schemaLoadingOptions?: SchemaLoadingOptions;
10+
injectValidationFunction?: boolean;
11+
12+
/** @deprecated use useGlobalNamespace instead */
13+
readGlobal?: boolean;
1214
}
1315

1416
// vite resolves first before passing to the rollup plugin
1517
export const appConfigImportRegex = /(app-config|app-config-main)\/dist(\/es)?\/index\.js/;
1618

1719
export default function appConfigRollup({
18-
readGlobal,
19-
injectValidationFunction,
20+
useGlobalNamespace,
2021
loadingOptions,
2122
schemaLoadingOptions,
23+
injectValidationFunction,
24+
25+
readGlobal,
2226
}: Options = {}): Plugin & { currentFilePaths?: string[] } {
2327
const currentFilePaths: string[] = [];
2428

@@ -34,27 +38,19 @@ export default function appConfigRollup({
3438
},
3539
async load(id) {
3640
if (packageNameRegex.exec(id) || appConfigImportRegex.exec(id)) {
37-
const { fullConfig, validationFunctionCode, filePaths } = await loadValidatedConfig(
38-
loadingOptions,
39-
schemaLoadingOptions,
40-
);
41+
const { fullConfig, environment, validationFunctionCode, filePaths } =
42+
await loadValidatedConfig(loadingOptions, schemaLoadingOptions);
4143

4244
if (filePaths) {
4345
currentFilePaths.length = 0;
4446
currentFilePaths.push(...filePaths);
4547
}
4648

4749
return generateModuleText(fullConfig, {
48-
esm: true,
49-
noGlobal: !readGlobal,
50-
currentEnvironment: currentEnvironment(
51-
asEnvOptions(
52-
loadingOptions?.environmentOverride,
53-
loadingOptions?.environmentAliases,
54-
loadingOptions?.environmentSourceNames,
55-
),
56-
),
50+
environment,
51+
useGlobalNamespace: useGlobalNamespace ?? readGlobal ?? true,
5752
validationFunctionCode: injectValidationFunction ? validationFunctionCode : undefined,
53+
esmValidationCode: true,
5854
});
5955
}
6056

app-config-rollup/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"include": ["src"],
88
"exclude": ["node_modules"],
99
"references": [
10+
{ "path": "../app-config-config" },
1011
{ "path": "../app-config-utils" },
1112
{ "path": "../app-config-test-utils" }
1213
]

app-config-utils/src/index.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,24 @@ export function isPrimitive(obj: Json): obj is JsonPrimitive {
2828
export function generateModuleText(
2929
fullConfig: Json,
3030
{
31-
esm,
32-
noGlobal,
33-
currentEnvironment,
31+
environment,
32+
useGlobalNamespace,
3433
validationFunctionCode,
34+
esmValidationCode,
3535
}: {
36-
esm: boolean;
37-
noGlobal: boolean;
38-
currentEnvironment: string | undefined;
36+
environment: string | undefined;
37+
useGlobalNamespace: boolean;
3938
validationFunctionCode?(): string;
4039
validationFunctionCode?(esm: true): [string, string];
40+
esmValidationCode: boolean;
4141
},
4242
): string {
4343
const privateName = '_appConfig';
4444
const config = JSON.stringify(fullConfig);
4545

4646
let generatedText: string;
4747

48-
if (noGlobal) {
49-
generatedText = `
50-
const config = ${config};
51-
52-
export { config };
53-
export default config;
54-
`;
55-
} else {
48+
if (useGlobalNamespace) {
5649
generatedText = `
5750
const configValue = ${config};
5851
@@ -69,13 +62,20 @@ export function generateModuleText(
6962
globalNamespace.${privateName} = config;
7063
}
7164
65+
export { config };
66+
export default config;
67+
`;
68+
} else {
69+
generatedText = `
70+
const config = ${config};
71+
7272
export { config };
7373
export default config;
7474
`;
7575
}
7676

7777
if (validationFunctionCode) {
78-
if (esm) {
78+
if (esmValidationCode) {
7979
const [code, imports] = validationFunctionCode(true);
8080

8181
generatedText = `${generatedText}
@@ -110,7 +110,7 @@ export function generateModuleText(
110110

111111
generatedText = `${generatedText}
112112
export function currentEnvironment() {
113-
return ${currentEnvironment ? JSON.stringify(currentEnvironment) : 'undefined'};
113+
return ${environment ? JSON.stringify(environment) : 'undefined'};
114114
}
115115
`;
116116

app-config-webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"prepublishOnly": "yarn clean && yarn build && yarn build:es"
3232
},
3333
"dependencies": {
34-
"@app-config/node": "^2.7.2",
34+
"@app-config/config": "^2.7.2",
3535
"@app-config/utils": "^2.7.2",
3636
"loader-utils": "2"
3737
},

app-config-webpack/src/index.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,44 @@
11
import { join } from 'path';
22
import { Compiler } from 'webpack';
33
import HtmlWebpackPlugin from 'html-webpack-plugin';
4-
import { ConfigLoadingOptions, SchemaLoadingOptions } from '@app-config/main';
4+
import type { ConfigLoadingOptions, SchemaLoadingOptions } from '@app-config/main';
5+
56
import { regex } from './loader';
67

78
// loader is the filepath, not the export
89
const loader = require.resolve('./loader');
910

1011
export interface Options {
1112
headerInjection?: boolean;
13+
useGlobalNamespace?: boolean;
14+
loadingOptions?: ConfigLoadingOptions;
15+
schemaLoadingOptions?: SchemaLoadingOptions;
16+
intercept?: RegExp;
17+
injectValidationFunction?: boolean;
18+
19+
/** @deprecated use useGlobalNamespace instead */
1220
noGlobal?: boolean;
21+
/** @deprecated use loadingOptions instead */
1322
loading?: ConfigLoadingOptions;
23+
/** @deprecated use schemaLoadingOptions instead */
1424
schemaLoading?: SchemaLoadingOptions;
15-
intercept?: RegExp;
16-
injectValidationFunction?: boolean;
1725
}
1826

19-
export default class AppConfigPlugin {
27+
export default class AppConfigPlugin implements Options {
2028
headerInjection: boolean;
21-
noGlobal: boolean;
29+
useGlobalNamespace: boolean;
2230
loadingOptions?: ConfigLoadingOptions;
2331
schemaLoadingOptions?: SchemaLoadingOptions;
32+
injectValidationFunction: boolean;
2433
intercept: RegExp;
2534

26-
constructor({
27-
headerInjection = false,
28-
noGlobal = false,
29-
loading,
30-
schemaLoading,
31-
intercept,
32-
}: Options = {}) {
33-
this.headerInjection = headerInjection;
34-
this.noGlobal = noGlobal;
35-
this.loadingOptions = loading;
36-
this.schemaLoadingOptions = schemaLoading;
37-
this.intercept = intercept ?? AppConfigPlugin.regex;
35+
constructor(options: Options = {}) {
36+
this.headerInjection = options.headerInjection ?? false;
37+
this.useGlobalNamespace = options.useGlobalNamespace ?? !options.noGlobal;
38+
this.loadingOptions = options.loadingOptions ?? options.loading;
39+
this.schemaLoadingOptions = options.schemaLoadingOptions ?? options.schemaLoading;
40+
this.injectValidationFunction = options.injectValidationFunction ?? true;
41+
this.intercept = options.intercept ?? AppConfigPlugin.regex;
3842
}
3943

4044
static loader = loader;
@@ -57,9 +61,16 @@ export default class AppConfigPlugin {
5761

5862
if (this.intercept.test(resolve.request)) {
5963
const queryString = JSON.stringify({
64+
headerInjection: this.headerInjection,
65+
useGlobalNamespace: this.useGlobalNamespace,
66+
loadingOptions: this.loadingOptions,
67+
schemaLoadingOptions: this.schemaLoadingOptions,
68+
injectValidationFunction: this.injectValidationFunction,
69+
70+
// deprecated options
71+
noGlobal: !this.useGlobalNamespace,
6072
loading: this.loadingOptions,
6173
schemaLoading: this.schemaLoadingOptions,
62-
noGlobal: this.noGlobal,
6374
});
6475

6576
// eslint-disable-next-line no-param-reassign

app-config-webpack/src/loader.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { getOptions, parseQuery } from 'loader-utils';
2-
import { loadValidatedConfig } from '@app-config/main';
3-
import { currentEnvironment, asEnvOptions } from '@app-config/node';
2+
import { loadValidatedConfig } from '@app-config/config';
43
import { generateModuleText, packageNameRegex } from '@app-config/utils';
54
import type { Options } from './index';
65

@@ -11,33 +10,29 @@ const loader = function AppConfigLoader(this: Loader) {
1110
if (this.cacheable) this.cacheable();
1211

1312
const callback = this.async()!;
14-
const {
15-
noGlobal = false,
16-
loading = {},
17-
schemaLoading,
18-
injectValidationFunction = true,
19-
}: Options = {
13+
const options: Options = {
2014
...getOptions(this),
2115
...parseQuery(this.resourceQuery),
2216
};
2317

24-
loadValidatedConfig(loading, schemaLoading)
25-
.then(({ fullConfig, filePaths, validationFunctionCode }) => {
18+
const useGlobalNamespace = options.useGlobalNamespace ?? !options.noGlobal;
19+
const loadingOptions = options.loadingOptions ?? options.loading ?? {};
20+
const schemaLoadingOptions = options.schemaLoadingOptions ?? options.schemaLoading;
21+
const injectValidationFunction = options.injectValidationFunction ?? true;
22+
23+
loadValidatedConfig(loadingOptions, schemaLoadingOptions)
24+
.then(({ fullConfig, environment, filePaths, validationFunctionCode }) => {
2625
if (filePaths) {
2726
filePaths.forEach((filePath) => this.addDependency(filePath));
2827
}
2928

30-
const { environmentOverride, environmentAliases, environmentSourceNames } = loading;
31-
3229
callback(
3330
null,
3431
generateModuleText(fullConfig, {
35-
esm: false,
36-
noGlobal,
37-
currentEnvironment: currentEnvironment(
38-
asEnvOptions(environmentOverride, environmentAliases, environmentSourceNames),
39-
),
32+
environment,
33+
useGlobalNamespace,
4034
validationFunctionCode: injectValidationFunction ? validationFunctionCode : undefined,
35+
esmValidationCode: false,
4136
}),
4237
);
4338
})

app-config-webpack/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
"exclude": ["node_modules"],
99
"references": [
1010
{ "path": "../app-config-utils" },
11-
{ "path": "../app-config-main" }
11+
{ "path": "../app-config-config" }
1212
]
1313
}

0 commit comments

Comments
 (0)