stepzen 0.18.0 → 0.19.0-beta.2
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 +13 -3
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/import.d.ts +21 -0
- package/lib/commands/import.js +208 -120
- package/lib/commands/init.js +2 -2
- package/lib/commands/lint.js +2 -2
- package/lib/commands/list.js +1 -1
- package/lib/commands/login.js +3 -3
- package/lib/commands/logout.js +1 -1
- package/lib/commands/start.js +14 -12
- package/lib/commands/transpile.js +5 -5
- package/lib/commands/upload.js +1 -1
- package/lib/commands/validate.js +6 -4
- package/lib/commands/whoami.js +3 -3
- package/lib/generate/curl2sdl.d.ts +4 -6
- package/lib/generate/curl2sdl.js +26 -17
- package/lib/generate/graphql2sdl.d.ts +5 -7
- package/lib/generate/graphql2sdl.js +21 -8
- package/lib/generate/helpers.d.ts +10 -2
- package/lib/generate/helpers.js +45 -22
- package/lib/generate/index.d.ts +5 -3
- package/lib/generate/index.js +6 -6
- package/lib/generate/sql2sdl.d.ts +23 -0
- package/lib/generate/sql2sdl.js +155 -0
- package/lib/hooks/prerun/check-upgrade.js +13 -10
- package/lib/hooks/prerun/ensure-config-file.js +3 -3
- package/lib/index.js +1 -0
- package/lib/shared/actions.js +9 -6
- package/lib/shared/configuration.js +20 -14
- package/lib/shared/constants.d.ts +4 -0
- package/lib/shared/constants.js +18 -4
- package/lib/shared/curl-parser.js +3 -2
- package/lib/shared/errors.js +2 -1
- package/lib/shared/header-params-parser.js +6 -4
- package/lib/shared/header.js +2 -1
- package/lib/shared/moniker.js +5 -3
- package/lib/shared/path-params-parser.d.ts +1 -1
- package/lib/shared/path-params-parser.js +5 -3
- package/lib/shared/stepzen-sdk.d.ts +1 -1
- package/lib/shared/stepzen-sdk.js +1 -1
- package/lib/shared/utils.d.ts +1 -0
- package/lib/shared/utils.js +22 -8
- package/lib/shared/validation.js +4 -2
- package/lib/shared/workspace.js +21 -16
- package/lib/shared/zen-command.js +7 -7
- package/lib/start/console.d.ts +1 -1
- package/lib/start/console.js +16 -9
- package/lib/start/index.js +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
package/lib/commands/start.js
CHANGED
|
@@ -27,25 +27,27 @@ class Start extends zen_command_1.default {
|
|
|
27
27
|
if (flags.endpoint) {
|
|
28
28
|
workspace.endpoint = flags.endpoint;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (!flags['no-dashboard']) {
|
|
31
|
+
// Check the port is available
|
|
32
|
+
const port = await detect(flags.port);
|
|
33
|
+
if (flags.port !== port) {
|
|
34
|
+
throw new errors_1.CLIError(`Could not start - port ${flags.port} is already in use`);
|
|
35
|
+
}
|
|
34
36
|
}
|
|
35
|
-
const printEndpointDetailsOnce = lodash_1.once(() => {
|
|
36
|
-
start_1.success({
|
|
37
|
+
const printEndpointDetailsOnce = (0, lodash_1.once)(() => {
|
|
38
|
+
(0, start_1.success)({
|
|
37
39
|
workspace,
|
|
38
40
|
account: configuration.account,
|
|
39
|
-
port: flags.port,
|
|
41
|
+
port: flags['no-dashboard'] ? undefined : flags.port,
|
|
40
42
|
});
|
|
41
43
|
this.log();
|
|
42
44
|
});
|
|
43
45
|
// This is the file watcher
|
|
44
46
|
if (!flags['no-watcher']) {
|
|
45
|
-
const redeploy = throttle_debounce_1.debounce(500, (path) => {
|
|
47
|
+
const redeploy = (0, throttle_debounce_1.debounce)(500, (path) => {
|
|
46
48
|
debug('stepzen:start')(`chokidar decected change to ${path}`);
|
|
47
|
-
start_1.changed({ workspace, file: path });
|
|
48
|
-
start_1.deploy({ workspace, flags }).then(didDeploy => {
|
|
49
|
+
(0, start_1.changed)({ workspace, file: path });
|
|
50
|
+
(0, start_1.deploy)({ workspace, flags }).then(didDeploy => {
|
|
49
51
|
didDeploy && printEndpointDetailsOnce();
|
|
50
52
|
});
|
|
51
53
|
});
|
|
@@ -65,7 +67,7 @@ class Start extends zen_command_1.default {
|
|
|
65
67
|
let didDeploy = false;
|
|
66
68
|
// Unless explicitly disabled, auto-init
|
|
67
69
|
if (!flags['no-init']) {
|
|
68
|
-
didDeploy = await start_1.deploy({ workspace, flags });
|
|
70
|
+
didDeploy = await (0, start_1.deploy)({ workspace, flags });
|
|
69
71
|
}
|
|
70
72
|
// Create the dashboard
|
|
71
73
|
if (!flags['no-dashboard']) {
|
|
@@ -96,7 +98,7 @@ class Start extends zen_command_1.default {
|
|
|
96
98
|
printEndpointDetailsOnce();
|
|
97
99
|
}
|
|
98
100
|
if (!flags['no-watcher']) {
|
|
99
|
-
start_1.watching(workspace);
|
|
101
|
+
(0, start_1.watching)(workspace);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
}
|
|
@@ -12,10 +12,10 @@ const zen_command_1 = require("../shared/zen-command");
|
|
|
12
12
|
class Transpile extends zen_command_1.default {
|
|
13
13
|
async run() {
|
|
14
14
|
const { args, flags } = this.parse(Transpile);
|
|
15
|
-
const folder = utils_1.getDirectory(args.folder);
|
|
15
|
+
const folder = (0, utils_1.getDirectory)(args.folder);
|
|
16
16
|
// CONFIG
|
|
17
17
|
if (flags['output-configuration']) {
|
|
18
|
-
const config = await transpiler_1.configure(folder, flags.silent);
|
|
18
|
+
const config = await (0, transpiler_1.configure)(folder, flags.silent);
|
|
19
19
|
if (flags['hide-output']) {
|
|
20
20
|
return config;
|
|
21
21
|
}
|
|
@@ -24,9 +24,9 @@ class Transpile extends zen_command_1.default {
|
|
|
24
24
|
}
|
|
25
25
|
// SCHEMA
|
|
26
26
|
try {
|
|
27
|
-
const schema = transpiler_1.stitch(folder);
|
|
28
|
-
transpiler_1.validate(schema, {
|
|
29
|
-
extensions: await utils_1.getStepZenExtensions(),
|
|
27
|
+
const schema = (0, transpiler_1.stitch)(folder);
|
|
28
|
+
(0, transpiler_1.validate)(schema, {
|
|
29
|
+
extensions: await (0, utils_1.getStepZenExtensions)(),
|
|
30
30
|
});
|
|
31
31
|
const file = path.join(schema, 'index.graphql');
|
|
32
32
|
const stitched = fs.readFileSync(file, 'utf8');
|
package/lib/commands/upload.js
CHANGED
|
@@ -37,7 +37,7 @@ class Upload extends zen_command_1.default {
|
|
|
37
37
|
if (!flags.silent) {
|
|
38
38
|
this.log('Uploading...');
|
|
39
39
|
}
|
|
40
|
-
const response = await actions_1.upload(args.type, args.destination, source);
|
|
40
|
+
const response = await (0, actions_1.upload)(args.type, args.destination, source);
|
|
41
41
|
if (response.success) {
|
|
42
42
|
if (!flags.silent) {
|
|
43
43
|
this.log(response.message);
|
package/lib/commands/validate.js
CHANGED
|
@@ -7,17 +7,19 @@ const errors_1 = require("@oclif/errors");
|
|
|
7
7
|
const transpiler_1 = require("@stepzen/transpiler");
|
|
8
8
|
const utils_1 = require("../shared/utils");
|
|
9
9
|
const zen_command_1 = require("../shared/zen-command");
|
|
10
|
+
const core_1 = require("@oclif/core");
|
|
10
11
|
class Validate extends zen_command_1.default {
|
|
11
12
|
async run() {
|
|
12
13
|
const { args } = this.parse(Validate);
|
|
13
|
-
const folder = utils_1.getDirectory(args.folder);
|
|
14
|
+
const folder = (0, utils_1.getDirectory)(args.folder);
|
|
14
15
|
try {
|
|
15
|
-
const schema = transpiler_1.stitch(folder);
|
|
16
|
-
transpiler_1.validate(schema, {
|
|
17
|
-
extensions: await utils_1.getStepZenExtensions(),
|
|
16
|
+
const schema = (0, transpiler_1.stitch)(folder);
|
|
17
|
+
(0, transpiler_1.validate)(schema, {
|
|
18
|
+
extensions: await (0, utils_1.getStepZenExtensions)(),
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
21
|
catch (error) {
|
|
22
|
+
core_1.CliUx.ux.action.stop(chalk.red('fail'));
|
|
21
23
|
throw new errors_1.CLIError(chalk.red(error));
|
|
22
24
|
}
|
|
23
25
|
}
|
package/lib/commands/whoami.js
CHANGED
|
@@ -9,7 +9,7 @@ const zen_command_1 = require("../shared/zen-command");
|
|
|
9
9
|
class WhoAmI extends zen_command_1.default {
|
|
10
10
|
async run() {
|
|
11
11
|
const { flags } = this.parse(WhoAmI);
|
|
12
|
-
const configuration = await configuration_1.readConfiguration();
|
|
12
|
+
const configuration = await (0, configuration_1.readConfiguration)();
|
|
13
13
|
if (!('account' in configuration)) {
|
|
14
14
|
this.log('You are not logged in.');
|
|
15
15
|
return;
|
|
@@ -36,7 +36,7 @@ class WhoAmI extends zen_command_1.default {
|
|
|
36
36
|
details.adminkey = configuration.adminkey;
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
details.adminkey = utils_1.maskStepZenKey(configuration.adminkey);
|
|
39
|
+
details.adminkey = (0, utils_1.maskStepZenKey)(configuration.adminkey);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
if (configuration.apikey) {
|
|
@@ -44,7 +44,7 @@ class WhoAmI extends zen_command_1.default {
|
|
|
44
44
|
details.apikey = configuration.apikey;
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
|
-
details.apikey = utils_1.maskStepZenKey(configuration.apikey);
|
|
47
|
+
details.apikey = (0, utils_1.maskStepZenKey)(configuration.apikey);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
this.log();
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { CurlArguments } from '../shared/curl-parser';
|
|
2
2
|
import { PathParam } from '../shared/path-params-parser';
|
|
3
3
|
import { HeaderInput } from '../shared/header';
|
|
4
|
-
|
|
4
|
+
import type { CommonImportOptions } from '.';
|
|
5
|
+
export declare type Curl2SdlOptions = CommonImportOptions & {
|
|
5
6
|
curlArgs: CurlArguments;
|
|
6
|
-
name?: string;
|
|
7
|
-
source: string;
|
|
8
7
|
queryName?: string;
|
|
9
8
|
rootType?: string;
|
|
10
9
|
typePrefix?: string;
|
|
11
10
|
pathParams: readonly PathParam[];
|
|
12
11
|
headers: readonly HeaderInput[];
|
|
13
|
-
onConflict: 'overwrite' | 'append';
|
|
14
12
|
};
|
|
15
|
-
export declare type
|
|
13
|
+
export declare type InteractiveCurl2SdlOptions = Pick<Curl2SdlOptions, 'curlArgs' | 'queryName' | 'rootType' | 'typePrefix' | 'pathParams'>;
|
|
16
14
|
export declare type CurlAnswers = {
|
|
17
15
|
url: string;
|
|
18
16
|
queryName: string;
|
|
@@ -47,7 +45,7 @@ export declare const compileParameterList: (headers: HeaderInput[], pathParams:
|
|
|
47
45
|
* there are no duplicates
|
|
48
46
|
*/
|
|
49
47
|
export declare const makeDuplicateParamsMessage: (headers: HeaderInput[], pathParams: PathParam[], url: string) => string | null;
|
|
50
|
-
export declare const askCurlQuestions: (defaultAnswers?: Partial<CurlAnswers>) => Promise<
|
|
48
|
+
export declare const askCurlQuestions: (defaultAnswers?: Partial<CurlAnswers>) => Promise<InteractiveCurl2SdlOptions>;
|
|
51
49
|
export declare const curl2sdl: ({ curlArgs, name, source, queryName, rootType, typePrefix, pathParams, headers, onConflict, }: Curl2SdlOptions) => Promise<{
|
|
52
50
|
error: string;
|
|
53
51
|
} | {
|
package/lib/generate/curl2sdl.js
CHANGED
|
@@ -9,6 +9,7 @@ const string_argv_1 = require("string-argv");
|
|
|
9
9
|
const curl_parser_1 = require("../shared/curl-parser");
|
|
10
10
|
const path_params_parser_1 = require("../shared/path-params-parser");
|
|
11
11
|
const helpers_1 = require("./helpers");
|
|
12
|
+
const constants_1 = require("../shared/constants");
|
|
12
13
|
/**
|
|
13
14
|
* Collect together all query parameters from HTTP headers and from the
|
|
14
15
|
* pathname, and return them as a uniform list.
|
|
@@ -18,12 +19,12 @@ const helpers_1 = require("./helpers");
|
|
|
18
19
|
* @param {*} pathname full pathname of the REST endpoint
|
|
19
20
|
* @returns {*} combined list of query parameters in a uniform format
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
+
const compileParameterList = (headers, pathParams, pathname) => {
|
|
22
23
|
// Drop empty segments, including empty string before the leading slash
|
|
23
24
|
const pathSegments = pathname.split('/').filter(Boolean);
|
|
24
25
|
// For each header, make a list of the parameters it contains.
|
|
25
26
|
// `flatMap()` concatenates each header's param lists into a single list.
|
|
26
|
-
return lodash_1.flatMap(headers, header => {
|
|
27
|
+
return (0, lodash_1.flatMap)(headers, header => {
|
|
27
28
|
// skip headers that don't contain parameters
|
|
28
29
|
if (!('parts' in header)) {
|
|
29
30
|
return [];
|
|
@@ -52,6 +53,7 @@ exports.compileParameterList = (headers, pathParams, pathname) => {
|
|
|
52
53
|
context: `pathname ${chalk.dim(`(${pathname})`)}`,
|
|
53
54
|
})));
|
|
54
55
|
};
|
|
56
|
+
exports.compileParameterList = compileParameterList;
|
|
55
57
|
/**
|
|
56
58
|
* Check the header and path parameters for duplicates, and construct a
|
|
57
59
|
* user-friendly error message describing identified problems (if any).
|
|
@@ -63,15 +65,15 @@ exports.compileParameterList = (headers, pathParams, pathname) => {
|
|
|
63
65
|
* @returns {*} a message describing duplicate query parameters, or null if
|
|
64
66
|
* there are no duplicates
|
|
65
67
|
*/
|
|
66
|
-
|
|
68
|
+
const makeDuplicateParamsMessage = (headers, pathParams, url) => {
|
|
67
69
|
// Create a uniform list of query parameters from the headers and path
|
|
68
|
-
const parameters = exports.compileParameterList(headers, pathParams, new URL(url).pathname);
|
|
69
|
-
const errors = Object.entries(lodash_1.groupBy(parameters, 'name'))
|
|
70
|
+
const parameters = (0, exports.compileParameterList)(headers, pathParams, new URL(url).pathname);
|
|
71
|
+
const errors = Object.entries((0, lodash_1.groupBy)(parameters, 'name'))
|
|
70
72
|
// Create groups for each unique parameter name,
|
|
71
73
|
// and then sub-groups for each unique [name, value] tuple.
|
|
72
74
|
.map(([name, group]) => ({
|
|
73
75
|
name,
|
|
74
|
-
values: Object.entries(lodash_1.groupBy(group, 'value')),
|
|
76
|
+
values: Object.entries((0, lodash_1.groupBy)(group, 'value')),
|
|
75
77
|
}))
|
|
76
78
|
// ignore the [name, value] tuples that occur only once
|
|
77
79
|
.filter(({ values }) => values.length > 1)
|
|
@@ -87,8 +89,9 @@ exports.makeDuplicateParamsMessage = (headers, pathParams, url) => {
|
|
|
87
89
|
}
|
|
88
90
|
return null;
|
|
89
91
|
};
|
|
90
|
-
exports.
|
|
91
|
-
|
|
92
|
+
exports.makeDuplicateParamsMessage = makeDuplicateParamsMessage;
|
|
93
|
+
const askCurlQuestions = async (defaultAnswers = {}) => {
|
|
94
|
+
const questions = [
|
|
92
95
|
{
|
|
93
96
|
name: 'url',
|
|
94
97
|
message: 'Endpoint URL or a full curl command',
|
|
@@ -110,16 +113,15 @@ exports.askCurlQuestions = async (defaultAnswers = {}) => {
|
|
|
110
113
|
message: 'Prefix to add to all generated type names (leave blank to use defaults)',
|
|
111
114
|
},
|
|
112
115
|
];
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const curlArgs = curl_parser_1.parseCurlArgv(string_argv_1.default(answers.url));
|
|
116
|
+
const answers = await inquirer.prompt((0, helpers_1.overrideDefaults)(questions, defaultAnswers));
|
|
117
|
+
const curlArgs = (0, curl_parser_1.parseCurlArgv)((0, string_argv_1.default)(answers.url));
|
|
116
118
|
if ('error' in curlArgs) {
|
|
117
119
|
console.log();
|
|
118
120
|
console.log(chalk.red('A problem occurred while parsing the curl command:\n', curlArgs.error), '\nPlease enter a URL or a supported curl command.');
|
|
119
121
|
console.log();
|
|
120
|
-
return exports.askCurlQuestions(answers);
|
|
122
|
+
return (0, exports.askCurlQuestions)(answers);
|
|
121
123
|
}
|
|
122
|
-
const parsedPathParamsOrError = path_params_parser_1.parsePathParamsPattern(curlArgs.url, answers.pathParams);
|
|
124
|
+
const parsedPathParamsOrError = (0, path_params_parser_1.parsePathParamsPattern)(curlArgs.url, answers.pathParams);
|
|
123
125
|
if ('error' in parsedPathParamsOrError) {
|
|
124
126
|
console.log();
|
|
125
127
|
console.log(chalk.red('A problem occurred while parsing path parameters pattern:\n', parsedPathParamsOrError.error));
|
|
@@ -132,7 +134,7 @@ exports.askCurlQuestions = async (defaultAnswers = {}) => {
|
|
|
132
134
|
`\tendpoint URL: https://example.com/users/jane/posts/12\n ` +
|
|
133
135
|
`\tpath parameters: /users/${chalk.bold('$userId')}/posts/${chalk.bold('$postId')}`);
|
|
134
136
|
console.log();
|
|
135
|
-
return exports.askCurlQuestions(answers);
|
|
137
|
+
return (0, exports.askCurlQuestions)(answers);
|
|
136
138
|
}
|
|
137
139
|
return {
|
|
138
140
|
curlArgs,
|
|
@@ -142,8 +144,9 @@ exports.askCurlQuestions = async (defaultAnswers = {}) => {
|
|
|
142
144
|
pathParams: parsedPathParamsOrError,
|
|
143
145
|
};
|
|
144
146
|
};
|
|
145
|
-
exports.
|
|
146
|
-
|
|
147
|
+
exports.askCurlQuestions = askCurlQuestions;
|
|
148
|
+
const curl2sdl = async ({ curlArgs, name, source, queryName, rootType, typePrefix, pathParams, headers, onConflict, }) => {
|
|
149
|
+
const response = await (0, helpers_1.queryIntrospectionService)(constants_1.STEPZEN_JSON2SDL_SERVER_URL, {
|
|
147
150
|
operation: 'getSDLFromCurl',
|
|
148
151
|
variables: {
|
|
149
152
|
command: {
|
|
@@ -183,5 +186,11 @@ exports.curl2sdl = async ({ curlArgs, name, source, queryName, rootType, typePre
|
|
|
183
186
|
if (response.error) {
|
|
184
187
|
return { error: response.error };
|
|
185
188
|
}
|
|
186
|
-
return helpers_1.writeSdlAndConfig(
|
|
189
|
+
return (0, helpers_1.writeSdlAndConfig)({
|
|
190
|
+
name: name || 'curl',
|
|
191
|
+
source,
|
|
192
|
+
onConflict,
|
|
193
|
+
response,
|
|
194
|
+
});
|
|
187
195
|
};
|
|
196
|
+
exports.curl2sdl = curl2sdl;
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { HeaderInput } from '../shared/header';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
source: string;
|
|
2
|
+
import type { CommonImportOptions } from '.';
|
|
3
|
+
export declare type GraphQL2SdlOptions = CommonImportOptions & {
|
|
5
4
|
endpoint: string;
|
|
6
5
|
typePrefix?: string;
|
|
7
6
|
includeRootOperations?: boolean;
|
|
8
7
|
headers: readonly HeaderInput[];
|
|
9
|
-
onConflict: 'overwrite' | 'append';
|
|
10
8
|
};
|
|
11
|
-
export declare type
|
|
9
|
+
export declare type InteractiveGraphQL2SdlOptions = Pick<GraphQL2SdlOptions, 'endpoint' | 'typePrefix' | 'includeRootOperations' | 'headers'>;
|
|
12
10
|
export declare type GraphQLAnswers = {
|
|
13
11
|
endpoint: string;
|
|
14
12
|
typePrefix: string;
|
|
15
13
|
includeRootOperations: boolean;
|
|
16
|
-
|
|
14
|
+
header: string;
|
|
17
15
|
};
|
|
18
|
-
export declare const askGraphQLQuestions: (defaultAnswers?: Partial<GraphQLAnswers>) => Promise<
|
|
16
|
+
export declare const askGraphQLQuestions: (defaultAnswers?: Partial<GraphQLAnswers>) => Promise<InteractiveGraphQL2SdlOptions>;
|
|
19
17
|
export declare const graphql2sdl: ({ name, source, endpoint, typePrefix, includeRootOperations, headers, onConflict, }: GraphQL2SdlOptions) => Promise<{
|
|
20
18
|
error: string;
|
|
21
19
|
} | {
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.graphql2sdl = exports.askGraphQLQuestions = void 0;
|
|
5
5
|
const inquirer = require("inquirer");
|
|
6
|
-
const lodash_1 = require("lodash");
|
|
7
6
|
const header_1 = require("../shared/header");
|
|
8
7
|
const helpers_1 = require("./helpers");
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const constants_1 = require("../shared/constants");
|
|
9
|
+
const askGraphQLQuestions = async (defaultAnswers = {}) => {
|
|
10
|
+
const questions = [
|
|
11
11
|
{
|
|
12
12
|
name: 'endpoint',
|
|
13
13
|
message: 'What is the GraphQL endpoint URL?',
|
|
@@ -30,11 +30,18 @@ exports.askGraphQLQuestions = async (defaultAnswers = {}) => {
|
|
|
30
30
|
validate: input => input === '' || header_1.HEADER_REGEX.test(input.trim()) || 'invalid header',
|
|
31
31
|
},
|
|
32
32
|
];
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const answers = await inquirer.prompt((0, helpers_1.overrideDefaults)(questions, defaultAnswers));
|
|
34
|
+
const header = (0, header_1.parseHeader)(answers.header);
|
|
35
|
+
return {
|
|
36
|
+
endpoint: answers.endpoint,
|
|
37
|
+
typePrefix: answers.typePrefix.trim() === '' ? undefined : answers.typePrefix.trim(),
|
|
38
|
+
includeRootOperations: answers.includeRootOperations,
|
|
39
|
+
headers: header && !('error' in header) ? [header] : [],
|
|
40
|
+
};
|
|
35
41
|
};
|
|
36
|
-
exports.
|
|
37
|
-
|
|
42
|
+
exports.askGraphQLQuestions = askGraphQLQuestions;
|
|
43
|
+
const graphql2sdl = async ({ name, source, endpoint, typePrefix, includeRootOperations, headers, onConflict, }) => {
|
|
44
|
+
const response = await (0, helpers_1.queryIntrospectionService)(constants_1.STEPZEN_JSON2SDL_SERVER_URL, {
|
|
38
45
|
operation: 'getSDLFromGraphQL',
|
|
39
46
|
variables: {
|
|
40
47
|
endpoint: {
|
|
@@ -58,5 +65,11 @@ exports.graphql2sdl = async ({ name, source, endpoint, typePrefix, includeRootOp
|
|
|
58
65
|
if (response.error) {
|
|
59
66
|
return { error: response.error };
|
|
60
67
|
}
|
|
61
|
-
return helpers_1.writeSdlAndConfig(
|
|
68
|
+
return (0, helpers_1.writeSdlAndConfig)({
|
|
69
|
+
name: name || 'graphql',
|
|
70
|
+
source,
|
|
71
|
+
onConflict,
|
|
72
|
+
response,
|
|
73
|
+
});
|
|
62
74
|
};
|
|
75
|
+
exports.graphql2sdl = graphql2sdl;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as inquirer from 'inquirer';
|
|
1
2
|
import type { Answers, DistinctQuestion } from 'inquirer';
|
|
2
3
|
export declare const createGeneratorFiles: (id: string, details: any) => Promise<string>;
|
|
3
4
|
export declare type GeneratorConfiguration = {
|
|
@@ -25,7 +26,14 @@ export declare type IntrospectionServiceResponse = {
|
|
|
25
26
|
config?: string;
|
|
26
27
|
error?: string;
|
|
27
28
|
};
|
|
28
|
-
export declare const queryIntrospectionService: (query: IntrospectionServiceQuery) => Promise<IntrospectionServiceResponse>;
|
|
29
|
-
export declare const writeSdlAndConfig: (name
|
|
29
|
+
export declare const queryIntrospectionService: (serverUrl: string, query: IntrospectionServiceQuery) => Promise<IntrospectionServiceResponse>;
|
|
30
|
+
export declare const writeSdlAndConfig: ({ name, source, mergeTypes, onConflict, response, }: {
|
|
31
|
+
name: string;
|
|
32
|
+
source: string;
|
|
33
|
+
mergeTypes?: boolean | undefined;
|
|
34
|
+
onConflict: 'overwrite' | 'append';
|
|
35
|
+
response: IntrospectionServiceResponse;
|
|
36
|
+
}) => Promise<{
|
|
30
37
|
outPath: string;
|
|
31
38
|
}>;
|
|
39
|
+
export declare const overrideDefaults: <Options>(questions: inquirer.DistinctQuestion<Options>[], defaultAnswers: Partial<Options>) => inquirer.DistinctQuestion<Options>[];
|
package/lib/generate/helpers.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Copyright (c) 2020,2021,2022, StepZen, Inc.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.writeSdlAndConfig = exports.queryIntrospectionService = exports.askTemplateQuestions = exports.askGeneratorQuestions = exports.getTemplates = exports.getSchema = exports.getConfiguration = exports.createGeneratorFiles = void 0;
|
|
4
|
+
exports.overrideDefaults = exports.writeSdlAndConfig = exports.queryIntrospectionService = exports.askTemplateQuestions = exports.askGeneratorQuestions = exports.getTemplates = exports.getSchema = exports.getConfiguration = exports.createGeneratorFiles = void 0;
|
|
5
5
|
const errors_1 = require("@oclif/errors");
|
|
6
6
|
const chalk = require("chalk");
|
|
7
7
|
const debug = require("debug");
|
|
@@ -17,12 +17,12 @@ const prettier = require("prettier");
|
|
|
17
17
|
const constants_1 = require("../shared/constants");
|
|
18
18
|
const errors_2 = require("../shared/errors");
|
|
19
19
|
const { version } = require('../../package.json');
|
|
20
|
-
|
|
20
|
+
const createGeneratorFiles = async (id, details) => {
|
|
21
21
|
const url = `${constants_1.STEPZEN_DIRECT_GENERATOR_ENGINES_URL}/create`;
|
|
22
22
|
debug('stepzen:generate')(`calling the generator engine ${id} via ${url}`);
|
|
23
23
|
const engineErrorMessageWrap = (msg) => `An error has occurred when creating the schema: ${msg}. Please check your parameters and try again.`;
|
|
24
24
|
try {
|
|
25
|
-
const response = await node_fetch_1.default(url, {
|
|
25
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
26
26
|
body: JSON.stringify({
|
|
27
27
|
id,
|
|
28
28
|
details: JSON.stringify(details.answers),
|
|
@@ -62,11 +62,12 @@ exports.createGeneratorFiles = async (id, details) => {
|
|
|
62
62
|
: new errors_1.CLIError(errors_2.PERMANENT_STEPZEN_ERROR);
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
-
exports.
|
|
65
|
+
exports.createGeneratorFiles = createGeneratorFiles;
|
|
66
|
+
const getConfiguration = async (id, details = {}) => {
|
|
66
67
|
const url = `${constants_1.STEPZEN_DIRECT_GENERATOR_ENGINES_URL}/configure`;
|
|
67
68
|
debug('stepzen:generate')(`calling the generator engine ${id} via ${url}`);
|
|
68
69
|
try {
|
|
69
|
-
const response = await node_fetch_1.default(url, {
|
|
70
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
70
71
|
body: JSON.stringify({
|
|
71
72
|
id,
|
|
72
73
|
details: JSON.stringify(details),
|
|
@@ -90,7 +91,8 @@ exports.getConfiguration = async (id, details = {}) => {
|
|
|
90
91
|
throw new errors_1.CLIError(errors_2.PERMANENT_STEPZEN_ERROR);
|
|
91
92
|
}
|
|
92
93
|
};
|
|
93
|
-
exports.
|
|
94
|
+
exports.getConfiguration = getConfiguration;
|
|
95
|
+
const getSchema = (arg) => {
|
|
94
96
|
const schema = arg.trim();
|
|
95
97
|
// Now supports importing only one schema at a time:
|
|
96
98
|
// https://github.com/steprz/stepzen-cli/issues/628
|
|
@@ -104,7 +106,8 @@ exports.getSchema = (arg) => {
|
|
|
104
106
|
}
|
|
105
107
|
return schema;
|
|
106
108
|
};
|
|
107
|
-
exports.
|
|
109
|
+
exports.getSchema = getSchema;
|
|
110
|
+
const getTemplates = async () => {
|
|
108
111
|
const tmp = path.join(os.tmpdir(), `stepzen-api-templates-${Date.now()}`);
|
|
109
112
|
fs.ensureDirSync(tmp);
|
|
110
113
|
const repository = constants_1.STEPZEN_API_TEMPLATES_REPOSITORY;
|
|
@@ -115,7 +118,8 @@ exports.getTemplates = async () => {
|
|
|
115
118
|
}
|
|
116
119
|
return tmp;
|
|
117
120
|
};
|
|
118
|
-
exports.
|
|
121
|
+
exports.getTemplates = getTemplates;
|
|
122
|
+
const askGeneratorQuestions = async (id, settings, state) => {
|
|
119
123
|
var _a, _b;
|
|
120
124
|
let status = -1;
|
|
121
125
|
do {
|
|
@@ -123,14 +127,14 @@ exports.askGeneratorQuestions = async (id, settings, state) => {
|
|
|
123
127
|
return Object.assign(Object.assign({ type: 'password' }, question), {
|
|
124
128
|
// set the previous iteration's answer as the default value, except for password fields
|
|
125
129
|
default: question.type && question.type !== 'password'
|
|
126
|
-
? lodash_1.get(state, question.name)
|
|
130
|
+
? (0, lodash_1.get)(state, question.name)
|
|
127
131
|
: undefined });
|
|
128
132
|
});
|
|
129
133
|
// eslint-disable-next-line no-await-in-loop
|
|
130
134
|
const answers = await inquirer.prompt(questions);
|
|
131
|
-
state = lodash_1.merge(state, answers);
|
|
135
|
+
state = (0, lodash_1.merge)(state, answers);
|
|
132
136
|
// eslint-disable-next-line no-await-in-loop
|
|
133
|
-
const result = await exports.getConfiguration(id, state);
|
|
137
|
+
const result = await (0, exports.getConfiguration)(id, state);
|
|
134
138
|
if (!result) {
|
|
135
139
|
// at this point the generator ${id} should have been validated
|
|
136
140
|
throw new errors_1.CLIError(errors_2.PERMANENT_STEPZEN_ERROR);
|
|
@@ -150,22 +154,23 @@ exports.askGeneratorQuestions = async (id, settings, state) => {
|
|
|
150
154
|
questions: result.questions,
|
|
151
155
|
};
|
|
152
156
|
// eslint-disable-next-line require-atomic-updates
|
|
153
|
-
state = lodash_1.merge(state, result.answers);
|
|
157
|
+
state = (0, lodash_1.merge)(state, result.answers);
|
|
154
158
|
}
|
|
155
159
|
status = result.status;
|
|
156
160
|
} while (status === -1);
|
|
157
161
|
return state;
|
|
158
162
|
};
|
|
159
|
-
exports.
|
|
163
|
+
exports.askGeneratorQuestions = askGeneratorQuestions;
|
|
164
|
+
const askTemplateQuestions = async (id, settings, state) => {
|
|
160
165
|
const questions = settings.questions.map((question) => (Object.assign({ type: 'password' }, question)));
|
|
161
166
|
const answers = await inquirer.prompt(questions);
|
|
162
167
|
return Object.assign(Object.assign({}, state), answers);
|
|
163
168
|
};
|
|
164
|
-
exports.
|
|
169
|
+
exports.askTemplateQuestions = askTemplateQuestions;
|
|
170
|
+
const queryIntrospectionService = async (serverUrl, query) => {
|
|
165
171
|
let json;
|
|
166
172
|
try {
|
|
167
|
-
|
|
168
|
-
debug('stepzen:introspection')(url);
|
|
173
|
+
debug('stepzen:introspection')(serverUrl);
|
|
169
174
|
const queryString = `query (
|
|
170
175
|
${Object.entries(query.variables).map(([id, { type }]) => `$${id}: ${type}`)}
|
|
171
176
|
) {
|
|
@@ -178,10 +183,10 @@ exports.queryIntrospectionService = async (query) => {
|
|
|
178
183
|
debug('stepzen:introspection')(query.variables);
|
|
179
184
|
const payload = JSON.stringify({
|
|
180
185
|
query: queryString,
|
|
181
|
-
variables: lodash_1.mapValues(query.variables, ({ value }) => value),
|
|
186
|
+
variables: (0, lodash_1.mapValues)(query.variables, ({ value }) => value),
|
|
182
187
|
});
|
|
183
188
|
debug('stepzen:introspection')(payload);
|
|
184
|
-
const response = await node_fetch_1.default(
|
|
189
|
+
const response = await (0, node_fetch_1.default)(serverUrl, {
|
|
185
190
|
method: 'POST',
|
|
186
191
|
headers: { 'Content-Type': 'application/json' },
|
|
187
192
|
body: payload,
|
|
@@ -201,9 +206,17 @@ exports.queryIntrospectionService = async (query) => {
|
|
|
201
206
|
}
|
|
202
207
|
if (json.errors) {
|
|
203
208
|
const compileError = (error) => {
|
|
204
|
-
var _a;
|
|
209
|
+
var _a, _b, _c;
|
|
205
210
|
return error.message +
|
|
206
|
-
|
|
211
|
+
// error.extensions.Message: DB introspection API (e.g. wrong password)
|
|
212
|
+
(((_a = error.extensions) === null || _a === void 0 ? void 0 : _a.Message) ? `: ${error.extensions.Message}` : '') +
|
|
213
|
+
// error.extensions.details: REST instrospection API (e.g. 401 / unauthorized)
|
|
214
|
+
(((_b = error.extensions) === null || _b === void 0 ? void 0 : _b.details)
|
|
215
|
+
? `: ${JSON.stringify(error.extensions.details)}`
|
|
216
|
+
: '') +
|
|
217
|
+
// error.extensions.cause: DB introspection API (e.g. --db-include=views-only and there are no views)
|
|
218
|
+
(((_c = error.extensions) === null || _c === void 0 ? void 0 : _c.cause)
|
|
219
|
+
? `: ${JSON.stringify(error.extensions.cause)}`
|
|
207
220
|
: '');
|
|
208
221
|
};
|
|
209
222
|
return { error: json.errors.map(compileError).join('\n') };
|
|
@@ -222,7 +235,9 @@ exports.queryIntrospectionService = async (query) => {
|
|
|
222
235
|
}
|
|
223
236
|
return { config, sdl };
|
|
224
237
|
};
|
|
225
|
-
exports.
|
|
238
|
+
exports.queryIntrospectionService = queryIntrospectionService;
|
|
239
|
+
const writeSdlAndConfig = async ({ name, source, mergeTypes = false, onConflict, response, }) => {
|
|
240
|
+
const { config, sdl } = response;
|
|
226
241
|
// write out the generated config and schema files
|
|
227
242
|
const tmp = path.join(os.tmpdir(), `stepzen-introspection-${Date.now()}`);
|
|
228
243
|
fs.ensureDirSync(tmp);
|
|
@@ -240,8 +255,16 @@ exports.writeSdlAndConfig = async (name, source, onConflict, { config, sdl }) =>
|
|
|
240
255
|
answers: {},
|
|
241
256
|
output: null,
|
|
242
257
|
silent: true,
|
|
243
|
-
mergeTypes
|
|
258
|
+
mergeTypes,
|
|
244
259
|
onConflict,
|
|
245
260
|
});
|
|
246
261
|
return { outPath: result };
|
|
247
262
|
};
|
|
263
|
+
exports.writeSdlAndConfig = writeSdlAndConfig;
|
|
264
|
+
const overrideDefaults = (questions, defaultAnswers) => {
|
|
265
|
+
return questions.map(question => {
|
|
266
|
+
const def = (0, lodash_1.get)(defaultAnswers, question.name);
|
|
267
|
+
return def === undefined ? question : Object.assign(Object.assign({}, question), { default: def });
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
exports.overrideDefaults = overrideDefaults;
|
package/lib/generate/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export declare type
|
|
2
|
-
schema: string;
|
|
1
|
+
export declare type CommonImportOptions = {
|
|
3
2
|
name?: string;
|
|
4
|
-
onConflict: 'overwrite' | 'append';
|
|
5
3
|
source: string;
|
|
4
|
+
onConflict: 'overwrite' | 'append';
|
|
5
|
+
};
|
|
6
|
+
export declare type GenerateOptions = CommonImportOptions & {
|
|
7
|
+
schema: string;
|
|
6
8
|
preAnswered?: {
|
|
7
9
|
[question: string]: string;
|
|
8
10
|
};
|
package/lib/generate/index.js
CHANGED
|
@@ -19,7 +19,7 @@ exports.default = async ({ schema, name, onConflict, source, preAnswered = {}, }
|
|
|
19
19
|
// Start downloading
|
|
20
20
|
core_1.CliUx.ux.action.start('Downloading from StepZen...');
|
|
21
21
|
// Get the generator configuration
|
|
22
|
-
const configure = await helpers_1.getConfiguration(schema, answers);
|
|
22
|
+
const configure = await (0, helpers_1.getConfiguration)(schema, answers);
|
|
23
23
|
if (((_a = configure === null || configure === void 0 ? void 0 : configure.questions) === null || _a === void 0 ? void 0 : _a.length) ||
|
|
24
24
|
((configure === null || configure === void 0 ? void 0 : configure.status) && configure.status >= 0)) {
|
|
25
25
|
generator = {
|
|
@@ -44,7 +44,7 @@ exports.default = async ({ schema, name, onConflict, source, preAnswered = {}, }
|
|
|
44
44
|
// Get the API templates repository
|
|
45
45
|
let templates;
|
|
46
46
|
if (generator === undefined) {
|
|
47
|
-
templates = await helpers_1.getTemplates();
|
|
47
|
+
templates = await (0, helpers_1.getTemplates)();
|
|
48
48
|
if (fs.existsSync(`${templates}/${schema}`)) {
|
|
49
49
|
const file = path.join(templates, schema, 'stepzen.config.json');
|
|
50
50
|
const config = fs.readFileSync(file, 'utf8');
|
|
@@ -67,19 +67,19 @@ exports.default = async ({ schema, name, onConflict, source, preAnswered = {}, }
|
|
|
67
67
|
throw new errors_1.CLIError(`Cannot find the schema ${schema}`);
|
|
68
68
|
}
|
|
69
69
|
else if (generator.type === 'generator') {
|
|
70
|
-
result = await helpers_1.askGeneratorQuestions(schema, generator, answers);
|
|
70
|
+
result = await (0, helpers_1.askGeneratorQuestions)(schema, generator, answers);
|
|
71
71
|
}
|
|
72
72
|
else if (generator.type === 'template') {
|
|
73
|
-
result = await helpers_1.askTemplateQuestions(schema, generator, answers);
|
|
73
|
+
result = await (0, helpers_1.askTemplateQuestions)(schema, generator, answers);
|
|
74
74
|
}
|
|
75
75
|
generator.answers = result;
|
|
76
|
-
answers = lodash_1.merge(answers, result);
|
|
76
|
+
answers = (0, lodash_1.merge)(answers, result);
|
|
77
77
|
// We now have all the answers! Generate schemas
|
|
78
78
|
console.log();
|
|
79
79
|
core_1.CliUx.ux.action.start('Generating schemas...');
|
|
80
80
|
let files;
|
|
81
81
|
if (generator.type === 'generator') {
|
|
82
|
-
files = await helpers_1.createGeneratorFiles(schema, generator);
|
|
82
|
+
files = await (0, helpers_1.createGeneratorFiles)(schema, generator);
|
|
83
83
|
tempFiles.push(files);
|
|
84
84
|
}
|
|
85
85
|
else {
|