@webiny/cli 5.22.0 → 5.23.0-beta.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/CHANGELOG.md +40 -0
- package/commands/index.js +6 -0
- package/commands/wcp/api/getProjectEnvironmentBySlug.js +108 -0
- package/commands/wcp/api/getUser.js +94 -0
- package/commands/wcp/api/index.js +14 -0
- package/commands/wcp/api/updateUserLastActiveOn.js +28 -0
- package/commands/wcp/hooks.js +67 -0
- package/commands/wcp/index.js +5 -0
- package/commands/wcp/login.js +188 -0
- package/commands/wcp/project.js +207 -0
- package/package.json +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,46 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [5.23.0-beta.1](https://github.com/webiny/webiny-js/compare/v5.23.0-beta.0...v5.23.0-beta.1) (2022-02-14)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @webiny/cli
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [5.23.0-beta.0](https://github.com/webiny/webiny-js/compare/v5.22.1...v5.23.0-beta.0) (2022-02-13)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* check project ID ([fe56278](https://github.com/webiny/webiny-js/commit/fe562788ace11ae3b571aa39d06328bcd220b100))
|
|
20
|
+
* correct comment ([54c3686](https://github.com/webiny/webiny-js/commit/54c36860132ac4c6ee6f09cc4035223ba977c4f2))
|
|
21
|
+
* eslint ([ad11ead](https://github.com/webiny/webiny-js/commit/ad11ead640111993e0cf6fb97ff6395633239cca))
|
|
22
|
+
* remove redundant code ([d1dde23](https://github.com/webiny/webiny-js/commit/d1dde23233f04f09eae9fc42374752eb46f36512))
|
|
23
|
+
* update deps ([6879623](https://github.com/webiny/webiny-js/commit/6879623d98b04229f07796fd601f4a3f0f534c3b))
|
|
24
|
+
* use the right hooks ([318db7a](https://github.com/webiny/webiny-js/commit/318db7acb30a85fe15ad3f4082536a2bf7a52f22))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [5.22.1](https://github.com/webiny/webiny-js/compare/v5.22.1-beta.0...v5.22.1) (2022-01-29)
|
|
31
|
+
|
|
32
|
+
**Note:** Version bump only for package @webiny/cli
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## [5.22.1-beta.0](https://github.com/webiny/webiny-js/compare/v5.22.0...v5.22.1-beta.0) (2022-01-29)
|
|
39
|
+
|
|
40
|
+
**Note:** Version bump only for package @webiny/cli
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
6
46
|
# [5.22.0](https://github.com/webiny/webiny-js/compare/v5.22.0-beta.3...v5.22.0) (2022-01-24)
|
|
7
47
|
|
|
8
48
|
**Note:** Version bump only for package @webiny/cli
|
package/commands/index.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
const run = require("./run");
|
|
2
2
|
const telemetry = require("./telemetry");
|
|
3
|
+
const wcp = require("./wcp");
|
|
3
4
|
const upgrade = require("./upgrade");
|
|
4
5
|
|
|
5
6
|
module.exports.createCommands = async (yargs, context) => {
|
|
6
7
|
context.plugins.register(run, telemetry, upgrade);
|
|
7
8
|
|
|
9
|
+
// For now, only register WCP related commands if
|
|
10
|
+
// `WCP_APP_URL` and `WCP_API_URL` env vars are defined.
|
|
11
|
+
if (process.env.WCP_APP_URL && process.env.WCP_API_URL) {
|
|
12
|
+
context.plugins.register(wcp);
|
|
13
|
+
}
|
|
8
14
|
await context.loadUserPlugins();
|
|
9
15
|
|
|
10
16
|
context.plugins.byType("cli-command").forEach(plugin => {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const { localStorage, log } = require("@webiny/cli/utils");
|
|
2
|
+
const { request } = require("graphql-request");
|
|
3
|
+
|
|
4
|
+
const ENVIRONMENT_FIELDS = /* GraphQL */ `
|
|
5
|
+
fragment EnvironmentFields on Environment {
|
|
6
|
+
id
|
|
7
|
+
status
|
|
8
|
+
name
|
|
9
|
+
apiKey
|
|
10
|
+
org {
|
|
11
|
+
id
|
|
12
|
+
name
|
|
13
|
+
}
|
|
14
|
+
project {
|
|
15
|
+
id
|
|
16
|
+
name
|
|
17
|
+
}
|
|
18
|
+
user {
|
|
19
|
+
id
|
|
20
|
+
email
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const CREATE_ENVIRONMENT = /* GraphQL */ `
|
|
26
|
+
${ENVIRONMENT_FIELDS}
|
|
27
|
+
mutation CreateEnvironment(
|
|
28
|
+
$orgId: ID!
|
|
29
|
+
$projectId: ID!
|
|
30
|
+
$userId: ID
|
|
31
|
+
$data: CreateEnvironmentDataInput!
|
|
32
|
+
) {
|
|
33
|
+
projects {
|
|
34
|
+
createEnvironment(orgId: $orgId, projectId: $projectId, userId: $userId, data: $data) {
|
|
35
|
+
...EnvironmentFields
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
const GET_ENVIRONMENT = /* GraphQL */ `
|
|
42
|
+
${ENVIRONMENT_FIELDS}
|
|
43
|
+
query GetEnvironment(
|
|
44
|
+
$environmentId: ID
|
|
45
|
+
$orgId: ID
|
|
46
|
+
$projectId: ID
|
|
47
|
+
$userId: ID
|
|
48
|
+
$apiKey: String
|
|
49
|
+
) {
|
|
50
|
+
projects {
|
|
51
|
+
getEnvironment(
|
|
52
|
+
environmentId: $environmentId
|
|
53
|
+
orgId: $orgId
|
|
54
|
+
projectId: $projectId
|
|
55
|
+
userId: $userId
|
|
56
|
+
apiKey: $apiKey
|
|
57
|
+
) {
|
|
58
|
+
...EnvironmentFields
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
module.exports.getProjectEnvironmentBySlug = async ({
|
|
65
|
+
orgId,
|
|
66
|
+
projectId,
|
|
67
|
+
userId,
|
|
68
|
+
environmentSlug
|
|
69
|
+
}) => {
|
|
70
|
+
const pat = localStorage().get("wcpPat");
|
|
71
|
+
if (!pat) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`It seems you are not logged in. Please login using the ${log.error.hl(
|
|
74
|
+
"webiny login"
|
|
75
|
+
)} command.`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { WCP_API_URL } = require(".");
|
|
80
|
+
const headers = { authorization: pat };
|
|
81
|
+
return request(
|
|
82
|
+
WCP_API_URL,
|
|
83
|
+
GET_ENVIRONMENT,
|
|
84
|
+
{
|
|
85
|
+
orgId,
|
|
86
|
+
projectId,
|
|
87
|
+
userId,
|
|
88
|
+
environmentId: environmentSlug
|
|
89
|
+
},
|
|
90
|
+
headers
|
|
91
|
+
)
|
|
92
|
+
.then(async response => response.projects.getEnvironment)
|
|
93
|
+
.catch(() => {
|
|
94
|
+
return request(
|
|
95
|
+
WCP_API_URL,
|
|
96
|
+
CREATE_ENVIRONMENT,
|
|
97
|
+
{
|
|
98
|
+
orgId,
|
|
99
|
+
projectId,
|
|
100
|
+
userId,
|
|
101
|
+
data: {
|
|
102
|
+
name: environmentSlug
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
headers
|
|
106
|
+
).then(async response => response.projects.createEnvironment);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const { localStorage, log } = require("@webiny/cli/utils");
|
|
2
|
+
const { request } = require("graphql-request");
|
|
3
|
+
|
|
4
|
+
const GET_CURRENT_USER = /* GraphQL */ `
|
|
5
|
+
query GetUser {
|
|
6
|
+
users {
|
|
7
|
+
getCurrentUser {
|
|
8
|
+
id
|
|
9
|
+
firstName
|
|
10
|
+
lastName
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
const LIST_ORGS = /* GraphQL */ `
|
|
17
|
+
query ListOrgs {
|
|
18
|
+
orgs {
|
|
19
|
+
listOrgs {
|
|
20
|
+
data {
|
|
21
|
+
id
|
|
22
|
+
name
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const LIST_PROJECTS = /* GraphQL */ `
|
|
30
|
+
query ListProjects($orgId: ID!) {
|
|
31
|
+
projects {
|
|
32
|
+
listProjects(orgId: $orgId) {
|
|
33
|
+
data {
|
|
34
|
+
id
|
|
35
|
+
name
|
|
36
|
+
org {
|
|
37
|
+
id
|
|
38
|
+
name
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
let user;
|
|
47
|
+
module.exports.getUser = async () => {
|
|
48
|
+
if (user) {
|
|
49
|
+
return user;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const pat = localStorage().get("wcpPat");
|
|
53
|
+
if (!pat) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`It seems you are not logged in. Please login using the ${log.error.hl(
|
|
56
|
+
"webiny login"
|
|
57
|
+
)} command.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const { WCP_API_URL } = require(".");
|
|
63
|
+
const headers = { authorization: pat };
|
|
64
|
+
user = await request(WCP_API_URL, GET_CURRENT_USER, {}, headers).then(async response => {
|
|
65
|
+
const user = response.users.getCurrentUser;
|
|
66
|
+
|
|
67
|
+
const orgs = await request(WCP_API_URL, LIST_ORGS, {}, headers).then(async response => {
|
|
68
|
+
const orgs = response.orgs.listOrgs.data;
|
|
69
|
+
for (let i = 0; i < orgs.length; i++) {
|
|
70
|
+
const org = orgs[i];
|
|
71
|
+
org.projects = await request(
|
|
72
|
+
WCP_API_URL,
|
|
73
|
+
LIST_PROJECTS,
|
|
74
|
+
{ orgId: org.id },
|
|
75
|
+
headers
|
|
76
|
+
).then(response => response.projects.listProjects.data);
|
|
77
|
+
}
|
|
78
|
+
return orgs;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const projects = orgs.map(org => org.projects).flat();
|
|
82
|
+
|
|
83
|
+
return { ...user, orgs, projects };
|
|
84
|
+
});
|
|
85
|
+
} catch {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`It seems the personal access token is incorrect or does not exist. Please log out and again log in using the ${log.error.hl(
|
|
88
|
+
"yarn webiny login"
|
|
89
|
+
)} command.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return user;
|
|
94
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const WCP_APP_URL = process.env.WCP_APP_URL || "https://wcp.webiny.com";
|
|
2
|
+
const WCP_API_URL = process.env.WCP_API_URL || "https://api.wcp.webiny.com/graphql";
|
|
3
|
+
|
|
4
|
+
const { getUser } = require("./getUser");
|
|
5
|
+
const { getProjectEnvironmentBySlug } = require("./getProjectEnvironmentBySlug");
|
|
6
|
+
const { updateUserLastActiveOn } = require("./updateUserLastActiveOn");
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
getUser,
|
|
10
|
+
getProjectEnvironmentBySlug,
|
|
11
|
+
updateUserLastActiveOn,
|
|
12
|
+
WCP_APP_URL,
|
|
13
|
+
WCP_API_URL
|
|
14
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const { request } = require("graphql-request");
|
|
2
|
+
const { localStorage, log } = require("@webiny/cli/utils");
|
|
3
|
+
|
|
4
|
+
const UPDATE_LAST_ACTIVE_TO_NOW = /* GraphQL */ `
|
|
5
|
+
mutation UpdateLastActiveToNow {
|
|
6
|
+
users {
|
|
7
|
+
updateLastActiveToNow {
|
|
8
|
+
id
|
|
9
|
+
lastActiveOn
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
module.exports.updateUserLastActiveOn = async () => {
|
|
16
|
+
const pat = localStorage().get("wcpPat");
|
|
17
|
+
if (!pat) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`It seems you are not logged in. Please login using the ${log.error.hl(
|
|
20
|
+
"webiny login"
|
|
21
|
+
)} command.`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { WCP_API_URL } = require(".");
|
|
26
|
+
const headers = { authorization: pat };
|
|
27
|
+
return request(WCP_API_URL, UPDATE_LAST_ACTIVE_TO_NOW, {}, headers);
|
|
28
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const { getUser, getProjectEnvironmentBySlug, updateUserLastActiveOn } = require("./api");
|
|
2
|
+
|
|
3
|
+
module.exports = () => [
|
|
4
|
+
// Within this hook, we're setting the `WCP_ENVIRONMENT_API_KEY` env variable, which can then be used in
|
|
5
|
+
// build / deploy steps. For example, we pass it to GraphQL and Headless CMS Lambda functions.
|
|
6
|
+
{
|
|
7
|
+
type: "hook-before-deploy",
|
|
8
|
+
name: "hook-before-deploy-environment-api-key",
|
|
9
|
+
async hook(args, context) {
|
|
10
|
+
// If the `WCP_ENVIRONMENT_API_KEY` has already been assigned, no need to do anything.
|
|
11
|
+
if (process.env.WCP_ENVIRONMENT_API_KEY) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const environment = await getProjectEnvironment(args, context);
|
|
16
|
+
if (environment) {
|
|
17
|
+
process.env.WCP_ENVIRONMENT_API_KEY = environment.apiKey;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
// Within this hook, we're updating user's "last active" field.
|
|
22
|
+
{
|
|
23
|
+
type: "hook-before-deploy",
|
|
24
|
+
name: "hook-before-deploy-update-last-active-on",
|
|
25
|
+
async hook(args, context) {
|
|
26
|
+
// Is this a user environment? If so, let's update his "last active" field.
|
|
27
|
+
const environment = await getProjectEnvironment(args, context);
|
|
28
|
+
if (environment && environment.user) {
|
|
29
|
+
await updateUserLastActiveOn();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const getProjectEnvironment = async (args, context) => {
|
|
36
|
+
// If the project isn't activated, also do nothing.
|
|
37
|
+
if (!context.project.config.id) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The `id` has the orgId/projectId structure, for example `my-org-x/my-project-y`.
|
|
42
|
+
const orgProject = context.project.config.id;
|
|
43
|
+
const [orgId, projectId] = orgProject.split("/");
|
|
44
|
+
|
|
45
|
+
const isValidId = orgId && projectId;
|
|
46
|
+
if (!isValidId) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`It seems the project ID, specified in "webiny.project.ts" file, is invalid.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check login.
|
|
53
|
+
const user = await getUser();
|
|
54
|
+
const project = user.projects.find(item => item.id === projectId);
|
|
55
|
+
if (!project) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`It seems you don't belong to the current project or the current project has been deleted.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return getProjectEnvironmentBySlug({
|
|
62
|
+
orgId,
|
|
63
|
+
projectId,
|
|
64
|
+
environmentSlug: args.env,
|
|
65
|
+
userId: user.id
|
|
66
|
+
});
|
|
67
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const open = require("open");
|
|
2
|
+
const { GraphQLClient } = require("graphql-request");
|
|
3
|
+
const { WCP_API_URL, WCP_APP_URL } = require("./api");
|
|
4
|
+
|
|
5
|
+
// 120 retries * 2000ms interval = 4 minutes until the command returns an error.
|
|
6
|
+
const LOGIN_RETRIES_COUNT = 30;
|
|
7
|
+
const LOGIN_RETRIES_INTERVAL = 2000;
|
|
8
|
+
|
|
9
|
+
const GENERATE_USER_PAT = /* GraphQL*/ `
|
|
10
|
+
mutation GenerateUserPat {
|
|
11
|
+
users {
|
|
12
|
+
generateUserPat
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const GET_USER_PAT = /* GraphQL*/ `
|
|
18
|
+
query GetUserPat($token: ID!) {
|
|
19
|
+
users {
|
|
20
|
+
getUserPat(token: $token) {
|
|
21
|
+
name
|
|
22
|
+
user {
|
|
23
|
+
email
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
module.exports = () => ({
|
|
31
|
+
type: "cli-command",
|
|
32
|
+
name: "cli-command-wcp-login",
|
|
33
|
+
create({ yargs, context }) {
|
|
34
|
+
yargs.command(
|
|
35
|
+
"login",
|
|
36
|
+
`Log in to the Webiny Control Panel`,
|
|
37
|
+
yargs => {
|
|
38
|
+
yargs.example("$0 login");
|
|
39
|
+
yargs.option("debug", {
|
|
40
|
+
describe: `Turn on debug logs`,
|
|
41
|
+
type: "boolean"
|
|
42
|
+
});
|
|
43
|
+
yargs.option("debug-level", {
|
|
44
|
+
default: 1,
|
|
45
|
+
describe: `Set the debug logs verbosity level`,
|
|
46
|
+
type: "number"
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
async ({ debug, debugLevel }) => {
|
|
50
|
+
const graphQLClient = new GraphQLClient(WCP_API_URL);
|
|
51
|
+
const token = await graphQLClient
|
|
52
|
+
.request(GENERATE_USER_PAT)
|
|
53
|
+
.then(({ users }) => users.generateUserPat);
|
|
54
|
+
|
|
55
|
+
const queryParams = `pat=${token}&pat_name=${encodeURIComponent(
|
|
56
|
+
"Webiny CLI"
|
|
57
|
+
)}&ref=cli`;
|
|
58
|
+
const openUrl = `${WCP_APP_URL}/login/cli?${queryParams}`;
|
|
59
|
+
|
|
60
|
+
debug && context.debug(`Opening ${context.debug.hl(openUrl)}...`);
|
|
61
|
+
await open(openUrl);
|
|
62
|
+
|
|
63
|
+
const graphql = {
|
|
64
|
+
variables: { token },
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: token
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
graphQLClient.setHeaders(graphql.headers);
|
|
71
|
+
|
|
72
|
+
let retries = 0;
|
|
73
|
+
const result = await new Promise(resolve => {
|
|
74
|
+
const interval = setInterval(async () => {
|
|
75
|
+
retries++;
|
|
76
|
+
if (retries > LOGIN_RETRIES_COUNT) {
|
|
77
|
+
clearInterval(interval);
|
|
78
|
+
resolve(false);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
await graphQLClient.request(GET_USER_PAT, graphql.variables);
|
|
83
|
+
clearInterval(interval);
|
|
84
|
+
resolve(true);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
// Do nothing.
|
|
87
|
+
if (debug) {
|
|
88
|
+
context.debug(
|
|
89
|
+
`Could not login. Will try again in ${LOGIN_RETRIES_INTERVAL}ms.`
|
|
90
|
+
);
|
|
91
|
+
if (debugLevel > 1) {
|
|
92
|
+
context.debug("GraphQL Request: ");
|
|
93
|
+
console.log(JSON.stringify(graphql, null, 2));
|
|
94
|
+
}
|
|
95
|
+
if (debugLevel > 2) {
|
|
96
|
+
context.debug(e.message);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}, LOGIN_RETRIES_INTERVAL);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!result) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Could not login. Did you complete the sign in / sign up process at ${WCP_APP_URL}?`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
context.localStorage.set("wcpPat", token);
|
|
110
|
+
|
|
111
|
+
context.success(`You've successfully logged in to Webiny Control Panel!`);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
yargs.command(
|
|
116
|
+
"logout",
|
|
117
|
+
`Log out from the Webiny Control Panel`,
|
|
118
|
+
yargs => {
|
|
119
|
+
yargs.example("$0 login");
|
|
120
|
+
yargs.option("debug", {
|
|
121
|
+
describe: `Turn on debug logs`,
|
|
122
|
+
type: "boolean"
|
|
123
|
+
});
|
|
124
|
+
yargs.option("debug-level", {
|
|
125
|
+
default: 1,
|
|
126
|
+
describe: `Set the debug logs verbosity level`,
|
|
127
|
+
type: "number"
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
async () => {
|
|
131
|
+
context.info(`You've successfully logged out from Webiny Control Panel.`);
|
|
132
|
+
|
|
133
|
+
context.localStorage.set("wcpPat", null);
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
yargs.command(
|
|
138
|
+
"whoami",
|
|
139
|
+
`Display the current logged-in user`,
|
|
140
|
+
yargs => {
|
|
141
|
+
yargs.example("$0 login");
|
|
142
|
+
yargs.option("debug", {
|
|
143
|
+
describe: `Turn on debug logs`,
|
|
144
|
+
type: "boolean"
|
|
145
|
+
});
|
|
146
|
+
yargs.option("debug-level", {
|
|
147
|
+
default: 1,
|
|
148
|
+
describe: `Set the debug logs verbosity level`,
|
|
149
|
+
type: "number"
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
async ({ debug }) => {
|
|
153
|
+
const pat = context.localStorage.get("wcpPat");
|
|
154
|
+
if (!pat) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`It seems you are not logged in. Please login using the ${context.error.hl(
|
|
157
|
+
"webiny login"
|
|
158
|
+
)} command.`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const graphQLClient = new GraphQLClient(WCP_API_URL);
|
|
163
|
+
graphQLClient.setHeaders({ authorization: pat });
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const user = await graphQLClient
|
|
167
|
+
.request(GET_USER_PAT, { token: pat })
|
|
168
|
+
.then(({ users }) => users.getUserPat.user);
|
|
169
|
+
|
|
170
|
+
context.info(
|
|
171
|
+
`You are logged in to Webiny Control Panel as ${context.info.hl(
|
|
172
|
+
user.email
|
|
173
|
+
)}.`
|
|
174
|
+
);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
if (debug) {
|
|
177
|
+
context.debug(e);
|
|
178
|
+
}
|
|
179
|
+
throw new Error(
|
|
180
|
+
`It seems you are not logged in. Please login using the ${context.error.hl(
|
|
181
|
+
"webiny login"
|
|
182
|
+
)} command.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const { getUser } = require("./api");
|
|
2
|
+
const { WCP_APP_URL } = require("./api");
|
|
3
|
+
const open = require("open");
|
|
4
|
+
const inquirer = require("inquirer");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const tsMorph = require("ts-morph");
|
|
7
|
+
|
|
8
|
+
module.exports = () => [
|
|
9
|
+
{
|
|
10
|
+
type: "cli-command",
|
|
11
|
+
name: "cli-command-wcp-project",
|
|
12
|
+
create({ yargs, context }) {
|
|
13
|
+
yargs.command(
|
|
14
|
+
["project <command>"],
|
|
15
|
+
`Webiny project-related commands`,
|
|
16
|
+
projectCommand => {
|
|
17
|
+
projectCommand.command(
|
|
18
|
+
"init",
|
|
19
|
+
`Initialize a Webiny project`,
|
|
20
|
+
command => {
|
|
21
|
+
yargs.option("debug", {
|
|
22
|
+
describe: `Turn on debug logs`,
|
|
23
|
+
type: "boolean"
|
|
24
|
+
});
|
|
25
|
+
yargs.option("debug-level", {
|
|
26
|
+
default: 1,
|
|
27
|
+
describe: `Set the debug logs verbosity level`,
|
|
28
|
+
type: "number"
|
|
29
|
+
});
|
|
30
|
+
command.example("$0 project init");
|
|
31
|
+
},
|
|
32
|
+
async () => {
|
|
33
|
+
// Check login.
|
|
34
|
+
const user = await getUser();
|
|
35
|
+
|
|
36
|
+
// User already initialized a project?
|
|
37
|
+
const { id } = context.project.config;
|
|
38
|
+
if (id) {
|
|
39
|
+
const project = user.projects.find(item => item.id === id);
|
|
40
|
+
if (project) {
|
|
41
|
+
context.info(
|
|
42
|
+
`It seems this project was already initialized (project name: ${context.info.hl(
|
|
43
|
+
project.name
|
|
44
|
+
)}).`
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const prompt = inquirer.createPromptModule();
|
|
48
|
+
const { proceed } = await prompt({
|
|
49
|
+
name: "proceed",
|
|
50
|
+
message: "Would you like to re-initialize it?",
|
|
51
|
+
type: "confirm",
|
|
52
|
+
default: false
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (!proceed) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Get user's organizations.
|
|
62
|
+
if (!user.orgs.length) {
|
|
63
|
+
context.info(
|
|
64
|
+
"It seems you're not part of any organization. Please log in to Webiny Control Panel and create one."
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const prompt = inquirer.createPromptModule();
|
|
68
|
+
const { proceed } = await prompt({
|
|
69
|
+
name: "proceed",
|
|
70
|
+
message: "Would you like to do that now?",
|
|
71
|
+
type: "confirm",
|
|
72
|
+
default: false
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (proceed) {
|
|
76
|
+
await open(WCP_APP_URL);
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let selectedOrg;
|
|
82
|
+
if (user.orgs.length === 1) {
|
|
83
|
+
selectedOrg = user.orgs[0];
|
|
84
|
+
} else {
|
|
85
|
+
context.info("It seems you're part of multiple organizations. ");
|
|
86
|
+
const choices = user.orgs.map(item => ({
|
|
87
|
+
name: item.name,
|
|
88
|
+
value: item
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const prompt = inquirer.createPromptModule();
|
|
92
|
+
selectedOrg = await prompt({
|
|
93
|
+
name: "org",
|
|
94
|
+
message: "Select organization:",
|
|
95
|
+
type: "list",
|
|
96
|
+
choices,
|
|
97
|
+
default: choices[0].value
|
|
98
|
+
}).then(result => result.org);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const orgProjects = user.projects.filter(
|
|
102
|
+
item => item.org.id === selectedOrg.id
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Get user's projects.
|
|
106
|
+
if (!orgProjects.length) {
|
|
107
|
+
context.info(
|
|
108
|
+
`It seems there are no projects created within the ${context.info.hl(
|
|
109
|
+
selectedOrg.name
|
|
110
|
+
)} organization.`
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const prompt = inquirer.createPromptModule();
|
|
114
|
+
const { proceed } = await prompt({
|
|
115
|
+
name: "proceed",
|
|
116
|
+
message: "Would you like to create one now?",
|
|
117
|
+
type: "confirm",
|
|
118
|
+
default: false
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (proceed) {
|
|
122
|
+
await open(WCP_APP_URL);
|
|
123
|
+
}
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let selectedProject;
|
|
128
|
+
if (orgProjects.length === 1) {
|
|
129
|
+
selectedProject = user.projects[0];
|
|
130
|
+
} else {
|
|
131
|
+
context.info(
|
|
132
|
+
`It seems there are multiple projects created within the ${context.info.hl(
|
|
133
|
+
selectedOrg.name
|
|
134
|
+
)} organization.`
|
|
135
|
+
);
|
|
136
|
+
const choices = orgProjects.map(item => ({
|
|
137
|
+
name: item.name,
|
|
138
|
+
value: item
|
|
139
|
+
}));
|
|
140
|
+
const prompt = inquirer.createPromptModule();
|
|
141
|
+
selectedProject = await prompt({
|
|
142
|
+
name: "project",
|
|
143
|
+
message: "Select project:",
|
|
144
|
+
type: "list",
|
|
145
|
+
choices,
|
|
146
|
+
default: choices[0].value
|
|
147
|
+
}).then(result => result.project);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Assign the necessary IDs into root `webiny.project.ts` project file.
|
|
151
|
+
const webinyProjectPath = path.join(
|
|
152
|
+
context.project.root,
|
|
153
|
+
"webiny.project.ts"
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const tsMorphProject = new tsMorph.Project();
|
|
157
|
+
tsMorphProject.addSourceFileAtPath(webinyProjectPath);
|
|
158
|
+
|
|
159
|
+
const source = tsMorphProject.getSourceFile(webinyProjectPath);
|
|
160
|
+
|
|
161
|
+
const defaultExport = source.getFirstDescendant(node => {
|
|
162
|
+
if (tsMorph.Node.isExportAssignment(node) === false) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return node.getText().startsWith("export default ");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (!defaultExport) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Could not find the default export in ${context.error.hl(
|
|
171
|
+
"webiny.project.ts"
|
|
172
|
+
)}.`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Get ObjectLiteralExpression within the default export and assign the `id` property to it.
|
|
177
|
+
const exportedObjectLiteral = defaultExport.getFirstDescendant(
|
|
178
|
+
node => tsMorph.Node.isObjectLiteralExpression(node) === true
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const existingIdProperty = exportedObjectLiteral.getProperty(node => {
|
|
182
|
+
return (
|
|
183
|
+
tsMorph.Node.isPropertyAssignment(node) &&
|
|
184
|
+
node.getName() === "id"
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
if (tsMorph.Node.isPropertyAssignment(existingIdProperty)) {
|
|
189
|
+
existingIdProperty.setInitializer(`"${selectedProject.id}"`);
|
|
190
|
+
} else {
|
|
191
|
+
exportedObjectLiteral.insertProperty(
|
|
192
|
+
0,
|
|
193
|
+
`id: "${selectedOrg.id}/${selectedProject.id}"`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
await tsMorphProject.save();
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
type: "cli-plugi"
|
|
206
|
+
}
|
|
207
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.23.0-beta.1",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"webiny": "./bin.js"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"author": "Pavel Denisjuk <pavel@webiny.com>",
|
|
14
14
|
"description": "A tool to bootstrap a Webiny project.",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@webiny/telemetry": "5.
|
|
16
|
+
"@webiny/telemetry": "5.23.0-beta.1",
|
|
17
17
|
"boolean": "3.1.4",
|
|
18
18
|
"camelcase": "5.3.1",
|
|
19
19
|
"chalk": "4.1.2",
|
|
@@ -21,8 +21,12 @@
|
|
|
21
21
|
"execa": "2.1.0",
|
|
22
22
|
"fast-glob": "3.2.7",
|
|
23
23
|
"find-up": "5.0.0",
|
|
24
|
-
"
|
|
24
|
+
"graphql-request": "3.7.0",
|
|
25
|
+
"inquirer": "7.3.3",
|
|
26
|
+
"open": "8.4.0",
|
|
27
|
+
"pirates": "4.0.5",
|
|
25
28
|
"semver": "7.3.4",
|
|
29
|
+
"ts-morph": "11.0.3",
|
|
26
30
|
"typescript": "4.1.3",
|
|
27
31
|
"uniqid": "5.4.0",
|
|
28
32
|
"yargs": "14.2.3"
|
|
@@ -59,5 +63,5 @@
|
|
|
59
63
|
]
|
|
60
64
|
}
|
|
61
65
|
},
|
|
62
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "04f2d5e43684b9086251e2a6370b3c085e6d51cb"
|
|
63
67
|
}
|