wgc 0.116.0 → 0.117.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 +1 -1
- package/dist/package.json +1 -1
- package/dist/src/commands/demo/api.d.ts +78 -0
- package/dist/src/commands/demo/api.js +152 -0
- package/dist/src/commands/demo/api.js.map +1 -0
- package/dist/src/commands/demo/command.d.ts +2 -0
- package/dist/src/commands/demo/command.js +425 -0
- package/dist/src/commands/demo/command.js.map +1 -0
- package/dist/src/commands/demo/index.d.ts +4 -0
- package/dist/src/commands/demo/index.js +13 -0
- package/dist/src/commands/demo/index.js.map +1 -0
- package/dist/src/commands/demo/types.d.ts +2 -0
- package/dist/src/commands/demo/types.js +2 -0
- package/dist/src/commands/demo/types.js.map +1 -0
- package/dist/src/commands/demo/util.d.ts +77 -0
- package/dist/src/commands/demo/util.js +482 -0
- package/dist/src/commands/demo/util.js.map +1 -0
- package/dist/src/commands/index.js +4 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/router/commands/plugin/commands/publish.js +37 -157
- package/dist/src/commands/router/commands/plugin/commands/publish.js.map +1 -1
- package/dist/src/commands/router/commands/token/commands/create.js +17 -23
- package/dist/src/commands/router/commands/token/commands/create.js.map +1 -1
- package/dist/src/commands/router/commands/token/commands/delete.js +8 -14
- package/dist/src/commands/router/commands/token/commands/delete.js.map +1 -1
- package/dist/src/core/config.d.ts +14 -0
- package/dist/src/core/config.js +14 -0
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/plugin-publish.d.ts +65 -0
- package/dist/src/core/plugin-publish.js +192 -0
- package/dist/src/core/plugin-publish.js.map +1 -0
- package/dist/src/core/router-token.d.ts +30 -0
- package/dist/src/core/router-token.js +45 -0
- package/dist/src/core/router-token.js.map +1 -0
- package/dist/src/utils.d.ts +20 -0
- package/dist/src/utils.js +99 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/test/demo/command.test.d.ts +1 -0
- package/dist/test/demo/command.test.js +396 -0
- package/dist/test/demo/command.test.js.map +1 -0
- package/dist/test/demo/util.test.d.ts +1 -0
- package/dist/test/demo/util.test.js +310 -0
- package/dist/test/demo/util.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
package/dist/package.json
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { FederatedGraph, Subgraph } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
|
|
2
|
+
import type { BaseCommandOptions } from '../../core/types/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Retrieve user information [email] and [organization name]
|
|
5
|
+
*/
|
|
6
|
+
export declare function fetchUserInfo(client: BaseCommandOptions['client']): Promise<{
|
|
7
|
+
userInfo: import("@wundergraph/cosmo-connect/dist/platform/v1/platform_pb").WhoAmIResponse;
|
|
8
|
+
error: null;
|
|
9
|
+
} | {
|
|
10
|
+
userInfo: null;
|
|
11
|
+
error: Error;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Retrieve onboarding record. Provides information about allowed [status]:
|
|
15
|
+
* [error] | [not-allowed] | [ok]
|
|
16
|
+
* If record exists, returns [onboarding] metadata.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkExistingOnboarding(client: BaseCommandOptions['client']): Promise<{
|
|
19
|
+
readonly error: Error;
|
|
20
|
+
readonly status: "error";
|
|
21
|
+
readonly onboarding?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
readonly status: "not-allowed";
|
|
24
|
+
readonly error?: undefined;
|
|
25
|
+
readonly onboarding?: undefined;
|
|
26
|
+
} | {
|
|
27
|
+
readonly onboarding: {
|
|
28
|
+
readonly finishedAt: string | undefined;
|
|
29
|
+
};
|
|
30
|
+
readonly status: "ok";
|
|
31
|
+
readonly error?: undefined;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves federated graph by [name] *demo*. Missing federated graph
|
|
35
|
+
* is a valid state.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fetchFederatedGraphByName(client: BaseCommandOptions['client'], { name, namespace }: {
|
|
38
|
+
name: string;
|
|
39
|
+
namespace: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
data: {
|
|
42
|
+
graph: FederatedGraph | undefined;
|
|
43
|
+
subgraphs: Subgraph[];
|
|
44
|
+
};
|
|
45
|
+
error: null;
|
|
46
|
+
} | {
|
|
47
|
+
data: null;
|
|
48
|
+
error: null;
|
|
49
|
+
} | {
|
|
50
|
+
data: null;
|
|
51
|
+
error: Error;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Cleans up the federated graph by [name] _demo_ and its related
|
|
55
|
+
* subgraphs.
|
|
56
|
+
*/
|
|
57
|
+
export declare function cleanUpFederatedGraph(client: BaseCommandOptions['client'], graphData: {
|
|
58
|
+
graph: FederatedGraph;
|
|
59
|
+
subgraphs: Subgraph[];
|
|
60
|
+
}): Promise<{
|
|
61
|
+
error: Error;
|
|
62
|
+
} | {
|
|
63
|
+
error: null;
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Creates federated graph using default [name] and [namespace], with pre-defined
|
|
67
|
+
* [labelMatcher] which identify the graph as _demo_.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createFederatedGraph(client: BaseCommandOptions['client'], options: {
|
|
70
|
+
name: string;
|
|
71
|
+
namespace: string;
|
|
72
|
+
labelMatcher: string;
|
|
73
|
+
routingUrl: URL;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
error: null;
|
|
76
|
+
} | {
|
|
77
|
+
error: Error;
|
|
78
|
+
}>;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
|
|
2
|
+
import { getBaseHeaders } from '../../core/config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Retrieve user information [email] and [organization name]
|
|
5
|
+
*/
|
|
6
|
+
export async function fetchUserInfo(client) {
|
|
7
|
+
var _a, _b, _c;
|
|
8
|
+
try {
|
|
9
|
+
const response = await client.platform.whoAmI({}, {
|
|
10
|
+
headers: getBaseHeaders(),
|
|
11
|
+
});
|
|
12
|
+
switch ((_a = response.response) === null || _a === void 0 ? void 0 : _a.code) {
|
|
13
|
+
case EnumStatusCode.OK: {
|
|
14
|
+
return {
|
|
15
|
+
userInfo: response,
|
|
16
|
+
error: null,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
default: {
|
|
20
|
+
return {
|
|
21
|
+
userInfo: null,
|
|
22
|
+
error: new Error((_c = (_b = response.response) === null || _b === void 0 ? void 0 : _b.details) !== null && _c !== void 0 ? _c : 'An unknown error occurred.'),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return {
|
|
29
|
+
userInfo: null,
|
|
30
|
+
error: err instanceof Error ? err : new Error('An unknown error occurred.'),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Retrieve onboarding record. Provides information about allowed [status]:
|
|
36
|
+
* [error] | [not-allowed] | [ok]
|
|
37
|
+
* If record exists, returns [onboarding] metadata.
|
|
38
|
+
*/
|
|
39
|
+
export async function checkExistingOnboarding(client) {
|
|
40
|
+
var _a;
|
|
41
|
+
const { response, finishedAt, enabled } = await client.platform.getOnboarding({}, {
|
|
42
|
+
headers: getBaseHeaders(),
|
|
43
|
+
});
|
|
44
|
+
if ((response === null || response === void 0 ? void 0 : response.code) !== EnumStatusCode.OK) {
|
|
45
|
+
return {
|
|
46
|
+
error: new Error((_a = response === null || response === void 0 ? void 0 : response.details) !== null && _a !== void 0 ? _a : 'Failed to fetch onboarding metadata.'),
|
|
47
|
+
status: 'error',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (!enabled) {
|
|
51
|
+
return {
|
|
52
|
+
status: 'not-allowed',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
onboarding: {
|
|
57
|
+
finishedAt,
|
|
58
|
+
},
|
|
59
|
+
status: 'ok',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Retrieves federated graph by [name] *demo*. Missing federated graph
|
|
64
|
+
* is a valid state.
|
|
65
|
+
*/
|
|
66
|
+
export async function fetchFederatedGraphByName(client, { name, namespace }) {
|
|
67
|
+
var _a;
|
|
68
|
+
const { response, graph, subgraphs } = await client.platform.getFederatedGraphByName({
|
|
69
|
+
name,
|
|
70
|
+
namespace,
|
|
71
|
+
}, {
|
|
72
|
+
headers: getBaseHeaders(),
|
|
73
|
+
});
|
|
74
|
+
switch (response === null || response === void 0 ? void 0 : response.code) {
|
|
75
|
+
case EnumStatusCode.OK: {
|
|
76
|
+
return { data: { graph, subgraphs }, error: null };
|
|
77
|
+
}
|
|
78
|
+
case EnumStatusCode.ERR_NOT_FOUND: {
|
|
79
|
+
return { data: null, error: null };
|
|
80
|
+
}
|
|
81
|
+
default: {
|
|
82
|
+
return {
|
|
83
|
+
data: null,
|
|
84
|
+
error: new Error((_a = response === null || response === void 0 ? void 0 : response.details) !== null && _a !== void 0 ? _a : 'An unknown error occured'),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Cleans up the federated graph by [name] _demo_ and its related
|
|
91
|
+
* subgraphs.
|
|
92
|
+
*/
|
|
93
|
+
export async function cleanUpFederatedGraph(client, graphData) {
|
|
94
|
+
var _a, _b, _c;
|
|
95
|
+
const subgraphDeleteResponses = await Promise.all(graphData.subgraphs.map(({ name, namespace }) => client.platform.deleteFederatedSubgraph({
|
|
96
|
+
namespace,
|
|
97
|
+
subgraphName: name,
|
|
98
|
+
disableResolvabilityValidation: false,
|
|
99
|
+
}, {
|
|
100
|
+
headers: getBaseHeaders(),
|
|
101
|
+
})));
|
|
102
|
+
const failedSubgraphDeleteResponses = subgraphDeleteResponses.filter(({ response }) => (response === null || response === void 0 ? void 0 : response.code) !== EnumStatusCode.OK);
|
|
103
|
+
if (failedSubgraphDeleteResponses.length > 0) {
|
|
104
|
+
return {
|
|
105
|
+
error: new Error(failedSubgraphDeleteResponses.map(({ response }) => { var _a; return (_a = response === null || response === void 0 ? void 0 : response.details) !== null && _a !== void 0 ? _a : 'Unknown error occurred.'; }).join('. ')),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const federatedGraphDeleteResponse = await client.platform.deleteFederatedGraph({
|
|
109
|
+
name: graphData.graph.name,
|
|
110
|
+
namespace: graphData.graph.namespace,
|
|
111
|
+
}, {
|
|
112
|
+
headers: getBaseHeaders(),
|
|
113
|
+
});
|
|
114
|
+
switch ((_a = federatedGraphDeleteResponse.response) === null || _a === void 0 ? void 0 : _a.code) {
|
|
115
|
+
case EnumStatusCode.OK: {
|
|
116
|
+
return {
|
|
117
|
+
error: null,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
default: {
|
|
121
|
+
return {
|
|
122
|
+
error: new Error((_c = (_b = federatedGraphDeleteResponse.response) === null || _b === void 0 ? void 0 : _b.details) !== null && _c !== void 0 ? _c : 'Unknown error occurred.'),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Creates federated graph using default [name] and [namespace], with pre-defined
|
|
129
|
+
* [labelMatcher] which identify the graph as _demo_.
|
|
130
|
+
*/
|
|
131
|
+
export async function createFederatedGraph(client, options) {
|
|
132
|
+
var _a, _b, _c;
|
|
133
|
+
const createFedGraphResponse = await client.platform.createFederatedGraph({
|
|
134
|
+
name: options.name,
|
|
135
|
+
namespace: options.namespace,
|
|
136
|
+
routingUrl: options.routingUrl.toString(),
|
|
137
|
+
labelMatchers: [options.labelMatcher],
|
|
138
|
+
}, {
|
|
139
|
+
headers: getBaseHeaders(),
|
|
140
|
+
});
|
|
141
|
+
switch ((_a = createFedGraphResponse.response) === null || _a === void 0 ? void 0 : _a.code) {
|
|
142
|
+
case EnumStatusCode.OK: {
|
|
143
|
+
return { error: null };
|
|
144
|
+
}
|
|
145
|
+
default: {
|
|
146
|
+
return {
|
|
147
|
+
error: new Error((_c = (_b = createFedGraphResponse.response) === null || _b === void 0 ? void 0 : _b.details) !== null && _c !== void 0 ? _c : 'An unknown error occured'),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/commands/demo/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import open from 'open';
|
|
4
|
+
import { config } from '../../core/config.js';
|
|
5
|
+
import { createRouterToken, deleteRouterToken } from '../../core/router-token.js';
|
|
6
|
+
import { waitForKeyPress, rainbow } from '../../utils.js';
|
|
7
|
+
import { cleanUpFederatedGraph, createFederatedGraph, fetchFederatedGraphByName, fetchUserInfo, checkExistingOnboarding, } from './api.js';
|
|
8
|
+
import { captureOnboardingEvent, checkDockerReadiness, clearScreen, getDemoLogPath, prepareSupportingData, printLogo, publishAllPlugins, resetScreen, runRouterContainer, updateScreenWithUserInfo, demoSpinner, } from './util.js';
|
|
9
|
+
function printHello() {
|
|
10
|
+
printLogo();
|
|
11
|
+
console.log(`\nThank you for choosing ${rainbow('WunderGraph')} - The open-source solution to building, maintaining, and collaborating on GraphQL Federation at Scale.`);
|
|
12
|
+
console.log('This command will guide you through the inital setup to create your first federated graph.');
|
|
13
|
+
}
|
|
14
|
+
async function handleGetFederatedGraphResponse(client, { onboarding, userInfo, }) {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
function retryFn() {
|
|
17
|
+
resetScreen(userInfo);
|
|
18
|
+
return handleGetFederatedGraphResponse(client, {
|
|
19
|
+
onboarding,
|
|
20
|
+
userInfo,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const spinner = demoSpinner().start();
|
|
24
|
+
const getFederatedGraphResponse = await fetchFederatedGraphByName(client, {
|
|
25
|
+
name: config.demoGraphName,
|
|
26
|
+
namespace: config.demoNamespace,
|
|
27
|
+
});
|
|
28
|
+
if (getFederatedGraphResponse.error) {
|
|
29
|
+
spinner.fail(`Failed to retrieve graph information ${getFederatedGraphResponse.error}`);
|
|
30
|
+
return await waitForKeyPress({
|
|
31
|
+
r: retryFn,
|
|
32
|
+
R: retryFn,
|
|
33
|
+
}, 'Hit [r] to refresh. CTRL+C to quit');
|
|
34
|
+
}
|
|
35
|
+
if ((_a = getFederatedGraphResponse.data) === null || _a === void 0 ? void 0 : _a.graph) {
|
|
36
|
+
spinner.succeed(`Federated graph ${pc.bold((_c = (_b = getFederatedGraphResponse.data) === null || _b === void 0 ? void 0 : _b.graph) === null || _c === void 0 ? void 0 : _c.name)} exists.`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
spinner.stop();
|
|
40
|
+
}
|
|
41
|
+
return getFederatedGraphResponse.data;
|
|
42
|
+
}
|
|
43
|
+
async function cleanupFederatedGraph(client, { graphData, userInfo, }) {
|
|
44
|
+
let deleted = false;
|
|
45
|
+
function retryFn() {
|
|
46
|
+
resetScreen(userInfo);
|
|
47
|
+
cleanupFederatedGraph(client, { graphData, userInfo });
|
|
48
|
+
}
|
|
49
|
+
const spinner = demoSpinner(`Removing federated graph ${pc.bold(graphData.graph.name)}…`).start();
|
|
50
|
+
const deleteResponse = await cleanUpFederatedGraph(client, graphData);
|
|
51
|
+
if (deleteResponse.error) {
|
|
52
|
+
deleted = false;
|
|
53
|
+
const failText = `Removing federated graph ${graphData.graph.name} failed.`;
|
|
54
|
+
spinner.fail(failText);
|
|
55
|
+
captureOnboardingEvent({
|
|
56
|
+
name: 'onboarding_step_failed',
|
|
57
|
+
properties: {
|
|
58
|
+
step_name: 'delete_federated_graph',
|
|
59
|
+
entry_source: 'wgc',
|
|
60
|
+
error_category: 'resource',
|
|
61
|
+
error_message: `${failText}\n${deleteResponse.error.message}`,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
console.error(deleteResponse.error.message);
|
|
65
|
+
return await waitForKeyPress({
|
|
66
|
+
Enter: () => undefined,
|
|
67
|
+
r: retryFn,
|
|
68
|
+
R: retryFn,
|
|
69
|
+
}, `Failed to delete the federated graph ${pc.bold(graphData.graph.name)}. [ENTER] to continue, [r] to retry. CTRL+C to quit.`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
deleted = true;
|
|
73
|
+
}
|
|
74
|
+
if (deleted) {
|
|
75
|
+
spinner.succeed(`Federated graph ${pc.bold(graphData.graph.name)} removed.`);
|
|
76
|
+
captureOnboardingEvent({
|
|
77
|
+
name: 'onboarding_step_completed',
|
|
78
|
+
properties: {
|
|
79
|
+
step_name: 'delete_federated_graph',
|
|
80
|
+
entry_source: 'wgc',
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function handleCreateFederatedGraphResponse(client, { onboarding, userInfo, }) {
|
|
86
|
+
function retryFn() {
|
|
87
|
+
resetScreen(userInfo);
|
|
88
|
+
handleCreateFederatedGraphResponse(client, { onboarding, userInfo });
|
|
89
|
+
}
|
|
90
|
+
const routingUrl = new URL('graphql', 'http://localhost');
|
|
91
|
+
routingUrl.port = String(config.demoRouterPort);
|
|
92
|
+
const federatedGraphSpinner = demoSpinner().start();
|
|
93
|
+
const createGraphResponse = await createFederatedGraph(client, {
|
|
94
|
+
name: config.demoGraphName,
|
|
95
|
+
namespace: config.demoNamespace,
|
|
96
|
+
labelMatcher: config.demoLabelMatcher,
|
|
97
|
+
routingUrl,
|
|
98
|
+
});
|
|
99
|
+
if (createGraphResponse.error) {
|
|
100
|
+
federatedGraphSpinner.fail(createGraphResponse.error.message);
|
|
101
|
+
await waitForKeyPress({
|
|
102
|
+
r: retryFn,
|
|
103
|
+
R: retryFn,
|
|
104
|
+
}, 'Hit [r] to refresh. CTRL+C to quit');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
federatedGraphSpinner.succeed(`Federated graph ${pc.bold('demo')} succesfully created.`);
|
|
108
|
+
}
|
|
109
|
+
async function handleStep2(opts, { onboarding, userInfo, supportDir, signal, logPath, }) {
|
|
110
|
+
var _a;
|
|
111
|
+
function retryFn() {
|
|
112
|
+
resetScreen(userInfo);
|
|
113
|
+
return handleStep2(opts, { onboarding, userInfo, supportDir, signal, logPath });
|
|
114
|
+
}
|
|
115
|
+
async function publishPlugins() {
|
|
116
|
+
console.log(`\nPublishing plugins… ${pc.dim(`(logs: ${logPath})`)}`);
|
|
117
|
+
const publishResult = await publishAllPlugins({
|
|
118
|
+
client: opts.client,
|
|
119
|
+
supportDir,
|
|
120
|
+
signal,
|
|
121
|
+
logPath,
|
|
122
|
+
});
|
|
123
|
+
if (publishResult.error) {
|
|
124
|
+
await waitForKeyPress({
|
|
125
|
+
r: retryFn,
|
|
126
|
+
R: retryFn,
|
|
127
|
+
}, 'Hit [r] to retry. CTRL+C to quit.');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const graphData = await handleGetFederatedGraphResponse(opts.client, {
|
|
131
|
+
onboarding,
|
|
132
|
+
userInfo,
|
|
133
|
+
});
|
|
134
|
+
const graph = graphData === null || graphData === void 0 ? void 0 : graphData.graph;
|
|
135
|
+
const subgraphs = (_a = graphData === null || graphData === void 0 ? void 0 : graphData.subgraphs) !== null && _a !== void 0 ? _a : [];
|
|
136
|
+
if (graph) {
|
|
137
|
+
let deleted = false;
|
|
138
|
+
const cleanupFn = async () => {
|
|
139
|
+
await cleanupFederatedGraph(opts.client, {
|
|
140
|
+
graphData: { graph, subgraphs },
|
|
141
|
+
userInfo,
|
|
142
|
+
});
|
|
143
|
+
deleted = true;
|
|
144
|
+
};
|
|
145
|
+
await waitForKeyPress({
|
|
146
|
+
Enter: () => undefined,
|
|
147
|
+
d: cleanupFn,
|
|
148
|
+
D: cleanupFn,
|
|
149
|
+
}, 'Hit [ENTER] to continue or [d] to delete the federated graph and its subgraphs to start over. CTRL+C to quit.');
|
|
150
|
+
if (deleted) {
|
|
151
|
+
console.log(pc.yellow('\nPlease restart the demo command to continue.\n'));
|
|
152
|
+
process.exit(0);
|
|
153
|
+
}
|
|
154
|
+
await publishPlugins();
|
|
155
|
+
return { routingUrl: graph.routingURL };
|
|
156
|
+
}
|
|
157
|
+
await handleCreateFederatedGraphResponse(opts.client, {
|
|
158
|
+
onboarding,
|
|
159
|
+
userInfo,
|
|
160
|
+
});
|
|
161
|
+
const routingUrl = new URL('graphql', 'http://localhost');
|
|
162
|
+
routingUrl.port = String(config.demoRouterPort);
|
|
163
|
+
await publishPlugins();
|
|
164
|
+
return { routingUrl: routingUrl.toString() };
|
|
165
|
+
}
|
|
166
|
+
async function handleStep3(opts, { userInfo, routerBaseUrl, signal, logPath, }) {
|
|
167
|
+
let firedQueries = 0;
|
|
168
|
+
function retryFn() {
|
|
169
|
+
firedQueries = 0;
|
|
170
|
+
resetScreen(userInfo);
|
|
171
|
+
return handleStep3(opts, { userInfo, routerBaseUrl, signal, logPath });
|
|
172
|
+
}
|
|
173
|
+
const tokenParams = {
|
|
174
|
+
client: opts.client,
|
|
175
|
+
tokenName: config.demoRouterTokenName,
|
|
176
|
+
graphName: config.demoGraphName,
|
|
177
|
+
namespace: config.demoNamespace,
|
|
178
|
+
};
|
|
179
|
+
// Delete existing token first (idempotent — no error if missing)
|
|
180
|
+
const deleteResult = await deleteRouterToken(tokenParams);
|
|
181
|
+
if (deleteResult.error) {
|
|
182
|
+
const errorText = `Failed to clean up existing router token: ${deleteResult.error.message}`;
|
|
183
|
+
console.error(errorText);
|
|
184
|
+
captureOnboardingEvent({
|
|
185
|
+
name: 'onboarding_step_failed',
|
|
186
|
+
properties: {
|
|
187
|
+
step_name: 'run_router_send_metrics',
|
|
188
|
+
entry_source: 'wgc',
|
|
189
|
+
error_category: 'router',
|
|
190
|
+
error_message: errorText,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
await waitForKeyPress({ r: retryFn, R: retryFn }, 'Hit [r] to retry. CTRL+C to quit.');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const spinner = demoSpinner('Generating router token…').start();
|
|
197
|
+
const createResult = await createRouterToken(tokenParams);
|
|
198
|
+
if (createResult.error) {
|
|
199
|
+
const failText = `Failed to generate router token: ${createResult.error.message}`;
|
|
200
|
+
spinner.fail(failText);
|
|
201
|
+
captureOnboardingEvent({
|
|
202
|
+
name: 'onboarding_step_failed',
|
|
203
|
+
properties: {
|
|
204
|
+
step_name: 'run_router_send_metrics',
|
|
205
|
+
entry_source: 'wgc',
|
|
206
|
+
error_category: 'router',
|
|
207
|
+
error_message: failText,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
await waitForKeyPress({ r: retryFn, R: retryFn }, 'Hit [r] to retry. CTRL+C to quit.');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
spinner.succeed('Router token generated.');
|
|
214
|
+
console.log(` ${pc.bold(createResult.token)}`);
|
|
215
|
+
const sampleQuery = JSON.stringify({
|
|
216
|
+
query: `query GetProductWithReviews($id: ID!) { product(id: $id) { id title price { currency amount } reviews { id author rating contents } } }`,
|
|
217
|
+
variables: { id: 'product-1' },
|
|
218
|
+
});
|
|
219
|
+
async function fireSampleQuery() {
|
|
220
|
+
const querySpinner = demoSpinner('Sending sample query…').start();
|
|
221
|
+
try {
|
|
222
|
+
const res = await fetch(`${routerBaseUrl}/graphql`, {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers: {
|
|
225
|
+
'Content-Type': 'application/json',
|
|
226
|
+
'GraphQL-Client-Name': 'wgc',
|
|
227
|
+
},
|
|
228
|
+
body: sampleQuery,
|
|
229
|
+
});
|
|
230
|
+
const body = await res.json();
|
|
231
|
+
querySpinner.succeed('Sample query response:');
|
|
232
|
+
console.log(pc.dim(JSON.stringify(body, null, 2)));
|
|
233
|
+
if (firedQueries === 0) {
|
|
234
|
+
captureOnboardingEvent({
|
|
235
|
+
name: 'onboarding_step_completed',
|
|
236
|
+
properties: {
|
|
237
|
+
step_name: 'run_router_send_metrics',
|
|
238
|
+
entry_source: 'wgc',
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
firedQueries++;
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
const failText = `Sample query failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
246
|
+
captureOnboardingEvent({
|
|
247
|
+
name: 'onboarding_step_failed',
|
|
248
|
+
properties: {
|
|
249
|
+
step_name: 'run_router_send_metrics',
|
|
250
|
+
entry_source: 'wgc',
|
|
251
|
+
error_category: 'router',
|
|
252
|
+
error_message: failText,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
querySpinner.fail(failText);
|
|
256
|
+
}
|
|
257
|
+
showQueryPrompt();
|
|
258
|
+
}
|
|
259
|
+
function showQueryPrompt() {
|
|
260
|
+
waitForKeyPress({ r: fireSampleQuery, R: fireSampleQuery }, 'Hit [r] to send a sample query. CTRL+C to stop the router.');
|
|
261
|
+
}
|
|
262
|
+
const routerResult = await runRouterContainer({
|
|
263
|
+
routerToken: createResult.token,
|
|
264
|
+
routerBaseUrl,
|
|
265
|
+
signal,
|
|
266
|
+
logPath,
|
|
267
|
+
});
|
|
268
|
+
if (routerResult.error) {
|
|
269
|
+
const errorText = `Router exited with error: ${routerResult.error.message}`;
|
|
270
|
+
console.error(`\n${errorText}`);
|
|
271
|
+
captureOnboardingEvent({
|
|
272
|
+
name: 'onboarding_step_failed',
|
|
273
|
+
properties: {
|
|
274
|
+
step_name: 'run_router_send_metrics',
|
|
275
|
+
entry_source: 'wgc',
|
|
276
|
+
error_category: 'router',
|
|
277
|
+
error_message: errorText,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
await waitForKeyPress({ r: retryFn, R: retryFn }, 'Hit [r] to retry. CTRL+C to quit.');
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
showQueryPrompt();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async function handleGetOnboardingResponse(client, userInfo) {
|
|
287
|
+
const onboardingCheck = await checkExistingOnboarding(client);
|
|
288
|
+
async function retryFn() {
|
|
289
|
+
return await handleGetOnboardingResponse(client, userInfo);
|
|
290
|
+
}
|
|
291
|
+
switch (onboardingCheck.status) {
|
|
292
|
+
case 'ok': {
|
|
293
|
+
return onboardingCheck.onboarding;
|
|
294
|
+
}
|
|
295
|
+
case 'not-allowed': {
|
|
296
|
+
const errorText = 'Only organization owners can trigger onboarding.';
|
|
297
|
+
captureOnboardingEvent({
|
|
298
|
+
name: 'onboarding_step_failed',
|
|
299
|
+
properties: {
|
|
300
|
+
step_name: 'check_onboarding',
|
|
301
|
+
entry_source: 'wgc',
|
|
302
|
+
error_category: 'resource',
|
|
303
|
+
error_message: errorText,
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
program.error(errorText);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case 'error': {
|
|
310
|
+
const errorText = 'An issue occured while fetching the onboarding status';
|
|
311
|
+
console.error(errorText);
|
|
312
|
+
console.error(onboardingCheck.error);
|
|
313
|
+
captureOnboardingEvent({
|
|
314
|
+
name: 'onboarding_step_failed',
|
|
315
|
+
properties: {
|
|
316
|
+
step_name: 'check_onboarding',
|
|
317
|
+
entry_source: 'wgc',
|
|
318
|
+
error_category: 'resource',
|
|
319
|
+
error_message: `${errorText}\n${onboardingCheck.error}`,
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
await waitForKeyPress({ Enter: retryFn }, 'Hit Enter to retry. CTRL+C to quit.');
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
default: {
|
|
326
|
+
program.error('Invariant');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
async function handleStep1(opts, userInfo) {
|
|
331
|
+
return await handleGetOnboardingResponse(opts.client, userInfo);
|
|
332
|
+
}
|
|
333
|
+
async function getUserInfo(client) {
|
|
334
|
+
const spinner = demoSpinner('Retrieving information about you…').start();
|
|
335
|
+
const { userInfo, error } = await fetchUserInfo(client);
|
|
336
|
+
if (error) {
|
|
337
|
+
spinner.fail(error.message);
|
|
338
|
+
captureOnboardingEvent({
|
|
339
|
+
name: 'onboarding_step_failed',
|
|
340
|
+
properties: {
|
|
341
|
+
step_name: 'init',
|
|
342
|
+
entry_source: 'wgc',
|
|
343
|
+
error_category: 'resource',
|
|
344
|
+
error_message: error.message,
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
program.error(error.message);
|
|
348
|
+
}
|
|
349
|
+
else if (!userInfo) {
|
|
350
|
+
spinner.fail('Could not retrieve information about your account.');
|
|
351
|
+
program.error('Failed to retrieve user information.');
|
|
352
|
+
}
|
|
353
|
+
spinner.succeed(`You are signed in as ${pc.bold(userInfo.userEmail)} in organization ${pc.bold(userInfo.organizationName)}.`);
|
|
354
|
+
return userInfo;
|
|
355
|
+
}
|
|
356
|
+
export default function (opts) {
|
|
357
|
+
return async function handleCommand() {
|
|
358
|
+
const controller = new AbortController();
|
|
359
|
+
try {
|
|
360
|
+
clearScreen();
|
|
361
|
+
printHello();
|
|
362
|
+
const supportDir = await prepareSupportingData();
|
|
363
|
+
await checkDockerReadiness();
|
|
364
|
+
const userInfo = await getUserInfo(opts.client);
|
|
365
|
+
updateScreenWithUserInfo(userInfo);
|
|
366
|
+
const onboardingUrl = new URL('/onboarding', config.webURL);
|
|
367
|
+
async function openOnboardingUrl() {
|
|
368
|
+
const browserUrl = new URL(onboardingUrl);
|
|
369
|
+
browserUrl.searchParams.set('referrer', 'wgc');
|
|
370
|
+
const process = await open(browserUrl.toString());
|
|
371
|
+
process.on('error', (error) => {
|
|
372
|
+
console.log(pc.yellow(`\nCouldn't open browser: ${error.message}`));
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
await waitForKeyPress({
|
|
376
|
+
Enter: () => undefined,
|
|
377
|
+
s: { callback: openOnboardingUrl, persistent: true },
|
|
378
|
+
S: { callback: openOnboardingUrl, persistent: true },
|
|
379
|
+
}, `It is recommended you run this command along the onboarding wizard at ${onboardingUrl} with the same account.\nPress [s] to open it in your browser, or [ENTER] to continue…`);
|
|
380
|
+
resetScreen(userInfo);
|
|
381
|
+
captureOnboardingEvent({
|
|
382
|
+
name: 'onboarding_step_completed',
|
|
383
|
+
properties: {
|
|
384
|
+
step_name: 'init',
|
|
385
|
+
entry_source: 'wgc',
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
const onboardingCheck = await handleStep1(opts, userInfo);
|
|
389
|
+
if (!onboardingCheck) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
captureOnboardingEvent({
|
|
393
|
+
name: 'onboarding_step_completed',
|
|
394
|
+
properties: {
|
|
395
|
+
step_name: 'check_onboarding',
|
|
396
|
+
entry_source: 'wgc',
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
const logPath = getDemoLogPath();
|
|
400
|
+
const step2Result = await handleStep2(opts, {
|
|
401
|
+
onboarding: onboardingCheck,
|
|
402
|
+
userInfo,
|
|
403
|
+
supportDir,
|
|
404
|
+
signal: controller.signal,
|
|
405
|
+
logPath,
|
|
406
|
+
});
|
|
407
|
+
if (!step2Result) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
captureOnboardingEvent({
|
|
411
|
+
name: 'onboarding_step_completed',
|
|
412
|
+
properties: {
|
|
413
|
+
step_name: 'create_federated_graph',
|
|
414
|
+
entry_source: 'wgc',
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
const routerBaseUrl = new URL(step2Result.routingUrl).origin;
|
|
418
|
+
await handleStep3(opts, { userInfo, routerBaseUrl, signal: controller.signal, logPath });
|
|
419
|
+
}
|
|
420
|
+
finally {
|
|
421
|
+
// no-op
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=command.js.map
|