wgc 0.117.2 → 0.118.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/dist/package.json +1 -1
- package/dist/src/commands/feature-flag/commands/recompose.d.ts +4 -0
- package/dist/src/commands/feature-flag/commands/recompose.js +85 -0
- package/dist/src/commands/feature-flag/commands/recompose.js.map +1 -0
- package/dist/src/commands/feature-flag/index.js +2 -0
- package/dist/src/commands/feature-flag/index.js.map +1 -1
- package/dist/test/feature-flag/recompose.test.d.ts +1 -0
- package/dist/test/feature-flag/recompose.test.js +113 -0
- package/dist/test/feature-flag/recompose.test.js.map +1 -0
- package/dist/test/feature-flag/utils.d.ts +12 -0
- package/dist/test/feature-flag/utils.js +35 -0
- package/dist/test/feature-flag/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
package/dist/package.json
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
|
|
2
|
+
import { Command, program } from 'commander';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { getBaseHeaders } from '../../../core/config.js';
|
|
6
|
+
import { handleCompositionResult } from '../../../handle-composition-result.js';
|
|
7
|
+
import { limitMaxValue } from '../../../constants.js';
|
|
8
|
+
export default (opts) => {
|
|
9
|
+
const command = new Command('recompose');
|
|
10
|
+
command.description('Triggers a recomposition of the specified feature flags using its current subgraphs.');
|
|
11
|
+
command.argument('<name>', 'The name of the feature flag to recompose.');
|
|
12
|
+
command.option('-n, --namespace [string]', 'The namespace of the feature flag.');
|
|
13
|
+
command.option('--suppress-warnings', 'This flag suppresses any warning produced by composition.');
|
|
14
|
+
command.option('--disable-resolvability-validation', 'This flag will disable the validation for whether all nodes of the feature flag are resolvable. Do NOT use unless troubleshooting.');
|
|
15
|
+
command.option('--fail-on-composition-error', 'If set, the command will fail if the composition of the feature flag fails.', false);
|
|
16
|
+
command.option('--fail-on-admission-webhook-error', 'If set, the command will fail if the admission webhook fails.', false);
|
|
17
|
+
command.option('-l, --limit <number>', 'The maximum number of composition errors, warnings, and deployment errors to display.', '50');
|
|
18
|
+
command.action(async (name, options) => {
|
|
19
|
+
const limit = Number(options.limit);
|
|
20
|
+
if (!Number.isInteger(limit) || limit <= 0 || limit > limitMaxValue) {
|
|
21
|
+
program.error(pc.red(`The limit must be a valid number between 1 and ${limitMaxValue}. Received: '${options.limit}'`));
|
|
22
|
+
}
|
|
23
|
+
const spinner = ora(`Recomposing feature flag "${name}"...`).start();
|
|
24
|
+
const resp = await opts.client.platform.recomposeFeatureFlag({
|
|
25
|
+
disableResolvabilityValidation: options.disableResolvabilityValidation,
|
|
26
|
+
limit,
|
|
27
|
+
name,
|
|
28
|
+
namespace: options.namespace,
|
|
29
|
+
}, {
|
|
30
|
+
headers: getBaseHeaders(),
|
|
31
|
+
});
|
|
32
|
+
if (!resp.response) {
|
|
33
|
+
spinner.fail(`Failed to recompose feature flag "${pc.bold(name)}".`);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
switch (resp.response.code) {
|
|
38
|
+
case EnumStatusCode.ERR: {
|
|
39
|
+
spinner.fail(`Failed to recompose feature flag "${pc.bold(name)}".`);
|
|
40
|
+
let message = `${pc.red('Split configuration loading is not enabled on the organization.')}`;
|
|
41
|
+
if (resp.response.details) {
|
|
42
|
+
message += `\n${pc.red(pc.bold(resp.response.details))}`;
|
|
43
|
+
}
|
|
44
|
+
program.error(message);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case EnumStatusCode.ERR_NOT_FOUND: {
|
|
48
|
+
spinner.fail(`Failed to recompose feature flag "${pc.bold(name)}".`);
|
|
49
|
+
let message = `${pc.red(`No valid record could be found for feature flag "${pc.bold(name)}".`)}\n` +
|
|
50
|
+
`Please check the name and namespace for the feature flag in Cosmo Studio.`;
|
|
51
|
+
if (resp.response.details) {
|
|
52
|
+
message += `\n${pc.red(pc.bold(resp.response.details))}`;
|
|
53
|
+
}
|
|
54
|
+
program.error(message);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
handleCompositionResult({
|
|
60
|
+
totalErrorCounts: resp.errorCounts,
|
|
61
|
+
responseCode: resp.response.code,
|
|
62
|
+
responseDetails: resp.response.details,
|
|
63
|
+
compositionErrors: resp.compositionErrors,
|
|
64
|
+
compositionWarnings: resp.compositionWarnings,
|
|
65
|
+
deploymentErrors: resp.deploymentErrors,
|
|
66
|
+
spinner,
|
|
67
|
+
successMessage: `Feature flag "${pc.bold(name)}" recomposed successfully.`,
|
|
68
|
+
subgraphCompositionBaseErrorMessage: `Recomposition of feature flag "${pc.bold(name)}" failed.`,
|
|
69
|
+
subgraphCompositionDetailedErrorMessage: pc.bold('Please check the errors below:'),
|
|
70
|
+
deploymentErrorMessage: `Feature flag was recomposed but the updated composition could not be deployed.` +
|
|
71
|
+
`\nThis means the updated composition is not accessible to the router.` +
|
|
72
|
+
`\n${pc.bold('Please check the errors below:')}`,
|
|
73
|
+
defaultErrorMessage: `Failed to recompose feature flag "${pc.bold(name)}".`,
|
|
74
|
+
suppressWarnings: options.suppressWarnings,
|
|
75
|
+
failOnCompositionError: options.failOnCompositionError,
|
|
76
|
+
failOnAdmissionWebhookError: options.failOnAdmissionWebhookError,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return command;
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=recompose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recompose.js","sourceRoot":"","sources":["../../../../../src/commands/feature-flag/commands/recompose.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import EnableFeatureFlagCommand from './commands/enable.js';
|
|
|
6
6
|
import DisableFeatureFlagCommand from './commands/disable.js';
|
|
7
7
|
import UpdateFeatureFlagCommand from './commands/update.js';
|
|
8
8
|
import ListFeatureFlagCommand from './commands/list.js';
|
|
9
|
+
import RecomposeFeatureFlagCommand from './commands/recompose.js';
|
|
9
10
|
export default (opts) => {
|
|
10
11
|
const command = new Command('feature-flag').alias('ff');
|
|
11
12
|
command.description('Provides commands for creating and managing feature flags.');
|
|
@@ -15,6 +16,7 @@ export default (opts) => {
|
|
|
15
16
|
command.addCommand(DisableFeatureFlagCommand(opts));
|
|
16
17
|
command.addCommand(UpdateFeatureFlagCommand(opts));
|
|
17
18
|
command.addCommand(ListFeatureFlagCommand(opts));
|
|
19
|
+
command.addCommand(RecomposeFeatureFlagCommand(opts));
|
|
18
20
|
command.hook('preAction', async () => {
|
|
19
21
|
await checkAuth();
|
|
20
22
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/feature-flag/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,yBAAyB,MAAM,uBAAuB,CAAC;AAC9D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,sBAAsB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/feature-flag/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,yBAAyB,MAAM,uBAAuB,CAAC;AAC9D,OAAO,wBAAwB,MAAM,sBAAsB,CAAC;AAC5D,OAAO,sBAAsB,MAAM,oBAAoB,CAAC;AACxD,OAAO,2BAA2B,MAAM,yBAAyB,CAAC;AAElE,eAAe,CAAC,IAAwB,EAAE,EAAE;IAC1C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,WAAW,CAAC,4DAA4D,CAAC,CAAC;IAElF,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,UAAU,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,UAAU,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,UAAU,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
|
|
3
|
+
import { runRecompose } from './utils.js';
|
|
4
|
+
describe('feature-flag recompose', () => {
|
|
5
|
+
let logSpy;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
8
|
+
vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
9
|
+
vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
10
|
+
throw new Error('process.exit');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
process.exitCode = undefined;
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
});
|
|
17
|
+
test('that recompose is successful with default namespace', async () => {
|
|
18
|
+
await runRecompose({
|
|
19
|
+
response: { code: EnumStatusCode.OK },
|
|
20
|
+
compositionErrors: [],
|
|
21
|
+
compositionWarnings: [],
|
|
22
|
+
deploymentErrors: [],
|
|
23
|
+
});
|
|
24
|
+
expect(process.exitCode).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
test('that recompose is successful with specific namespace', async () => {
|
|
27
|
+
await runRecompose({
|
|
28
|
+
response: { code: EnumStatusCode.OK },
|
|
29
|
+
compositionErrors: [],
|
|
30
|
+
compositionWarnings: [],
|
|
31
|
+
deploymentErrors: [],
|
|
32
|
+
}, { namespace: 'production' });
|
|
33
|
+
expect(process.exitCode).toBeUndefined();
|
|
34
|
+
});
|
|
35
|
+
test('that recompose fails with exit code 1 if response is missing', async () => {
|
|
36
|
+
await runRecompose({});
|
|
37
|
+
expect(process.exitCode).toBe(1);
|
|
38
|
+
});
|
|
39
|
+
test('that recompose fails fails with exit code 1 if config splitting is not enabled', async () => {
|
|
40
|
+
await expect(runRecompose({
|
|
41
|
+
response: { code: EnumStatusCode.ERR, details: 'Configuration splitting not enabled' },
|
|
42
|
+
compositionErrors: [],
|
|
43
|
+
compositionWarnings: [],
|
|
44
|
+
deploymentErrors: [],
|
|
45
|
+
})).rejects.toThrow();
|
|
46
|
+
expect(process.exitCode).toBeUndefined();
|
|
47
|
+
});
|
|
48
|
+
test('that recompose fails but does not return exit code 1 if the feature flag is not found', async () => {
|
|
49
|
+
await expect(runRecompose({
|
|
50
|
+
response: { code: EnumStatusCode.ERR_NOT_FOUND, details: 'The feature flag "feature-flag" was not found' },
|
|
51
|
+
compositionErrors: [],
|
|
52
|
+
compositionWarnings: [],
|
|
53
|
+
deploymentErrors: [],
|
|
54
|
+
})).rejects.toThrow();
|
|
55
|
+
expect(process.exitCode).toBeUndefined();
|
|
56
|
+
});
|
|
57
|
+
test('that recompose fails if composition errors occur but does not return exit code 1', async () => {
|
|
58
|
+
await runRecompose({
|
|
59
|
+
response: { code: EnumStatusCode.ERR_SUBGRAPH_COMPOSITION_FAILED },
|
|
60
|
+
compositionErrors: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Composition failed' }],
|
|
61
|
+
compositionWarnings: [],
|
|
62
|
+
deploymentErrors: [],
|
|
63
|
+
});
|
|
64
|
+
expect(process.exitCode).toBeUndefined();
|
|
65
|
+
});
|
|
66
|
+
test('that recompose fails if composition errors occur and returns exit code 1 if --fail-on-composition-error is set', async () => {
|
|
67
|
+
await runRecompose({
|
|
68
|
+
response: { code: EnumStatusCode.ERR_SUBGRAPH_COMPOSITION_FAILED },
|
|
69
|
+
compositionErrors: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Composition failed' }],
|
|
70
|
+
compositionWarnings: [],
|
|
71
|
+
deploymentErrors: [],
|
|
72
|
+
}, { failOnCompositionError: true });
|
|
73
|
+
expect(process.exitCode).toBe(1);
|
|
74
|
+
});
|
|
75
|
+
test('that recompose fails if deployment errors occur but does not return exit code 1', async () => {
|
|
76
|
+
await runRecompose({
|
|
77
|
+
response: { code: EnumStatusCode.ERR_DEPLOYMENT_FAILED },
|
|
78
|
+
compositionErrors: [],
|
|
79
|
+
compositionWarnings: [],
|
|
80
|
+
deploymentErrors: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Deploy failed' }],
|
|
81
|
+
});
|
|
82
|
+
expect(process.exitCode).toBeUndefined();
|
|
83
|
+
});
|
|
84
|
+
test('that recompose fails if deployment errors occur and returns exit code 1 if --fail-on-admission-webhook-error is set', async () => {
|
|
85
|
+
await runRecompose({
|
|
86
|
+
response: { code: EnumStatusCode.ERR_DEPLOYMENT_FAILED },
|
|
87
|
+
compositionErrors: [],
|
|
88
|
+
compositionWarnings: [],
|
|
89
|
+
deploymentErrors: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Deploy failed' }],
|
|
90
|
+
}, { failOnAdmissionWebhookError: true });
|
|
91
|
+
expect(process.exitCode).toBe(1);
|
|
92
|
+
});
|
|
93
|
+
test('that composition warnings are shown by default', async () => {
|
|
94
|
+
await runRecompose({
|
|
95
|
+
response: { code: EnumStatusCode.OK },
|
|
96
|
+
compositionErrors: [],
|
|
97
|
+
compositionWarnings: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Some warning' }],
|
|
98
|
+
deploymentErrors: [],
|
|
99
|
+
});
|
|
100
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('warnings were produced'));
|
|
101
|
+
});
|
|
102
|
+
test('suppresses composition warnings when --suppress-warnings is set', async () => {
|
|
103
|
+
await runRecompose({
|
|
104
|
+
response: { code: EnumStatusCode.OK },
|
|
105
|
+
compositionErrors: [],
|
|
106
|
+
compositionWarnings: [{ federatedGraphName: 'mygraph', namespace: 'default', message: 'Some warning' }],
|
|
107
|
+
deploymentErrors: [],
|
|
108
|
+
}, { suppressWarnings: true });
|
|
109
|
+
const warningCalls = logSpy.mock.calls.filter(([arg]) => typeof arg === 'string' && arg.includes('warnings were produced'));
|
|
110
|
+
expect(warningCalls).toHaveLength(0);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=recompose.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recompose.test.js","sourceRoot":"","sources":["../../../test/feature-flag/recompose.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAqB,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAI,MAAwC,CAAC;IAE7C,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/D,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACjE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAChD,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC7B,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,YAAY,CAAC;YACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;YACrC,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,YAAY,CAChB;YACE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;YACrC,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,EACD,EAAE,SAAS,EAAE,YAAY,EAAE,CAC5B,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;QAEvB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,MAAM,CACV,YAAY,CAAC;YACX,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,qCAAqC,EAAE;YACtF,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAEpB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,MAAM,CACV,YAAY,CAAC;YACX,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,aAAa,EAAE,OAAO,EAAE,+CAA+C,EAAE;YAC1G,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAEpB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,YAAY,CAAC;YACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,+BAA+B,EAAE;YAClE,iBAAiB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;YAC3G,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gHAAgH,EAAE,KAAK,IAAI,EAAE;QAChI,MAAM,YAAY,CAChB;YACE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,+BAA+B,EAAE;YAClE,iBAAiB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;YAC3G,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,EAAE;SACrB,EACD,EAAE,sBAAsB,EAAE,IAAI,EAAE,CACjC,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QACjG,MAAM,YAAY,CAAC;YACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,qBAAqB,EAAE;YACxD,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;SACtG,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qHAAqH,EAAE,KAAK,IAAI,EAAE;QACrI,MAAM,YAAY,CAChB;YACE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,qBAAqB,EAAE;YACxD,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,EAAE;YACvB,gBAAgB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;SACtG,EACD,EAAE,2BAA2B,EAAE,IAAI,EAAE,CACtC,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,YAAY,CAAC;YACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;YACrC,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;YACvG,gBAAgB,EAAE,EAAE;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,YAAY,CAChB;YACE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;YACrC,iBAAiB,EAAE,EAAE;YACrB,mBAAmB,EAAE,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;YACvG,gBAAgB,EAAE,EAAE;SACrB,EACD,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAC3B,CAAC;QAEF,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAC3C,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAC7E,CAAC;QACF,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PartialMessage } from '@bufbuild/protobuf';
|
|
2
|
+
import { RecomposeFeatureFlagResponse } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
|
|
3
|
+
import { Transport } from '@connectrpc/connect';
|
|
4
|
+
import { Client } from '../../src/core/client/client.js';
|
|
5
|
+
export declare function createMockTransport(response: PartialMessage<RecomposeFeatureFlagResponse>): Transport;
|
|
6
|
+
export declare function createClient(response: PartialMessage<RecomposeFeatureFlagResponse>): Client;
|
|
7
|
+
export declare function runRecompose(response: PartialMessage<RecomposeFeatureFlagResponse>, opts?: {
|
|
8
|
+
namespace?: string;
|
|
9
|
+
failOnCompositionError?: boolean;
|
|
10
|
+
failOnAdmissionWebhookError?: boolean;
|
|
11
|
+
suppressWarnings?: boolean;
|
|
12
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createPromiseClient, createRouterTransport } from '@connectrpc/connect';
|
|
2
|
+
import { PlatformService } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_connect';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import RecomposeCommand from '../../src/commands/feature-flag/commands/recompose.js';
|
|
5
|
+
export function createMockTransport(response) {
|
|
6
|
+
return createRouterTransport(({ service }) => {
|
|
7
|
+
service(PlatformService, {
|
|
8
|
+
recomposeFeatureFlag: () => response,
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export function createClient(response) {
|
|
13
|
+
return {
|
|
14
|
+
platform: createPromiseClient(PlatformService, createMockTransport(response)),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function runRecompose(response, opts = {}) {
|
|
18
|
+
const args = ['recompose', 'feature-flag'];
|
|
19
|
+
if (opts.namespace) {
|
|
20
|
+
args.push('--namespace', opts.namespace);
|
|
21
|
+
}
|
|
22
|
+
if (opts.failOnCompositionError) {
|
|
23
|
+
args.push('--fail-on-composition-error');
|
|
24
|
+
}
|
|
25
|
+
if (opts.failOnAdmissionWebhookError) {
|
|
26
|
+
args.push('--fail-on-admission-webhook-error');
|
|
27
|
+
}
|
|
28
|
+
if (opts.suppressWarnings) {
|
|
29
|
+
args.push('--suppress-warnings');
|
|
30
|
+
}
|
|
31
|
+
const program = new Command();
|
|
32
|
+
program.addCommand(RecomposeCommand({ client: createClient(response) }));
|
|
33
|
+
await program.parseAsync(args, { from: 'user' });
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../test/feature-flag/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAa,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAC;AAC/F,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,gBAAgB,MAAM,uDAAuD,CAAC;AAGrF,MAAM,UAAU,mBAAmB,CAAC,QAAsD;IACxF,OAAO,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,EAAQ,EAAE;QACjD,OAAO,CAAC,eAAe,EAAE;YACvB,oBAAoB,EAAE,GAAG,EAAE,CAAC,QAAQ;SACrC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAsD;IACjF,OAAO;QACL,QAAQ,EAAE,mBAAmB,CAAC,eAAe,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;KAC9E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAsD,EACtD,OAKI,EAAE;IAEN,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,CAAC,2BAA2B,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC"}
|