@nexical/cli 0.1.7 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy.yml +3 -3
- package/GEMINI.md +193 -0
- package/README.md +317 -104
- package/dist/chunk-JYASTIIW.js +42 -0
- package/dist/chunk-JYASTIIW.js.map +1 -0
- package/dist/chunk-LZ3YQWAR.js +2204 -0
- package/dist/chunk-LZ3YQWAR.js.map +1 -0
- package/dist/chunk-OKXOCNXP.js +105 -0
- package/dist/chunk-OKXOCNXP.js.map +1 -0
- package/dist/chunk-OYFWMYPG.js +52 -0
- package/dist/chunk-OYFWMYPG.js.map +1 -0
- package/dist/chunk-WKERTCM6.js +74 -0
- package/dist/chunk-WKERTCM6.js.map +1 -0
- package/dist/index.js +32 -5
- package/dist/index.js.map +1 -1
- package/dist/src/commands/init.d.ts +11 -0
- package/dist/src/commands/init.js +89 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/module/add.d.ts +14 -0
- package/dist/src/commands/module/add.js +136 -0
- package/dist/src/commands/module/add.js.map +1 -0
- package/dist/src/commands/module/list.d.ts +10 -0
- package/dist/src/commands/module/list.js +73 -0
- package/dist/src/commands/module/list.js.map +1 -0
- package/dist/src/commands/module/remove.d.ts +12 -0
- package/dist/src/commands/module/remove.js +71 -0
- package/dist/src/commands/module/remove.js.map +1 -0
- package/dist/src/commands/module/update.d.ts +11 -0
- package/dist/src/commands/module/update.js +52 -0
- package/dist/src/commands/module/update.js.map +1 -0
- package/dist/src/commands/run.d.ts +11 -0
- package/dist/src/commands/run.js +93 -0
- package/dist/src/commands/run.js.map +1 -0
- package/dist/src/commands/{login.d.ts → setup.d.ts} +2 -2
- package/dist/src/commands/setup.js +62 -0
- package/dist/src/commands/setup.js.map +1 -0
- package/dist/src/utils/discovery.d.ts +13 -0
- package/dist/src/utils/discovery.js +9 -0
- package/dist/src/utils/git.d.ts +16 -0
- package/dist/src/utils/git.js +29 -0
- package/dist/src/utils/git.js.map +1 -0
- package/dist/src/utils/url-resolver.d.ts +15 -0
- package/dist/src/utils/url-resolver.js +9 -0
- package/dist/src/utils/url-resolver.js.map +1 -0
- package/index.ts +29 -5
- package/package.json +32 -30
- package/src/commands/init.ts +86 -0
- package/src/commands/module/add.ts +169 -0
- package/src/commands/module/list.ts +69 -0
- package/src/commands/module/remove.ts +74 -0
- package/src/commands/module/update.ts +50 -0
- package/src/commands/run.ts +98 -0
- package/src/commands/setup.ts +74 -0
- package/src/utils/discovery.ts +134 -0
- package/src/utils/git.ts +65 -0
- package/src/utils/url-resolver.ts +57 -0
- package/test/e2e/lifecycle.e2e.test.ts +153 -0
- package/test/integration/commands/init.integration.test.ts +85 -0
- package/test/integration/commands/module.integration.test.ts +144 -0
- package/test/integration/commands/run.integration.test.ts +90 -0
- package/test/integration/utils/command-loading.integration.test.ts +80 -0
- package/test/unit/commands/init.test.ts +153 -0
- package/test/unit/commands/module/add.test.ts +262 -0
- package/test/unit/commands/module/list.test.ts +115 -0
- package/test/unit/commands/module/remove.test.ts +89 -0
- package/test/unit/commands/module/update.test.ts +91 -0
- package/test/unit/commands/run.test.ts +252 -0
- package/test/unit/commands/setup.test.ts +169 -0
- package/test/unit/utils/command-discovery.test.ts +176 -0
- package/test/unit/utils/git.test.ts +152 -0
- package/test/unit/utils/integration-helpers.test.ts +72 -0
- package/test/unit/utils/url-resolver.test.ts +39 -0
- package/test/utils/integration-helpers.ts +66 -0
- package/vitest.e2e.config.ts +0 -1
- package/dist/chunk-JDRAVUKK.js +0 -48
- package/dist/chunk-JDRAVUKK.js.map +0 -1
- package/dist/src/commands/admin/create-user.d.ts +0 -15
- package/dist/src/commands/admin/create-user.js +0 -49
- package/dist/src/commands/admin/create-user.js.map +0 -1
- package/dist/src/commands/branch/create.d.ts +0 -19
- package/dist/src/commands/branch/create.js +0 -59
- package/dist/src/commands/branch/create.js.map +0 -1
- package/dist/src/commands/branch/delete.d.ts +0 -15
- package/dist/src/commands/branch/delete.js +0 -50
- package/dist/src/commands/branch/delete.js.map +0 -1
- package/dist/src/commands/branch/get.d.ts +0 -15
- package/dist/src/commands/branch/get.js +0 -53
- package/dist/src/commands/branch/get.js.map +0 -1
- package/dist/src/commands/branch/list.d.ts +0 -15
- package/dist/src/commands/branch/list.js +0 -51
- package/dist/src/commands/branch/list.js.map +0 -1
- package/dist/src/commands/job/get.d.ts +0 -15
- package/dist/src/commands/job/get.js +0 -62
- package/dist/src/commands/job/get.js.map +0 -1
- package/dist/src/commands/job/list.d.ts +0 -15
- package/dist/src/commands/job/list.js +0 -57
- package/dist/src/commands/job/list.js.map +0 -1
- package/dist/src/commands/job/logs.d.ts +0 -15
- package/dist/src/commands/job/logs.js +0 -67
- package/dist/src/commands/job/logs.js.map +0 -1
- package/dist/src/commands/job/trigger.d.ts +0 -19
- package/dist/src/commands/job/trigger.js +0 -74
- package/dist/src/commands/job/trigger.js.map +0 -1
- package/dist/src/commands/login.js +0 -31
- package/dist/src/commands/login.js.map +0 -1
- package/dist/src/commands/project/create.d.ts +0 -24
- package/dist/src/commands/project/create.js +0 -63
- package/dist/src/commands/project/create.js.map +0 -1
- package/dist/src/commands/project/delete.d.ts +0 -20
- package/dist/src/commands/project/delete.js +0 -58
- package/dist/src/commands/project/delete.js.map +0 -1
- package/dist/src/commands/project/get.d.ts +0 -15
- package/dist/src/commands/project/get.js +0 -49
- package/dist/src/commands/project/get.js.map +0 -1
- package/dist/src/commands/project/list.d.ts +0 -15
- package/dist/src/commands/project/list.js +0 -45
- package/dist/src/commands/project/list.js.map +0 -1
- package/dist/src/commands/project/update.d.ts +0 -19
- package/dist/src/commands/project/update.js +0 -66
- package/dist/src/commands/project/update.js.map +0 -1
- package/dist/src/commands/team/create.d.ts +0 -19
- package/dist/src/commands/team/create.js +0 -45
- package/dist/src/commands/team/create.js.map +0 -1
- package/dist/src/commands/team/delete.d.ts +0 -20
- package/dist/src/commands/team/delete.js +0 -52
- package/dist/src/commands/team/delete.js.map +0 -1
- package/dist/src/commands/team/get.d.ts +0 -15
- package/dist/src/commands/team/get.js +0 -42
- package/dist/src/commands/team/get.js.map +0 -1
- package/dist/src/commands/team/list.d.ts +0 -8
- package/dist/src/commands/team/list.js +0 -30
- package/dist/src/commands/team/list.js.map +0 -1
- package/dist/src/commands/team/member/invite.d.ts +0 -20
- package/dist/src/commands/team/member/invite.js +0 -54
- package/dist/src/commands/team/member/invite.js.map +0 -1
- package/dist/src/commands/team/member/remove.d.ts +0 -15
- package/dist/src/commands/team/member/remove.js +0 -43
- package/dist/src/commands/team/member/remove.js.map +0 -1
- package/dist/src/commands/team/update.d.ts +0 -19
- package/dist/src/commands/team/update.js +0 -55
- package/dist/src/commands/team/update.js.map +0 -1
- package/dist/src/commands/token/generate.d.ts +0 -19
- package/dist/src/commands/token/generate.js +0 -48
- package/dist/src/commands/token/generate.js.map +0 -1
- package/dist/src/commands/token/list.d.ts +0 -8
- package/dist/src/commands/token/list.js +0 -31
- package/dist/src/commands/token/list.js.map +0 -1
- package/dist/src/commands/token/revoke.d.ts +0 -15
- package/dist/src/commands/token/revoke.js +0 -38
- package/dist/src/commands/token/revoke.js.map +0 -1
- package/dist/src/commands/whoami.d.ts +0 -8
- package/dist/src/commands/whoami.js +0 -26
- package/dist/src/commands/whoami.js.map +0 -1
- package/dist/src/utils/nexical-client.d.ts +0 -10
- package/dist/src/utils/nexical-client.js +0 -12
- package/src/commands/admin/create-user.ts +0 -46
- package/src/commands/branch/create.ts +0 -57
- package/src/commands/branch/delete.ts +0 -47
- package/src/commands/branch/get.ts +0 -50
- package/src/commands/branch/list.ts +0 -50
- package/src/commands/job/get.ts +0 -59
- package/src/commands/job/list.ts +0 -56
- package/src/commands/job/logs.ts +0 -67
- package/src/commands/job/trigger.ts +0 -73
- package/src/commands/login.ts +0 -31
- package/src/commands/project/create.ts +0 -61
- package/src/commands/project/delete.ts +0 -56
- package/src/commands/project/get.ts +0 -46
- package/src/commands/project/list.ts +0 -44
- package/src/commands/project/update.ts +0 -63
- package/src/commands/team/create.ts +0 -43
- package/src/commands/team/delete.ts +0 -50
- package/src/commands/team/get.ts +0 -39
- package/src/commands/team/list.ts +0 -26
- package/src/commands/team/member/invite.ts +0 -56
- package/src/commands/team/member/remove.ts +0 -40
- package/src/commands/team/update.ts +0 -53
- package/src/commands/token/generate.ts +0 -45
- package/src/commands/token/list.ts +0 -27
- package/src/commands/token/revoke.ts +0 -35
- package/src/commands/whoami.ts +0 -21
- package/src/utils/nexical-client.ts +0 -47
- package/test/e2e/auth.e2e.test.ts +0 -46
- package/test/e2e/job-workflow.e2e.test.ts +0 -33
- package/test/e2e/project-lifecycle.e2e.test.ts +0 -48
- package/test/e2e/setup.ts +0 -237
- package/test/e2e/utils.ts +0 -33
- package/test/integration/commands/admin/create-user.test.ts +0 -51
- package/test/integration/commands/branch/create.test.ts +0 -51
- package/test/integration/commands/branch/delete.test.ts +0 -43
- package/test/integration/commands/branch/get.test.ts +0 -49
- package/test/integration/commands/branch/list.test.ts +0 -47
- package/test/integration/commands/job/get.test.ts +0 -54
- package/test/integration/commands/job/list.test.ts +0 -47
- package/test/integration/commands/job/logs.test.ts +0 -47
- package/test/integration/commands/job/trigger.test.ts +0 -57
- package/test/integration/commands/login.test.ts +0 -62
- package/test/integration/commands/project/create.test.ts +0 -53
- package/test/integration/commands/project/delete.test.ts +0 -43
- package/test/integration/commands/project/get.test.ts +0 -51
- package/test/integration/commands/project/list.test.ts +0 -47
- package/test/integration/commands/project/update.test.ts +0 -53
- package/test/integration/commands/team/create.test.ts +0 -53
- package/test/integration/commands/team/delete.test.ts +0 -43
- package/test/integration/commands/team/get.test.ts +0 -50
- package/test/integration/commands/team/list.test.ts +0 -47
- package/test/integration/commands/team/member/invite.test.ts +0 -46
- package/test/integration/commands/team/member/remove.test.ts +0 -43
- package/test/integration/commands/team/update.test.ts +0 -50
- package/test/integration/commands/token/generate.test.ts +0 -51
- package/test/integration/commands/token/list.test.ts +0 -47
- package/test/integration/commands/token/revoke.test.ts +0 -43
- package/test/integration/commands/whoami.test.ts +0 -49
- package/test/unit/commands/admin/create-user.test.ts +0 -51
- package/test/unit/commands/branch/create.test.ts +0 -57
- package/test/unit/commands/branch/delete.test.ts +0 -49
- package/test/unit/commands/branch/get.test.ts +0 -67
- package/test/unit/commands/branch/list.test.ts +0 -62
- package/test/unit/commands/job/get.test.ts +0 -76
- package/test/unit/commands/job/list.test.ts +0 -62
- package/test/unit/commands/job/logs.test.ts +0 -60
- package/test/unit/commands/job/trigger.test.ts +0 -75
- package/test/unit/commands/login.test.ts +0 -64
- package/test/unit/commands/project/create.test.ts +0 -64
- package/test/unit/commands/project/delete.test.ts +0 -72
- package/test/unit/commands/project/get.test.ts +0 -73
- package/test/unit/commands/project/list.test.ts +0 -62
- package/test/unit/commands/project/update.test.ts +0 -58
- package/test/unit/commands/team/create.test.ts +0 -68
- package/test/unit/commands/team/delete.test.ts +0 -71
- package/test/unit/commands/team/get.test.ts +0 -70
- package/test/unit/commands/team/list.test.ts +0 -56
- package/test/unit/commands/team/member/invite.test.ts +0 -52
- package/test/unit/commands/team/member/remove.test.ts +0 -49
- package/test/unit/commands/team/update.test.ts +0 -63
- package/test/unit/commands/token/generate.test.ts +0 -65
- package/test/unit/commands/token/list.test.ts +0 -58
- package/test/unit/commands/token/revoke.test.ts +0 -49
- package/test/unit/commands/whoami.test.ts +0 -49
- package/test/unit/utils/nexical-client.test.ts +0 -113
- /package/dist/src/utils/{nexical-client.js.map → discovery.js.map} +0 -0
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class TeamsListCommand extends BaseCommand {
|
|
6
|
-
static description = 'List all teams you belong to';
|
|
7
|
-
|
|
8
|
-
async run() {
|
|
9
|
-
const client = getClient();
|
|
10
|
-
try {
|
|
11
|
-
const teams = await client.teams.list();
|
|
12
|
-
|
|
13
|
-
if (teams.length === 0) {
|
|
14
|
-
this.info('You are not a member of any teams.');
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this.info('Your Teams:');
|
|
19
|
-
for (const team of teams) {
|
|
20
|
-
this.info(`- ${team.name} (${team.slug}) [${team.role || 'member'}]`);
|
|
21
|
-
}
|
|
22
|
-
} catch (error: any) {
|
|
23
|
-
this.error(`Failed to list teams: ${error.message}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class TeamsInviteCommand extends BaseCommand {
|
|
6
|
-
static description = 'Invite a user to a team';
|
|
7
|
-
|
|
8
|
-
static args = {
|
|
9
|
-
args: [
|
|
10
|
-
{
|
|
11
|
-
name: 'teamId',
|
|
12
|
-
required: true,
|
|
13
|
-
description: 'ID of the team',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
name: 'email',
|
|
17
|
-
required: true,
|
|
18
|
-
description: 'Email of the user to invite',
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
options: [
|
|
22
|
-
{
|
|
23
|
-
name: '--role <role>',
|
|
24
|
-
description: 'Role for the new member (admin, member)',
|
|
25
|
-
default: 'member',
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
async run(options: any) {
|
|
31
|
-
const client = getClient();
|
|
32
|
-
const { teamId, email, role } = options;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
// teamId from args is string, but SDK expects number usually?
|
|
36
|
-
// Docs say: Team { id: number; ... }
|
|
37
|
-
// SDK methods: inviteMember(id, data)
|
|
38
|
-
// BaseCommand options are typically strings from CLI args.
|
|
39
|
-
// I should parse teamId to number.
|
|
40
|
-
const tid = parseInt(teamId, 10);
|
|
41
|
-
if (isNaN(tid)) {
|
|
42
|
-
this.error('Team ID must be a number.');
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
await client.teams.inviteMember(tid, {
|
|
47
|
-
email,
|
|
48
|
-
role: role as any, // Cast to expected enum if needed
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
this.success(`Invited ${email} to team ${tid} as ${role}.`);
|
|
52
|
-
} catch (error: any) {
|
|
53
|
-
this.error(`Failed to invite member: ${error.message}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class TeamsMembersRemoveCommand extends BaseCommand {
|
|
6
|
-
static description = 'Remove a member from a team';
|
|
7
|
-
|
|
8
|
-
static args = {
|
|
9
|
-
args: [
|
|
10
|
-
{
|
|
11
|
-
name: 'teamId',
|
|
12
|
-
required: true,
|
|
13
|
-
description: 'Team ID',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
name: 'userId',
|
|
17
|
-
required: true,
|
|
18
|
-
description: 'User ID (UUID)',
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
async run(options: any) {
|
|
24
|
-
const client = getClient();
|
|
25
|
-
const { teamId, userId } = options;
|
|
26
|
-
const tid = parseInt(teamId, 10);
|
|
27
|
-
|
|
28
|
-
if (isNaN(tid)) {
|
|
29
|
-
this.error('Team ID must be a number.');
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
await client.teams.removeMember(tid, userId);
|
|
35
|
-
this.success(`User ${userId} removed from team ${tid}.`);
|
|
36
|
-
} catch (error: any) {
|
|
37
|
-
this.error(`Failed to remove member: ${error.message}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class TeamsUpdateCommand extends BaseCommand {
|
|
6
|
-
static description = 'Update team details';
|
|
7
|
-
|
|
8
|
-
static args = {
|
|
9
|
-
args: [
|
|
10
|
-
{
|
|
11
|
-
name: 'teamId',
|
|
12
|
-
required: true,
|
|
13
|
-
description: 'Team ID',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
options: [
|
|
17
|
-
{
|
|
18
|
-
name: '--name <name>',
|
|
19
|
-
description: 'New name',
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
name: '--slug <slug>',
|
|
23
|
-
description: 'New slug',
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
async run(options: any) {
|
|
29
|
-
const client = getClient();
|
|
30
|
-
const { teamId, name, slug } = options;
|
|
31
|
-
const tid = parseInt(teamId, 10);
|
|
32
|
-
|
|
33
|
-
if (isNaN(tid)) {
|
|
34
|
-
this.error('Team ID must be a number.');
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!name && !slug) {
|
|
39
|
-
this.warn('No updates provided. Use --name or --slug.');
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const team = await client.teams.update(tid, {
|
|
45
|
-
name,
|
|
46
|
-
});
|
|
47
|
-
this.success(`Team ${team.id} updated!`);
|
|
48
|
-
this.info(`Name: ${team.name}`);
|
|
49
|
-
} catch (error: any) {
|
|
50
|
-
this.error(`Failed to update team: ${error.message}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class AuthTokensGenerateCommand extends BaseCommand {
|
|
6
|
-
static description = 'Generate a new API token';
|
|
7
|
-
|
|
8
|
-
static args = {
|
|
9
|
-
args: [
|
|
10
|
-
{
|
|
11
|
-
name: 'name',
|
|
12
|
-
required: true,
|
|
13
|
-
description: 'Name of the token',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
options: [
|
|
17
|
-
{
|
|
18
|
-
name: '--scopes <scopes>',
|
|
19
|
-
description: 'Comma-separated list of scopes',
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
name: '--expires <isoDate>',
|
|
23
|
-
description: 'Expiration date (ISO 8601)',
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
async run(options: any) {
|
|
29
|
-
const client = getClient();
|
|
30
|
-
const { name, scopes, expires } = options;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const token = await client.auth.generateToken({
|
|
34
|
-
name,
|
|
35
|
-
scopes: scopes ? scopes.split(',') : undefined,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.success(`Token "${name}" generated!`);
|
|
39
|
-
this.warn(`Token: ${token.token}`);
|
|
40
|
-
this.warn('Make sure to copy it now. You won\'t be able to see it again!');
|
|
41
|
-
} catch (error: any) {
|
|
42
|
-
this.error(`Failed to generate token: ${error.message}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class AuthTokensListCommand extends BaseCommand {
|
|
6
|
-
static description = 'List your API tokens';
|
|
7
|
-
|
|
8
|
-
async run() {
|
|
9
|
-
const client = getClient();
|
|
10
|
-
try {
|
|
11
|
-
const response = await client.auth.listTokens();
|
|
12
|
-
const tokens = response.tokens;
|
|
13
|
-
|
|
14
|
-
if (tokens.length === 0) {
|
|
15
|
-
this.info('No API tokens found.');
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
this.info('Your API Tokens:');
|
|
20
|
-
for (const token of tokens) {
|
|
21
|
-
this.info(`- ${token.name} (${token.tokenPrefix}...) [Expires: ${token.expiresAt || 'Never'}]`);
|
|
22
|
-
}
|
|
23
|
-
} catch (error: any) {
|
|
24
|
-
this.error(`Failed to list tokens: ${error.message}`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class AuthTokensRevokeCommand extends BaseCommand {
|
|
6
|
-
static description = 'Revoke an API token';
|
|
7
|
-
|
|
8
|
-
static args = {
|
|
9
|
-
args: [
|
|
10
|
-
{
|
|
11
|
-
name: 'id',
|
|
12
|
-
required: true,
|
|
13
|
-
description: 'ID of the token to revoke',
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
async run(options: any) {
|
|
19
|
-
const client = getClient();
|
|
20
|
-
const { id } = options;
|
|
21
|
-
const tid = parseInt(id, 10);
|
|
22
|
-
|
|
23
|
-
if (isNaN(tid)) {
|
|
24
|
-
this.error('Token ID must be a number.');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
await client.auth.revokeToken(tid);
|
|
30
|
-
this.success(`Token ${tid} revoked.`);
|
|
31
|
-
} catch (error: any) {
|
|
32
|
-
this.error(`Failed to revoke token: ${error.message}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
package/src/commands/whoami.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
3
|
-
import { getClient } from '../utils/nexical-client.js';
|
|
4
|
-
|
|
5
|
-
export default class WhoamiCommand extends BaseCommand {
|
|
6
|
-
static description = 'Show current logged in user';
|
|
7
|
-
|
|
8
|
-
async run() {
|
|
9
|
-
const client = getClient();
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const user = await client.users.me();
|
|
13
|
-
this.info(`Logged in as:`);
|
|
14
|
-
this.info(` Name: ${user.fullName}`);
|
|
15
|
-
this.info(` Email: ${user.email}`);
|
|
16
|
-
this.info(` ID: ${user.id}`);
|
|
17
|
-
} catch (error: any) {
|
|
18
|
-
this.error('Not logged in or token expired. Run `astrical login`.');
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { NexicalClient } from '@nexical/sdk';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import os from 'node:os';
|
|
6
|
-
|
|
7
|
-
const getConfigPaths = () => {
|
|
8
|
-
const HOME = process.env.HOME || os.homedir();
|
|
9
|
-
const CONFIG_DIR = path.join(HOME, '.nexical');
|
|
10
|
-
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
11
|
-
return { CONFIG_DIR, CONFIG_FILE };
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
interface Config {
|
|
15
|
-
token?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function getConfig(): Config {
|
|
19
|
-
const { CONFIG_FILE } = getConfigPaths();
|
|
20
|
-
if (!fs.existsSync(CONFIG_FILE)) {
|
|
21
|
-
return {};
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
25
|
-
return JSON.parse(content);
|
|
26
|
-
} catch (error) {
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function saveToken(token: string) {
|
|
32
|
-
const { CONFIG_DIR, CONFIG_FILE } = getConfigPaths();
|
|
33
|
-
if (!fs.existsSync(CONFIG_DIR)) {
|
|
34
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
35
|
-
}
|
|
36
|
-
const config = getConfig();
|
|
37
|
-
config.token = token;
|
|
38
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function getClient(): NexicalClient {
|
|
42
|
-
const config = getConfig();
|
|
43
|
-
return new NexicalClient({
|
|
44
|
-
token: config.token,
|
|
45
|
-
baseURL: process.env.NEXICAL_API_URL,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
-
import { runCLI, TEST_HOME } from './utils.js';
|
|
3
|
-
import { resetMockStore } from './setup.js';
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
|
|
7
|
-
describe('Authentication E2E', () => {
|
|
8
|
-
// Isolate config for tests
|
|
9
|
-
const TEST_CONFIG_DIR = path.join(TEST_HOME, '.nexical');
|
|
10
|
-
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
-
|
|
12
|
-
beforeAll(async () => {
|
|
13
|
-
resetMockStore();
|
|
14
|
-
// Clean up any existing config
|
|
15
|
-
if (await fs.pathExists(TEST_CONFIG_FILE)) {
|
|
16
|
-
await fs.remove(TEST_CONFIG_FILE);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should show not logged in initially', async () => {
|
|
21
|
-
const { stdout } = await runCLI(['whoami']);
|
|
22
|
-
expect(stdout).toContain('Not logged in or token expired');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should login successfully', async () => {
|
|
26
|
-
// Simulate login
|
|
27
|
-
// Since login is interactive (browser open), we might mock the open module or
|
|
28
|
-
// just trust runCLI can handle the non-interactive part until the prompt.
|
|
29
|
-
// However, key to this test is that we can MANUALLY set the token via CLI
|
|
30
|
-
// OR we just simulate the token save if the CLI doesn't support non-interactive login easily.
|
|
31
|
-
|
|
32
|
-
// For E2E of the CLI 'login' command specifically, it's hard without a browser.
|
|
33
|
-
// But we can verify "whoami" works IF we have a token.
|
|
34
|
-
|
|
35
|
-
// Let's manually inject a token to simulate a successful login state for now
|
|
36
|
-
// as true E2E of OAuth device flow requires browser automation which is out of scope.
|
|
37
|
-
|
|
38
|
-
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
39
|
-
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
40
|
-
|
|
41
|
-
const { stdout } = await runCLI(['whoami']);
|
|
42
|
-
expect(stdout).toContain('Logged in as:');
|
|
43
|
-
expect(stdout).toContain('Name: Test User');
|
|
44
|
-
expect(stdout).toContain('Email: test@example.com');
|
|
45
|
-
});
|
|
46
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
-
import { runCLI } from './utils.js';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import os from 'os';
|
|
6
|
-
import { resetMockStore } from './setup.js';
|
|
7
|
-
|
|
8
|
-
describe('Job Workflow E2E', () => {
|
|
9
|
-
const TEST_CONFIG_DIR = path.join(os.homedir(), '.nexical');
|
|
10
|
-
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
-
|
|
12
|
-
beforeAll(async () => {
|
|
13
|
-
resetMockStore();
|
|
14
|
-
resetMockStore();
|
|
15
|
-
// Ensure logged in
|
|
16
|
-
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
17
|
-
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should trigger a job', async () => {
|
|
21
|
-
// We use "3" as branchId (must be numeric for CLI validation)
|
|
22
|
-
const { stdout } = await runCLI(['job', 'trigger', '1', '101', '3', 'deploy']);
|
|
23
|
-
expect(stdout).toContain('Job 123 triggered successfully!');
|
|
24
|
-
expect(stdout).toContain('Status: pending');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('should get job logs', async () => {
|
|
28
|
-
const { stdout } = await runCLI(['job', 'logs', '1', '101', '3', '123']);
|
|
29
|
-
expect(stdout).toContain('Logs for Job 123:');
|
|
30
|
-
expect(stdout).toContain('Build initialized');
|
|
31
|
-
expect(stdout).toContain('Build successful');
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
-
import { runCLI } from './utils.js';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import os from 'os';
|
|
6
|
-
import { resetMockStore } from './setup.js';
|
|
7
|
-
|
|
8
|
-
describe('Project Lifecycle E2E', () => {
|
|
9
|
-
const TEST_CONFIG_DIR = path.join(os.homedir(), '.nexical');
|
|
10
|
-
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
-
|
|
12
|
-
beforeAll(async () => {
|
|
13
|
-
resetMockStore();
|
|
14
|
-
// Ensure logged intMockStore();
|
|
15
|
-
// Ensure logged in
|
|
16
|
-
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
17
|
-
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should create a new project', async () => {
|
|
21
|
-
const { stdout } = await runCLI(['project', 'create', '1', 'My Project', '--repo', 'https://github.com/test/repo']);
|
|
22
|
-
expect(stdout).toContain('Project "My Project" set up successfully!');
|
|
23
|
-
expect(stdout).toContain('ID: 101');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should list projects', async () => {
|
|
27
|
-
const { stdout } = await runCLI(['project', 'list', '1']);
|
|
28
|
-
expect(stdout).toContain('Projects in Team 1:');
|
|
29
|
-
expect(stdout).toContain('My Project (ID: 101)');
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should update project', async () => {
|
|
33
|
-
const { stdout } = await runCLI(['project', 'update', '1', '101', '--name', 'Updated Project']);
|
|
34
|
-
// Note: The CLI success message format depends on command impl.
|
|
35
|
-
expect(stdout).toContain('Project 101 updated!');
|
|
36
|
-
// expect(stdout).toContain('Name: Updated Project'); // CLI might not print details
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should delete project', async () => {
|
|
40
|
-
const { stdout } = await runCLI(['project', 'delete', '1', '101', '--confirm']);
|
|
41
|
-
expect(stdout).toContain('Project 101 deleted.');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should verify deletion', async () => {
|
|
45
|
-
const { stdout } = await runCLI(['project', 'list', '1']);
|
|
46
|
-
expect(stdout).not.toContain('ID: 101');
|
|
47
|
-
});
|
|
48
|
-
});
|