stepzen 0.13.0-beta.2 → 0.14.0-beta.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.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/lib/commands/deploy.d.ts +1 -0
  3. package/lib/commands/import.d.ts +1 -0
  4. package/lib/commands/import.js +4 -12
  5. package/lib/commands/init.d.ts +1 -0
  6. package/lib/commands/lint.d.ts +1 -0
  7. package/lib/commands/list.d.ts +2 -0
  8. package/lib/commands/login.d.ts +1 -0
  9. package/lib/commands/login.js +10 -9
  10. package/lib/commands/logout.d.ts +2 -0
  11. package/lib/commands/logout.js +1 -1
  12. package/lib/commands/start.d.ts +1 -0
  13. package/lib/commands/start.js +3 -4
  14. package/lib/commands/transpile.d.ts +1 -0
  15. package/lib/commands/upload.d.ts +1 -0
  16. package/lib/commands/upload.js +13 -4
  17. package/lib/commands/validate.d.ts +2 -0
  18. package/lib/commands/whoami.d.ts +2 -0
  19. package/lib/commands/whoami.js +2 -2
  20. package/lib/generate/helpers.d.ts +0 -4
  21. package/lib/generate/helpers.js +27 -110
  22. package/lib/generate/index.js +5 -5
  23. package/lib/hooks/prerun/{ensure-api-key.d.ts → ensure-config-file.d.ts} +0 -0
  24. package/lib/hooks/prerun/ensure-config-file.js +28 -0
  25. package/lib/shared/actions.d.ts +1 -1
  26. package/lib/shared/actions.js +5 -18
  27. package/lib/shared/configuration.d.ts +24 -5
  28. package/lib/shared/configuration.js +92 -34
  29. package/lib/shared/constants.d.ts +2 -2
  30. package/lib/shared/constants.js +4 -3
  31. package/lib/shared/curl-parser.js +22 -8
  32. package/lib/shared/path-params-parser.js +17 -9
  33. package/lib/shared/stepzen-sdk.d.ts +14 -14
  34. package/lib/shared/stepzen-sdk.js +25 -17
  35. package/lib/shared/types.d.ts +14 -2
  36. package/lib/shared/utils.d.ts +0 -2
  37. package/lib/shared/utils.js +1 -50
  38. package/lib/shared/zen-command.d.ts +6 -5
  39. package/lib/shared/zen-command.js +28 -8
  40. package/lib/start/deploy.js +4 -4
  41. package/oclif.manifest.json +1 -1
  42. package/package.json +6 -6
  43. package/lib/hooks/prerun/ensure-api-key.js +0 -8
@@ -1,5 +1,24 @@
1
- import { MachineConfiguration } from './types';
2
- export declare const readConfiguration: () => MachineConfiguration | null;
3
- export declare const importConfiguration: (filepath: string) => MachineConfiguration;
4
- export declare const removeConfigurationFromLoginFile: () => boolean;
5
- export declare const writeConfigurationToLoginFile: (configuration: MachineConfiguration) => MachineConfiguration;
1
+ import { LoggedInMachineConfiguration, LoggedOutMachineConfiguration, MachineConfiguration, StepZenCredentials } from './types';
2
+ /**
3
+ * Ensure that the `stepzen-config.yaml` file exists and has valid content.
4
+ * Cover 3 cases:
5
+ * - file does not exist (this is the first time the CLI is run)
6
+ * -> initialize the config file and add a UUID into it
7
+ * - file exists but does not include a UUID (it was created by an earlier
8
+ * version of the CLI)
9
+ * -> add a UUID into the existing config file
10
+ * - file exists, has stepzen credentials, but does not include an API key
11
+ * (it was created by an earlier version of the CLI)
12
+ * -> either fetch the API key from StepZen or remove logged in credentials
13
+ *
14
+ * @param {*} maybeConfiguration raw contents of the configuration file
15
+ */
16
+ export declare const ensureValidConfiguration: (maybeConfiguration: Record<string, any> | null) => Promise<{
17
+ configuration: MachineConfiguration;
18
+ modified: boolean;
19
+ }>;
20
+ export declare const importConfiguration: (filepath: string) => Promise<Record<string, any>>;
21
+ export declare const readConfiguration: () => Promise<MachineConfiguration>;
22
+ export declare const writeConfiguration: (configuration: MachineConfiguration) => Promise<MachineConfiguration>;
23
+ export declare const writeCredentialsToConfigFile: (credentials: StepZenCredentials) => Promise<LoggedInMachineConfiguration>;
24
+ export declare const removeCredentialsFromConfigFile: () => Promise<LoggedOutMachineConfiguration>;
@@ -1,61 +1,106 @@
1
1
  "use strict";
2
2
  // Copyright (c) 2020,2021,2022, StepZen, Inc.
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.writeConfigurationToLoginFile = exports.removeConfigurationFromLoginFile = exports.importConfiguration = exports.readConfiguration = void 0;
4
+ exports.removeCredentialsFromConfigFile = exports.writeCredentialsToConfigFile = exports.writeConfiguration = exports.readConfiguration = exports.importConfiguration = exports.ensureValidConfiguration = void 0;
5
5
  // This file contains methods for managing configuration
6
6
  const errors_1 = require("@oclif/errors");
7
7
  const debug = require("debug");
8
8
  const fs = require("fs");
9
+ const crypto = require("crypto");
9
10
  const path = require("path");
10
11
  const yaml = require("yaml");
12
+ const stepzen_sdk_1 = require("./stepzen-sdk");
11
13
  const constants_1 = require("./constants");
12
- exports.readConfiguration = () => {
13
- try {
14
- let configuration;
15
- // If the configuration comes from an env var, use it
16
- if (process.env.STEPZEN_CONFIG_CONTENT) {
17
- configuration = process.env.STEPZEN_CONFIG_CONTENT;
14
+ const configFilePath = path.join(constants_1.STEPZEN_CONFIG_DIRECTORY, constants_1.STEPZEN_CONFIG_FILE);
15
+ /**
16
+ * Ensure that the `stepzen-config.yaml` file exists and has valid content.
17
+ * Cover 3 cases:
18
+ * - file does not exist (this is the first time the CLI is run)
19
+ * -> initialize the config file and add a UUID into it
20
+ * - file exists but does not include a UUID (it was created by an earlier
21
+ * version of the CLI)
22
+ * -> add a UUID into the existing config file
23
+ * - file exists, has stepzen credentials, but does not include an API key
24
+ * (it was created by an earlier version of the CLI)
25
+ * -> either fetch the API key from StepZen or remove logged in credentials
26
+ *
27
+ * @param {*} maybeConfiguration raw contents of the configuration file
28
+ */
29
+ exports.ensureValidConfiguration = async (maybeConfiguration) => {
30
+ let modified = false;
31
+ const configuration = Object.assign({}, maybeConfiguration);
32
+ // ensure configuration exists
33
+ if (!maybeConfiguration) {
34
+ modified = true;
35
+ }
36
+ // ensure configuration has a UUID
37
+ if (!configuration.uuid) {
38
+ configuration.uuid = crypto.randomUUID();
39
+ debug('stepzen:configuration')(`Generated a new machine UUID: ${configuration.uuid}`);
40
+ modified = true;
41
+ }
42
+ // ensure a logged-in configuration includes an API key
43
+ if (configuration.account && !configuration.apikey) {
44
+ try {
45
+ debug('stepzen:configuration')(`Fetching an API key for account ${configuration.account}`);
46
+ const credentials = await stepzen_sdk_1.default.login(configuration.adminkey, configuration.account);
47
+ configuration.apikey = credentials.apikey;
18
48
  }
19
- else {
20
- // Read the stored configuration, if it exists.
21
- const file = path.join(constants_1.STEPZEN_CONFIG_DIRECTORY, constants_1.STEPZEN_CONFIG_FILE);
22
- configuration = fs.readFileSync(file, 'utf8');
49
+ catch (error) {
50
+ if (error instanceof Error &&
51
+ error.message.includes('Your credentials are invalid')) {
52
+ debug('stepzen:configuration')(`Removing the stored account credentials because logging in failed. ${error}`);
53
+ delete configuration.account;
54
+ delete configuration.adminkey;
55
+ delete configuration.apikey;
56
+ }
57
+ else {
58
+ // ignore other errors
59
+ }
23
60
  }
24
- // Parse the yaml into an Object.
25
- const parsed = yaml.parse(configuration);
26
- debug('stepzen:configuration')(parsed);
27
- return parsed;
28
- }
29
- catch (_a) {
30
- return null;
61
+ modified = true;
31
62
  }
63
+ return {
64
+ configuration: configuration,
65
+ modified,
66
+ };
32
67
  };
33
- exports.importConfiguration = (filepath) => {
68
+ exports.importConfiguration = async (filepath) => {
34
69
  if (!fs.existsSync(filepath)) {
35
70
  throw new errors_1.CLIError('Configuration file does not exist');
36
71
  }
37
- const configuration = fs.readFileSync(filepath, 'utf8');
72
+ const content = fs.readFileSync(filepath, 'utf8');
38
73
  try {
39
- const parsed = yaml.parse(configuration);
40
- debug('stepzen:configuration')(parsed);
41
- return parsed;
74
+ return yaml.parse(content);
42
75
  }
43
76
  catch (_a) {
44
77
  throw new errors_1.CLIError('Configuration file is not valid yaml');
45
78
  }
46
79
  };
47
- exports.removeConfigurationFromLoginFile = () => {
48
- try {
49
- // Remove the configuration file
50
- const file = path.join(constants_1.STEPZEN_CONFIG_DIRECTORY, constants_1.STEPZEN_CONFIG_FILE);
51
- fs.unlinkSync(file);
52
- return true;
80
+ exports.readConfiguration = async () => {
81
+ let maybeConfiguration = null;
82
+ // If the configuration comes from an env var, use it
83
+ if (process.env.STEPZEN_CONFIG_CONTENT) {
84
+ try {
85
+ maybeConfiguration = yaml.parse(process.env.STEPZEN_CONFIG_CONTENT);
86
+ }
87
+ catch (error) {
88
+ debug('stepzen:configuration')(`Could not parse the STEPZEN_CONFIG_CONTENT env var as YAML: ${error}`);
89
+ }
53
90
  }
54
- catch (_a) {
55
- return false;
91
+ else {
92
+ try {
93
+ maybeConfiguration = await exports.importConfiguration(configFilePath);
94
+ }
95
+ catch (error) {
96
+ debug('stepzen:configuration')(`Could not read the config file at ${configFilePath}: ${error}`);
97
+ }
56
98
  }
99
+ const { configuration } = await exports.ensureValidConfiguration(maybeConfiguration);
100
+ debug('stepzen:configuration')(configuration);
101
+ return configuration;
57
102
  };
58
- exports.writeConfigurationToLoginFile = (configuration) => {
103
+ exports.writeConfiguration = async (configuration) => {
59
104
  // Generate YAML from the configuration
60
105
  const content = yaml.stringify(configuration);
61
106
  // Check that the configuration directory exists. If not, create it.
@@ -63,7 +108,20 @@ exports.writeConfigurationToLoginFile = (configuration) => {
63
108
  fs.mkdirSync(constants_1.STEPZEN_CONFIG_DIRECTORY);
64
109
  }
65
110
  // Write the configuration file. Overwrites if it already exists.
66
- const file = path.join(constants_1.STEPZEN_CONFIG_DIRECTORY, constants_1.STEPZEN_CONFIG_FILE);
67
- fs.writeFileSync(file, content, { mode: '600' });
111
+ fs.writeFileSync(configFilePath, content, { mode: '600' });
112
+ return exports.readConfiguration();
113
+ };
114
+ exports.writeCredentialsToConfigFile = async (credentials) => {
115
+ const oldConfig = await exports.readConfiguration();
116
+ const newConfig = Object.assign(Object.assign({}, oldConfig), credentials);
117
+ const writtenConfig = await exports.writeConfiguration(newConfig);
118
+ return Object.assign(Object.assign({}, newConfig), writtenConfig);
119
+ };
120
+ exports.removeCredentialsFromConfigFile = async () => {
121
+ const configuration = await exports.readConfiguration();
122
+ delete configuration.account;
123
+ delete configuration.apikey;
124
+ delete configuration.adminkey;
125
+ await exports.writeConfiguration(configuration);
68
126
  return configuration;
69
127
  };
@@ -5,11 +5,11 @@ export declare const STEPZEN_DOMAIN: string;
5
5
  export declare const STEPZEN_SERVER_URL: string;
6
6
  export declare const STEPZEN_GENERATOR_ENGINES_SCHEMA: string;
7
7
  export declare const STEPZEN_GENERATOR_ENGINES_ENDPOINT = "stepzen-generator/engines";
8
- export declare const STEPZEN_DIRECT_GENERATOR_ENGINES_URL: string | undefined;
8
+ export declare const STEPZEN_DIRECT_GENERATOR_ENGINES_URL: string;
9
9
  export declare const STEPZEN_API_TEMPLATES_REPOSITORY = "https://github.com/steprz/stepzen-schemas";
10
10
  export declare const ADMIN_DEPLOY_URL = "/cli/admin/deploy";
11
11
  export declare const ADMIN_LIST_URL = "/cli/admin/list";
12
12
  export declare const ADMIN_UPLOAD_URL = "/cli/admin/upload";
13
- export declare const ADMIN_VERIFY_URL = "/cli/admin/verify";
13
+ export declare const ADMIN_ACCOUNT_URL = "/cli/admin/account";
14
14
  export declare const STEPZEN_JSON2SDL_SERVER_URL: string;
15
15
  export declare const STEPZEN_DISCORD_URL = "https://discord.gg/9k2VdPn2FR";
@@ -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.STEPZEN_DISCORD_URL = exports.STEPZEN_JSON2SDL_SERVER_URL = exports.ADMIN_VERIFY_URL = exports.ADMIN_UPLOAD_URL = exports.ADMIN_LIST_URL = exports.ADMIN_DEPLOY_URL = exports.STEPZEN_API_TEMPLATES_REPOSITORY = exports.STEPZEN_DIRECT_GENERATOR_ENGINES_URL = exports.STEPZEN_GENERATOR_ENGINES_ENDPOINT = exports.STEPZEN_GENERATOR_ENGINES_SCHEMA = exports.STEPZEN_SERVER_URL = exports.STEPZEN_DOMAIN = exports.STEPZEN_CONFIG_FILE = exports.STEPZEN_LAST_UPDATE_CHECK_TIMESTAMP = exports.STEPZEN_CONFIG_DIRECTORY = void 0;
4
+ exports.STEPZEN_DISCORD_URL = exports.STEPZEN_JSON2SDL_SERVER_URL = exports.ADMIN_ACCOUNT_URL = exports.ADMIN_UPLOAD_URL = exports.ADMIN_LIST_URL = exports.ADMIN_DEPLOY_URL = exports.STEPZEN_API_TEMPLATES_REPOSITORY = exports.STEPZEN_DIRECT_GENERATOR_ENGINES_URL = exports.STEPZEN_GENERATOR_ENGINES_ENDPOINT = exports.STEPZEN_GENERATOR_ENGINES_SCHEMA = exports.STEPZEN_SERVER_URL = exports.STEPZEN_DOMAIN = exports.STEPZEN_CONFIG_FILE = exports.STEPZEN_LAST_UPDATE_CHECK_TIMESTAMP = exports.STEPZEN_CONFIG_DIRECTORY = void 0;
5
5
  // This file contains constants and all magic strings
6
6
  const dotenv = require("dotenv");
7
7
  const os = require("os");
@@ -24,14 +24,15 @@ exports.STEPZEN_GENERATOR_ENGINES_SCHEMA = ENV_VAR_STEPZEN_GENERATOR_ENGINES_SCH
24
24
  // Generator Engines schema: target API endpoint
25
25
  exports.STEPZEN_GENERATOR_ENGINES_ENDPOINT = 'stepzen-generator/engines';
26
26
  // If defined, call the generator engines cloud function directly, skipping zenctl
27
- exports.STEPZEN_DIRECT_GENERATOR_ENGINES_URL = ENV_VAR_STEPZEN_DIRECT_GENERATOR_ENGINES_URL;
27
+ exports.STEPZEN_DIRECT_GENERATOR_ENGINES_URL = ENV_VAR_STEPZEN_DIRECT_GENERATOR_ENGINES_URL ||
28
+ 'https://us-central1-stepzen-functions.cloudfunctions.net/generator-engine';
28
29
  // API Templates repository
29
30
  exports.STEPZEN_API_TEMPLATES_REPOSITORY = 'https://github.com/steprz/stepzen-schemas';
30
31
  // Paths to the endpoints used (only for tests)
31
32
  exports.ADMIN_DEPLOY_URL = '/cli/admin/deploy';
32
33
  exports.ADMIN_LIST_URL = '/cli/admin/list';
33
34
  exports.ADMIN_UPLOAD_URL = '/cli/admin/upload';
34
- exports.ADMIN_VERIFY_URL = '/cli/admin/verify';
35
+ exports.ADMIN_ACCOUNT_URL = '/cli/admin/account';
35
36
  exports.STEPZEN_JSON2SDL_SERVER_URL = ENV_VAR_STEPZEN_JSON2SDL_SERVER_URL ||
36
37
  'https://jsonintrospection-ng-prod-xynkgeaaaa-uc.a.run.app';
37
38
  exports.STEPZEN_DISCORD_URL = 'https://discord.gg/9k2VdPn2FR';
@@ -87,6 +87,17 @@ const parseMethodFlag = (value, partialCurlArgs) => {
87
87
  result: Object.assign(Object.assign({}, partialCurlArgs), { method }),
88
88
  };
89
89
  };
90
+ const parseURLFlag = (value, partialCurlArgs) => {
91
+ if (partialCurlArgs.url) {
92
+ return {
93
+ error: `Multiple URLs are not currently supported by StepZen CLI (${value}).` +
94
+ ` If this is a blocker for you, please let us know on Discord (${constants_1.STEPZEN_DISCORD_URL})`,
95
+ };
96
+ }
97
+ return {
98
+ result: Object.assign(Object.assign({}, partialCurlArgs), { url: value }),
99
+ };
100
+ };
90
101
  const flags = [
91
102
  {
92
103
  matches: ['-H', '--header'],
@@ -100,6 +111,10 @@ const flags = [
100
111
  matches: ['-X', '--request'],
101
112
  parse: parseMethodFlag,
102
113
  },
114
+ {
115
+ matches: ['--url'],
116
+ parse: parseURLFlag,
117
+ },
103
118
  ];
104
119
  const tryMatchCurlFlag = (matches, argv, i) => {
105
120
  for (const match of matches) {
@@ -155,7 +170,7 @@ exports.parseCurlArgv = (argv) => {
155
170
  continue;
156
171
  }
157
172
  if ('error' in matcherResult) {
158
- // flag matched but it requies a value which is missing
173
+ // flag matched but it requires a value which is missing
159
174
  return matcherResult;
160
175
  }
161
176
  const parserResult = flag.parse(matcherResult.value, result, matcherResult.match);
@@ -174,14 +189,13 @@ exports.parseCurlArgv = (argv) => {
174
189
  };
175
190
  }
176
191
  }
177
- else if (result.url) {
178
- return {
179
- error: `Multiple URLs are not currently supported by StepZen CLI (${argv[i]}).` +
180
- ` If this is a blocker for you, please let us know on Discord (${constants_1.STEPZEN_DISCORD_URL})`,
181
- };
182
- }
183
192
  else {
184
- result.url = argv[i];
193
+ // The only curl argument that's not a flag is the URL
194
+ const resultOrError = parseURLFlag(argv[i], result, '');
195
+ if ('error' in resultOrError) {
196
+ return resultOrError;
197
+ }
198
+ result = resultOrError.result;
185
199
  }
186
200
  }
187
201
  if (!result.url) {
@@ -4,6 +4,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.parsePathParamsPattern = exports.formatPatternDiffWithPath = void 0;
5
5
  const chalk = require("chalk");
6
6
  const pathParamRegex = /^\$[_A-Za-z]\w*$/;
7
+ // in a literal segment, $ should be escaped as $$
8
+ const pathSegmentRegex = /^([^$]|\$\$)+$/;
7
9
  exports.formatPatternDiffWithPath = (patternSegments, pathSegments) => {
8
10
  let hasErrors = false;
9
11
  const diff = [];
@@ -13,12 +15,9 @@ exports.formatPatternDiffWithPath = (patternSegments, pathSegments) => {
13
15
  diff.push(chalk.red(`< ${patternSegment} >`));
14
16
  hasErrors = true;
15
17
  }
16
- else if (patternSegment.charAt(0) === '$') {
17
- diff.push(patternSegment);
18
- }
19
- else {
18
+ else if (pathSegmentRegex.test(patternSegment)) {
20
19
  const pathSegment = pathSegments[i];
21
- if (pathSegment === patternSegment) {
20
+ if (pathSegment === patternSegment.replace('$$', '$')) {
22
21
  diff.push(pathSegment);
23
22
  }
24
23
  else {
@@ -26,6 +25,13 @@ exports.formatPatternDiffWithPath = (patternSegments, pathSegments) => {
26
25
  hasErrors = true;
27
26
  }
28
27
  }
28
+ else {
29
+ // If the path segment contains some unescaped (single) $ chars,
30
+ // interpret it as a pattern for now. An error will be reported
31
+ // later (in parsePathParamsPattern) if it doesn't match
32
+ // pathParamRegex (starts with $)
33
+ diff.push(patternSegment);
34
+ }
29
35
  }
30
36
  for (let i = patternSegments.length; i < pathSegments.length; i++) {
31
37
  diff.push(chalk.magenta(`< ${pathSegments[i]} >`));
@@ -52,22 +58,24 @@ exports.parsePathParamsPattern = (url, pathParamsPattern) => {
52
58
  error: `Path parameters do not align with the URL path: /${maybeDiff}`,
53
59
  };
54
60
  }
55
- const invalidParameterSegments = patternSegments.filter(segment => segment.charAt(0) === '$' && !pathParamRegex.test(segment));
61
+ const invalidParameterSegments = patternSegments.filter(segment => !pathSegmentRegex.test(segment) && !pathParamRegex.test(segment));
56
62
  if (invalidParameterSegments.length > 0) {
57
63
  return {
58
64
  error: `The path parameter name '${invalidParameterSegments[0]}' is not` +
59
65
  ` allowed. Path parameter names should be valid GraphQL identifiers` +
60
- ` prefixed with $ (dollar sign).`,
66
+ ` prefixed with $ (dollar sign). $ in literal path segments must be` +
67
+ ` escaped as $$.`,
61
68
  };
62
69
  }
63
- return patternSegments
70
+ const retval = patternSegments
64
71
  .map((segment, index) => ({
65
72
  index,
66
73
  name: segment,
67
74
  }))
68
- .filter(({ name }) => name.charAt(0) === '$')
75
+ .filter(({ name }) => pathParamRegex.test(name))
69
76
  .map(({ index, name }) => ({
70
77
  index,
71
78
  name: name.slice(1),
72
79
  }));
80
+ return retval;
73
81
  };
@@ -1,14 +1,14 @@
1
+ import { StepZenCredentials } from './types';
1
2
  declare const stepzen: {
2
- login: (adminkey: string, account?: string) => Promise<{
3
- account: string;
4
- adminkey: string;
5
- }>;
6
- createAnonymousAccount: () => {
7
- account: string;
8
- adminkey: string;
9
- };
3
+ login: (adminkey: string, account?: string) => Promise<StepZenCredentials>;
4
+ createAnonymousAccount: (uuid: string) => Promise<StepZenCredentials>;
10
5
  verify: (account: string, adminkey: string) => Promise<boolean>;
11
- client: (options: Pick<import("@stepzen/sdk").StepZenAccount, "account" | "adminkey"> & Partial<import("@stepzen/sdk").StepZenAccount>) => Promise<{
6
+ client: (options: import("@stepzen/sdk/lib/client").AnonymousClientOptions | import("@stepzen/sdk/lib/client").UserCredentialsClientOptions) => Promise<{
7
+ readonly credentials: {
8
+ account: string;
9
+ adminkey: string;
10
+ apikey: string;
11
+ };
12
12
  account: () => Promise<{
13
13
  account: string;
14
14
  apikey: string;
@@ -19,14 +19,14 @@ declare const stepzen: {
19
19
  deploy: (destination: string, properties: {
20
20
  configurationsets?: string[] | undefined;
21
21
  schema: string;
22
- }) => Promise<import("@stepzen/sdk").ZenCtlResponse>;
22
+ }) => Promise<import("@stepzen/sdk/lib/client").ZenCtlResponse>;
23
23
  list: {
24
- configurationsets: () => Promise<import("@stepzen/sdk").ZenCtlResponse>;
25
- schemas: () => Promise<import("@stepzen/sdk").ZenCtlResponse>;
24
+ configurationsets: () => Promise<import("@stepzen/sdk/lib/client").ZenCtlResponse>;
25
+ schemas: () => Promise<import("@stepzen/sdk/lib/client").ZenCtlResponse>;
26
26
  };
27
27
  upload: {
28
- configurationset: (destination: string, file: string) => Promise<import("@stepzen/sdk").ZenCtlResponse>;
29
- schema: (destination: string, directory: string) => Promise<import("@stepzen/sdk").ZenCtlResponse>;
28
+ configurationset: (destination: string, file: string) => Promise<import("@stepzen/sdk/lib/client").ZenCtlResponse>;
29
+ schema: (destination: string, directory: string) => Promise<import("@stepzen/sdk/lib/client").ZenCtlResponse>;
30
30
  };
31
31
  }>;
32
32
  };
@@ -3,26 +3,34 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const errors_1 = require("@oclif/errors");
5
5
  const sdk_1 = require("@stepzen/sdk");
6
+ const constants_1 = require("./constants");
6
7
  const { version } = require('../../package.json');
7
8
  const stepzen = Object.assign(Object.assign({}, sdk_1.init({ appName: `stepzen-cli/${version}` })), { login: async (adminkey, account = adminkey.split(':')[0]) => {
8
- // Check whether the account and admin key exist and are correct by calling
9
- // the stepzen admin api.
10
- const isValidConfiguration = await stepzen.verify(account, adminkey);
11
- if (!isValidConfiguration) {
9
+ try {
10
+ const client = await stepzen.client({
11
+ account,
12
+ adminkey,
13
+ domain: constants_1.STEPZEN_DOMAIN,
14
+ server: constants_1.STEPZEN_SERVER_URL,
15
+ });
16
+ return client.credentials;
17
+ }
18
+ catch (error) {
12
19
  // Exit, with error
13
- throw new errors_1.CLIError('We are unable to verify your account details. Could you please check them?');
20
+ throw new errors_1.CLIError('We are unable to verify your account details. Could you please check them?' +
21
+ ` (${error})`);
22
+ }
23
+ }, createAnonymousAccount: async (uuid) => {
24
+ try {
25
+ const client = await stepzen.client({
26
+ publicAccountToken: uuid,
27
+ domain: constants_1.STEPZEN_DOMAIN,
28
+ server: constants_1.STEPZEN_SERVER_URL,
29
+ });
30
+ return client.credentials;
31
+ }
32
+ catch (error) {
33
+ throw new errors_1.CLIError(`Could not create a public account (${error})`);
14
34
  }
15
- return {
16
- account,
17
- adminkey,
18
- };
19
- }, createAnonymousAccount: () => {
20
- const anonAdminKey = process.env.STEPZEN_ANONYMOUS_ADMINKEY ||
21
- // LATER: call the actual API (pending https://github.com/steprz/zen/issues/5545)
22
- 'test::steprz.io+666::test';
23
- return {
24
- account: anonAdminKey.split(':')[0],
25
- adminkey: anonAdminKey,
26
- };
27
35
  } });
28
36
  exports.default = stepzen;
@@ -1,8 +1,20 @@
1
- export interface MachineConfiguration {
1
+ export interface StepZenCredentials {
2
2
  account: string;
3
3
  adminkey: string;
4
- apikey?: string;
4
+ apikey: string;
5
5
  }
6
+ export interface LoggedOutMachineConfiguration {
7
+ uuid: string;
8
+ }
9
+ export declare type LoggedInMachineConfiguration = LoggedOutMachineConfiguration & StepZenCredentials;
10
+ /**
11
+ * In-memory representation of the `~/.stepzen/stepzen-config.yaml`
12
+ * configuration file.
13
+ *
14
+ * If the user is not logged in, it has only a UUID of the CLI installation.
15
+ * If the user is logged in, it has also has the StepZen account credentials.
16
+ */
17
+ export declare type MachineConfiguration = LoggedInMachineConfiguration | LoggedOutMachineConfiguration;
6
18
  /**
7
19
  * On-disk representation of a workspace config file, `stepzen.config.json`
8
20
  */
@@ -1,6 +1,4 @@
1
- export declare const checkAuth: () => Promise<void>;
2
1
  export declare const clearConsole: () => void;
3
- export declare const ensureApiKey: () => Promise<void>;
4
2
  export declare const getDirectory: (d?: string | undefined) => string;
5
3
  export declare const getStepZenExtensions: () => Promise<string>;
6
4
  export declare const validateEndpoint: (endpoint: string) => any;
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  // Copyright (c) 2020,2021,2022, StepZen, Inc.
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.maskStepZenKey = exports.validateEndpoint = exports.getStepZenExtensions = exports.getDirectory = exports.ensureApiKey = exports.clearConsole = exports.checkAuth = void 0;
4
+ exports.maskStepZenKey = exports.validateEndpoint = exports.getStepZenExtensions = exports.getDirectory = exports.clearConsole = void 0;
5
5
  const errors_1 = require("@oclif/errors");
6
- const chalk = require("chalk");
7
6
  const debug = require("debug");
8
7
  const node_fetch_1 = require("node-fetch");
9
8
  const fs = require("fs");
@@ -11,60 +10,12 @@ const os = require("os");
11
10
  const path = require("path");
12
11
  const prettier = require("prettier");
13
12
  const constants_1 = require("./constants");
14
- const configuration_1 = require("./configuration");
15
- const stepzen_sdk_1 = require("./stepzen-sdk");
16
- exports.checkAuth = async () => {
17
- var _a;
18
- const configuration = configuration_1.readConfiguration();
19
- // If there is no configuration, you're not logged in
20
- if (!configuration) {
21
- return;
22
- }
23
- const details = configuration;
24
- // If the account is called 'test', return. It's a test.
25
- if (details.account === 'test') {
26
- return;
27
- }
28
- const isValidAccount = await stepzen_sdk_1.default.verify(details.account, details.adminkey);
29
- if (!isValidAccount) {
30
- if ((_a = details.account) === null || _a === void 0 ? void 0 : _a.endsWith('Playground')) {
31
- console.log(chalk.yellow(`
32
- ╔════════════════════════════════════════╗
33
- ║ Your playground account has expired! ║
34
- ║ Sign up for a full account: ║
35
- ║ www.stepzen.com ║
36
- ╚════════════════════════════════════════╝
37
- `));
38
- }
39
- else {
40
- console.log('Could not complete the request. Please check your authentication details are correct.');
41
- }
42
- // eslint-disable-next-line no-process-exit,unicorn/no-process-exit
43
- process.exit(1);
44
- }
45
- };
46
13
  exports.clearConsole = () => {
47
14
  process.stdout.write(
48
15
  // Taken from create-react-app
49
16
  // eslint-disable-next-line unicorn/no-hex-escape
50
17
  process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H');
51
18
  };
52
- exports.ensureApiKey = async () => {
53
- const configuration = configuration_1.readConfiguration();
54
- const details = configuration;
55
- if (details && !details.apikey) {
56
- debug('stepzen:account')(`Fetching API key for account ${details.account}`);
57
- try {
58
- const client = await stepzen_sdk_1.default.client(details);
59
- const response = await client.account();
60
- if ('apikey' in response) {
61
- details.apikey = response.apikey;
62
- await configuration_1.writeConfigurationToLoginFile(details);
63
- }
64
- }
65
- catch (_a) { }
66
- }
67
- };
68
19
  exports.getDirectory = (d = process.cwd()) => {
69
20
  let directory = d;
70
21
  // If it starts with `~`, expand this
@@ -1,14 +1,15 @@
1
- import { Command } from '@oclif/command';
2
- import { MachineConfiguration } from './types';
1
+ import { Command, flags } from '@oclif/command';
2
+ import { MachineConfiguration, StepZenCredentials } from './types';
3
3
  export declare abstract class ZenCommand extends Command {
4
4
  static flags: {
5
5
  'non-interactive': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
6
+ 'enable-login-prompt': flags.IOptionFlag<boolean | undefined>;
6
7
  };
7
8
  ensureStepZenAccount(): Promise<{
8
- configuration: MachineConfiguration;
9
+ configuration: import("./types").LoggedInMachineConfiguration;
9
10
  }>;
10
- promptUserToLogIn(): Promise<{
11
- configuration: MachineConfiguration;
11
+ promptUserToLogIn(uuid: string): Promise<{
12
+ configuration: MachineConfiguration & StepZenCredentials;
12
13
  }>;
13
14
  }
14
15
  export default ZenCommand;
@@ -3,21 +3,28 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.ZenCommand = void 0;
5
5
  const command_1 = require("@oclif/command");
6
+ const errors_1 = require("@oclif/errors");
6
7
  const inquirer = require("inquirer");
7
8
  const chalk = require("chalk");
8
9
  const configuration_1 = require("./configuration");
9
10
  const stepzen_sdk_1 = require("./stepzen-sdk");
10
11
  class ZenCommand extends command_1.Command {
11
12
  async ensureStepZenAccount() {
12
- const configuration = configuration_1.readConfiguration();
13
- if (configuration && configuration.account) {
13
+ const configuration = await configuration_1.readConfiguration();
14
+ if ('account' in configuration) {
14
15
  return {
15
16
  configuration,
16
17
  };
17
18
  }
18
- return this.promptUserToLogIn();
19
+ const TheCommand = this.constructor;
20
+ const { flags } = this.parse(TheCommand);
21
+ if (flags['enable-login-prompt']) {
22
+ return this.promptUserToLogIn(configuration.uuid);
23
+ }
24
+ throw new errors_1.CLIError('Could not find StepZen account credentials.' +
25
+ ' Please run `stepzen login` first.');
19
26
  }
20
- async promptUserToLogIn() {
27
+ async promptUserToLogIn(uuid) {
21
28
  this.log(chalk.bold(chalk.cyan('Welcome to StepZen CLI!')));
22
29
  this.log('');
23
30
  this.log(`Please log in with your StepZen account to make your GraphQL API private.` +
@@ -53,14 +60,14 @@ class ZenCommand extends command_1.Command {
53
60
  suffix: chalk.blue(` (available at ${chalk.bold('https://stepzen.com/account')})`),
54
61
  },
55
62
  ]);
56
- configuration = await stepzen_sdk_1.default.login(answers.adminkey);
57
- configuration_1.writeConfigurationToLoginFile(configuration);
63
+ const credentials = await stepzen_sdk_1.default.login(answers.adminkey);
64
+ configuration = await configuration_1.writeCredentialsToConfigFile(credentials);
58
65
  this.log('You have successfully logged in.');
59
66
  this.log('');
60
67
  }
61
68
  else {
62
- configuration = await stepzen_sdk_1.default.createAnonymousAccount();
63
- configuration_1.writeConfigurationToLoginFile(configuration);
69
+ const credentials = await stepzen_sdk_1.default.createAnonymousAccount(uuid);
70
+ configuration = await configuration_1.writeCredentialsToConfigFile(credentials);
64
71
  this.log(`We've created a temporary public account for you.\nAll endpoints` +
65
72
  ` deployed to this account will be automatically deleted after 24` +
66
73
  ` hours. You can log in with your regular StepZen account at any` +
@@ -76,5 +83,18 @@ ZenCommand.flags = {
76
83
  description: 'disable all interactive prompts',
77
84
  hidden: true,
78
85
  }),
86
+ // The flag type has to be `option` (not `boolean`) for `env` to take effect
87
+ 'enable-login-prompt': command_1.flags.option({
88
+ description: 'An (internal) feature flag to enable the "prompt user to log in"' +
89
+ ' feature for the users who run the CLI without being logged in. It' +
90
+ ' is intentially hidden and not documented because in the future' +
91
+ ' this feature will be enabled for all users and the flag will be' +
92
+ ' removed.',
93
+ hidden: true,
94
+ options: ['true', 'false'],
95
+ parse: value => Boolean(value),
96
+ default: false,
97
+ env: 'STEPZEN_ENABLE_LOGIN_PROMPT',
98
+ }),
79
99
  };
80
100
  exports.default = ZenCommand;