ardent-cli-beta 0.0.8 → 0.0.10
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 +9 -2
- package/dist/api/client.js +2 -0
- package/dist/commands/member/delete.d.ts +12 -0
- package/dist/commands/member/delete.js +48 -0
- package/dist/commands/member/invite.d.ts +13 -0
- package/dist/commands/member/invite.js +35 -0
- package/dist/commands/member/list.d.ts +10 -0
- package/dist/commands/member/list.js +41 -0
- package/dist/commands/project/delete.d.ts +12 -0
- package/dist/commands/project/delete.js +33 -0
- package/dist/members/client.d.ts +29 -0
- package/dist/members/client.js +114 -0
- package/dist/projects/client.d.ts +1 -0
- package/dist/projects/client.js +6 -0
- package/oclif.manifest.json +153 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,8 +11,10 @@ API token for CI and automation; `ARDENT_TOKEN` supplies the same flag
|
|
|
11
11
|
non-interactively. `ardent status` and `ardent logout` inspect and remove that
|
|
12
12
|
local session. The CLI always talks to Ardent's production control plane. Oclif
|
|
13
13
|
provides help, version, autocomplete, and native JSON command behavior. Resource
|
|
14
|
-
context is retained from login. Project listing, creation, and local
|
|
15
|
-
switching are implemented
|
|
14
|
+
context is retained from login. Project listing, creation, deletion, and local
|
|
15
|
+
context switching are implemented. Organization member listing, invitation,
|
|
16
|
+
removal, and pending-invitation cancellation are implemented; other resource
|
|
17
|
+
commands are not implemented yet.
|
|
16
18
|
|
|
17
19
|
Set `ARDENT_API_URL` to point the CLI at a development control plane. Without
|
|
18
20
|
it, the CLI uses `https://production.tryardent.com`.
|
|
@@ -26,6 +28,11 @@ npm run build
|
|
|
26
28
|
./bin/run.js project list
|
|
27
29
|
./bin/run.js project create "My project"
|
|
28
30
|
./bin/run.js project switch "My project"
|
|
31
|
+
./bin/run.js project delete "My project"
|
|
32
|
+
./bin/run.js member list
|
|
33
|
+
./bin/run.js member invite teammate@example.com
|
|
34
|
+
./bin/run.js member invite administrator@example.com --role admin
|
|
35
|
+
./bin/run.js member delete teammate@example.com
|
|
29
36
|
ARDENT_API_URL=http://localhost:8080 ./bin/run.js login --token <token>
|
|
30
37
|
```
|
|
31
38
|
|
package/dist/api/client.js
CHANGED
|
@@ -48,6 +48,8 @@ async function requestJSON(path, init) {
|
|
|
48
48
|
}
|
|
49
49
|
throw new APIError(detail.message ?? `Ardent API request failed with HTTP ${response.status}.`, response.status, detail.error);
|
|
50
50
|
}
|
|
51
|
+
if (response.status === 204)
|
|
52
|
+
return undefined;
|
|
51
53
|
try {
|
|
52
54
|
return JSON.parse(text);
|
|
53
55
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ArdentCommand } from '../../command.js';
|
|
2
|
+
export default class MemberDelete extends ArdentCommand {
|
|
3
|
+
static args: {
|
|
4
|
+
email: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static helpGroup: string;
|
|
8
|
+
run(): Promise<{
|
|
9
|
+
email: string;
|
|
10
|
+
status: 'active' | 'pending';
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { loadSession } from '../../auth/credentials.js';
|
|
3
|
+
import { ArdentCommand } from '../../command.js';
|
|
4
|
+
import { deleteInvitation, deleteMembership, listInvitations, listMemberships } from '../../members/client.js';
|
|
5
|
+
import { terminalText } from '../../terminal.js';
|
|
6
|
+
export default class MemberDelete extends ArdentCommand {
|
|
7
|
+
static args = {
|
|
8
|
+
email: Args.string({ description: 'Member or pending invitation email', required: true }),
|
|
9
|
+
};
|
|
10
|
+
static description = 'Delete a member or pending invitation by email';
|
|
11
|
+
static helpGroup = 'Members';
|
|
12
|
+
async run() {
|
|
13
|
+
const { args } = await this.parse(MemberDelete);
|
|
14
|
+
const email = args.email.trim().toLowerCase();
|
|
15
|
+
if (!email)
|
|
16
|
+
this.error('Email cannot be empty.');
|
|
17
|
+
const session = await loadSession(this.config.configDir);
|
|
18
|
+
if (!session?.organization)
|
|
19
|
+
this.error('You must be logged in to run this command. Run ardent login.');
|
|
20
|
+
const [memberships, invitations] = await Promise.all([
|
|
21
|
+
listMemberships(session.token, session.organization.id),
|
|
22
|
+
listInvitations(session.token, session.organization.id),
|
|
23
|
+
]);
|
|
24
|
+
const matchingMemberships = memberships.filter((candidate) => candidate.email.toLowerCase() === email);
|
|
25
|
+
const matchingInvitations = invitations.filter((candidate) => candidate.email.toLowerCase() === email);
|
|
26
|
+
if (matchingMemberships.length + matchingInvitations.length > 1) {
|
|
27
|
+
this.error(`Multiple active members or pending invitations match ${JSON.stringify(email)}.`);
|
|
28
|
+
}
|
|
29
|
+
const [membership] = matchingMemberships;
|
|
30
|
+
const [invitation] = matchingInvitations;
|
|
31
|
+
if (membership) {
|
|
32
|
+
if (!this.jsonEnabled())
|
|
33
|
+
this.log(`Deleting member ${terminalText(membership.email)}...`);
|
|
34
|
+
await deleteMembership(session.token, session.organization.id, membership.user_id);
|
|
35
|
+
if (!this.jsonEnabled())
|
|
36
|
+
this.log(`✓ Deleted member ${terminalText(membership.email)}`);
|
|
37
|
+
return { email: membership.email, status: 'active' };
|
|
38
|
+
}
|
|
39
|
+
if (!invitation)
|
|
40
|
+
this.error(`Member ${JSON.stringify(email)} not found.`);
|
|
41
|
+
if (!this.jsonEnabled())
|
|
42
|
+
this.log(`Canceling invitation for ${terminalText(invitation.email)}...`);
|
|
43
|
+
await deleteInvitation(session.token, session.organization.id, invitation.id);
|
|
44
|
+
if (!this.jsonEnabled())
|
|
45
|
+
this.log(`✓ Canceled invitation for ${terminalText(invitation.email)}`);
|
|
46
|
+
return { email: invitation.email, status: 'pending' };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ArdentCommand } from '../../command.js';
|
|
2
|
+
import { type Invitation } from '../../members/client.js';
|
|
3
|
+
export default class MemberInvite extends ArdentCommand {
|
|
4
|
+
static args: {
|
|
5
|
+
email: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static helpGroup: string;
|
|
9
|
+
static flags: {
|
|
10
|
+
role: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<Invitation>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { loadSession } from '../../auth/credentials.js';
|
|
3
|
+
import { ArdentCommand } from '../../command.js';
|
|
4
|
+
import { inviteMember } from '../../members/client.js';
|
|
5
|
+
import { terminalText } from '../../terminal.js';
|
|
6
|
+
const roles = {
|
|
7
|
+
admin: 'Admin',
|
|
8
|
+
member: 'Member',
|
|
9
|
+
owner: 'Owner',
|
|
10
|
+
viewer: 'Viewer',
|
|
11
|
+
};
|
|
12
|
+
export default class MemberInvite extends ArdentCommand {
|
|
13
|
+
static args = {
|
|
14
|
+
email: Args.string({ description: 'Email address to invite', required: true }),
|
|
15
|
+
};
|
|
16
|
+
static description = 'Invite a member to the organization';
|
|
17
|
+
static helpGroup = 'Members';
|
|
18
|
+
static flags = {
|
|
19
|
+
role: Flags.string({ default: 'member', description: 'Role to grant', options: Object.keys(roles) }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(MemberInvite);
|
|
23
|
+
const email = args.email.trim().toLowerCase();
|
|
24
|
+
if (!email)
|
|
25
|
+
this.error('Email cannot be empty.');
|
|
26
|
+
const session = await loadSession(this.config.configDir);
|
|
27
|
+
if (!session?.organization)
|
|
28
|
+
this.error('You must be logged in to run this command. Run ardent login.');
|
|
29
|
+
const role = roles[flags.role];
|
|
30
|
+
const invitation = await inviteMember(session.token, session.organization.id, email, role);
|
|
31
|
+
if (!this.jsonEnabled())
|
|
32
|
+
this.log(`✓ Invited ${terminalText(invitation.email)} as ${terminalText(invitation.role_display_name)}`);
|
|
33
|
+
return invitation;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ArdentCommand } from '../../command.js';
|
|
2
|
+
import { type Invitation, type Membership } from '../../members/client.js';
|
|
3
|
+
export default class MemberList extends ArdentCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static helpGroup: string;
|
|
6
|
+
run(): Promise<{
|
|
7
|
+
invitations: Invitation[] | null;
|
|
8
|
+
memberships: Membership[];
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { loadSession } from '../../auth/credentials.js';
|
|
2
|
+
import { ArdentCommand } from '../../command.js';
|
|
3
|
+
import { listMemberships, listReadableInvitations } from '../../members/client.js';
|
|
4
|
+
import { terminalText } from '../../terminal.js';
|
|
5
|
+
export default class MemberList extends ArdentCommand {
|
|
6
|
+
static description = 'List organization members and pending invitations';
|
|
7
|
+
static helpGroup = 'Members';
|
|
8
|
+
async run() {
|
|
9
|
+
const session = await loadSession(this.config.configDir);
|
|
10
|
+
if (!session?.organization)
|
|
11
|
+
this.error('You must be logged in to run this command. Run ardent login.');
|
|
12
|
+
const [memberships, invitations] = await Promise.all([
|
|
13
|
+
listMemberships(session.token, session.organization.id),
|
|
14
|
+
listReadableInvitations(session.token, session.organization.id),
|
|
15
|
+
]);
|
|
16
|
+
const readableInvitations = invitations ?? [];
|
|
17
|
+
if (!this.jsonEnabled()) {
|
|
18
|
+
const rows = [
|
|
19
|
+
...memberships.map((membership) => ({
|
|
20
|
+
email: terminalText(membership.email),
|
|
21
|
+
role: terminalText(membership.role_display_name),
|
|
22
|
+
status: 'Active',
|
|
23
|
+
})),
|
|
24
|
+
...readableInvitations.map((invitation) => ({
|
|
25
|
+
email: terminalText(invitation.email),
|
|
26
|
+
role: terminalText(invitation.role_display_name),
|
|
27
|
+
status: 'Pending',
|
|
28
|
+
})),
|
|
29
|
+
];
|
|
30
|
+
if (rows.length === 0)
|
|
31
|
+
this.log('No members found.');
|
|
32
|
+
const emailWidth = Math.max(0, ...rows.map(({ email }) => email.length));
|
|
33
|
+
const roleWidth = Math.max(0, ...rows.map(({ role }) => role.length));
|
|
34
|
+
for (const row of rows)
|
|
35
|
+
this.log(`${row.email.padEnd(emailWidth)} ${row.role.padEnd(roleWidth)} ${row.status}`);
|
|
36
|
+
if (invitations === undefined)
|
|
37
|
+
this.log('Pending invitations are not visible with this login.');
|
|
38
|
+
}
|
|
39
|
+
return { invitations: invitations ?? null, memberships };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ArdentCommand } from '../../command.js';
|
|
2
|
+
export default class ProjectDelete extends ArdentCommand {
|
|
3
|
+
static args: {
|
|
4
|
+
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static helpGroup: string;
|
|
8
|
+
run(): Promise<{
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { loadSession } from '../../auth/credentials.js';
|
|
3
|
+
import { ArdentCommand } from '../../command.js';
|
|
4
|
+
import { deleteProject, listProjects } from '../../projects/client.js';
|
|
5
|
+
import { replaceProjectCache } from '../../projects/context.js';
|
|
6
|
+
import { terminalText } from '../../terminal.js';
|
|
7
|
+
export default class ProjectDelete extends ArdentCommand {
|
|
8
|
+
static args = {
|
|
9
|
+
name: Args.string({ description: 'Project name', required: true }),
|
|
10
|
+
};
|
|
11
|
+
static description = 'Delete a project by name';
|
|
12
|
+
static helpGroup = 'Projects';
|
|
13
|
+
async run() {
|
|
14
|
+
const { args } = await this.parse(ProjectDelete);
|
|
15
|
+
const name = args.name.trim();
|
|
16
|
+
if (!name)
|
|
17
|
+
this.error('Project name cannot be empty.');
|
|
18
|
+
const session = await loadSession(this.config.configDir);
|
|
19
|
+
if (!session?.organization)
|
|
20
|
+
this.error('You must be logged in to run this command. Run ardent login.');
|
|
21
|
+
const projects = await listProjects(session.token, session.organization.id);
|
|
22
|
+
const project = projects.find((candidate) => candidate.name === name);
|
|
23
|
+
if (!project)
|
|
24
|
+
this.error(`Project ${JSON.stringify(name)} not found.`);
|
|
25
|
+
if (!this.jsonEnabled())
|
|
26
|
+
this.log(`Deleting project ${terminalText(project.name)}...`);
|
|
27
|
+
await deleteProject(session.token, session.organization.id, project.id);
|
|
28
|
+
await replaceProjectCache(this.config.configDir, session, projects.filter(({ id }) => id !== project.id));
|
|
29
|
+
if (!this.jsonEnabled())
|
|
30
|
+
this.log(`✓ Deleted project ${terminalText(project.name)}`);
|
|
31
|
+
return { id: project.id, name: project.name };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type OrganizationRole = 'Admin' | 'Member' | 'Owner' | 'Viewer';
|
|
2
|
+
export interface Membership {
|
|
3
|
+
created_at: string;
|
|
4
|
+
email: string;
|
|
5
|
+
full_name: string | null;
|
|
6
|
+
organization_id: string;
|
|
7
|
+
role_display_name: string;
|
|
8
|
+
scopes: string[];
|
|
9
|
+
updated_at: string;
|
|
10
|
+
user_id: string;
|
|
11
|
+
}
|
|
12
|
+
export interface Invitation {
|
|
13
|
+
created_at: string;
|
|
14
|
+
created_by: string | null;
|
|
15
|
+
email: string;
|
|
16
|
+
expires_at: string;
|
|
17
|
+
id: string;
|
|
18
|
+
inviter_name: string | null;
|
|
19
|
+
organization_id: string;
|
|
20
|
+
organization_name: string;
|
|
21
|
+
role_display_name: string;
|
|
22
|
+
scopes: string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function listMemberships(token: string, organizationID: string): Promise<Membership[]>;
|
|
25
|
+
export declare function listInvitations(token: string, organizationID: string): Promise<Invitation[]>;
|
|
26
|
+
export declare function listReadableInvitations(token: string, organizationID: string): Promise<Invitation[] | undefined>;
|
|
27
|
+
export declare function inviteMember(token: string, organizationID: string, email: string, role: OrganizationRole): Promise<Invitation>;
|
|
28
|
+
export declare function deleteMembership(token: string, organizationID: string, userID: string): Promise<void>;
|
|
29
|
+
export declare function deleteInvitation(token: string, organizationID: string, invitationID: string): Promise<void>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { APIError, request } from '../api/client.js';
|
|
3
|
+
const sharedReadScopes = [
|
|
4
|
+
'organizations.read',
|
|
5
|
+
'organization_memberships.read',
|
|
6
|
+
'projects.read',
|
|
7
|
+
'environments.read',
|
|
8
|
+
'connectors.read',
|
|
9
|
+
];
|
|
10
|
+
const adminScopes = [
|
|
11
|
+
'organizations.read',
|
|
12
|
+
'organization_memberships.read',
|
|
13
|
+
'organization_memberships.update',
|
|
14
|
+
'organization_invitations.read',
|
|
15
|
+
'organization_invitations.create',
|
|
16
|
+
'organization_invitations.delete',
|
|
17
|
+
'projects.read',
|
|
18
|
+
'projects.create',
|
|
19
|
+
'projects.update',
|
|
20
|
+
'projects.delete',
|
|
21
|
+
'environments.read',
|
|
22
|
+
'environments.create',
|
|
23
|
+
'connectors.read',
|
|
24
|
+
'connectors.create',
|
|
25
|
+
'environments.update',
|
|
26
|
+
'branches.connect',
|
|
27
|
+
'billing.read',
|
|
28
|
+
'api_keys.read',
|
|
29
|
+
'api_keys.create',
|
|
30
|
+
'api_keys.revoke',
|
|
31
|
+
];
|
|
32
|
+
const standardRoleScopes = {
|
|
33
|
+
Owner: adminScopes.flatMap((scope) => (scope === 'billing.read' ? [scope, 'billing.manage'] : [scope])),
|
|
34
|
+
Admin: adminScopes,
|
|
35
|
+
Member: [...sharedReadScopes, 'projects.create', 'connectors.create', 'branches.connect'],
|
|
36
|
+
Viewer: sharedReadScopes,
|
|
37
|
+
};
|
|
38
|
+
export async function listMemberships(token, organizationID) {
|
|
39
|
+
const memberships = await request(token, `/organizations/${encodeURIComponent(organizationID)}/memberships`);
|
|
40
|
+
if (!Array.isArray(memberships) || memberships.some((membership) => !isMembership(membership, organizationID))) {
|
|
41
|
+
throw new Error('Ardent API returned an invalid memberships response.');
|
|
42
|
+
}
|
|
43
|
+
return memberships;
|
|
44
|
+
}
|
|
45
|
+
export async function listInvitations(token, organizationID) {
|
|
46
|
+
const invitations = await request(token, `/organizations/${encodeURIComponent(organizationID)}/invitations`);
|
|
47
|
+
if (!Array.isArray(invitations) || invitations.some((invitation) => !isInvitation(invitation, organizationID))) {
|
|
48
|
+
throw new Error('Ardent API returned an invalid invitations response.');
|
|
49
|
+
}
|
|
50
|
+
return invitations;
|
|
51
|
+
}
|
|
52
|
+
export async function listReadableInvitations(token, organizationID) {
|
|
53
|
+
try {
|
|
54
|
+
return await listInvitations(token, organizationID);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof APIError && error.status === 403 && error.code === 'permission_denied')
|
|
58
|
+
return undefined;
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function inviteMember(token, organizationID, email, role) {
|
|
63
|
+
const invitation = await request(token, `/organizations/${encodeURIComponent(organizationID)}/invitations`, {
|
|
64
|
+
body: JSON.stringify({ email, role_display_name: role, scopes: standardRoleScopes[role] }),
|
|
65
|
+
headers: { 'Idempotency-Key': randomUUID() },
|
|
66
|
+
method: 'POST',
|
|
67
|
+
});
|
|
68
|
+
if (!isInvitation(invitation, organizationID))
|
|
69
|
+
throw new Error('Ardent API returned an invalid invitation response.');
|
|
70
|
+
return invitation;
|
|
71
|
+
}
|
|
72
|
+
export async function deleteMembership(token, organizationID, userID) {
|
|
73
|
+
const response = await request(token, `/organizations/${encodeURIComponent(organizationID)}/memberships/${encodeURIComponent(userID)}`, { method: 'DELETE' });
|
|
74
|
+
if (response !== undefined)
|
|
75
|
+
throw new Error('Ardent API did not confirm member deletion. Run ardent member list before retrying.');
|
|
76
|
+
}
|
|
77
|
+
export async function deleteInvitation(token, organizationID, invitationID) {
|
|
78
|
+
const response = await request(token, `/organizations/${encodeURIComponent(organizationID)}/invitations/${encodeURIComponent(invitationID)}`, { method: 'DELETE' });
|
|
79
|
+
if (response !== undefined)
|
|
80
|
+
throw new Error('Ardent API did not confirm invitation cancellation. Run ardent member list before retrying.');
|
|
81
|
+
}
|
|
82
|
+
function isMembership(value, organizationID) {
|
|
83
|
+
if (typeof value !== 'object' || value === null)
|
|
84
|
+
return false;
|
|
85
|
+
const membership = value;
|
|
86
|
+
return (membership.organization_id === organizationID &&
|
|
87
|
+
typeof membership.user_id === 'string' &&
|
|
88
|
+
membership.user_id.length > 0 &&
|
|
89
|
+
typeof membership.email === 'string' &&
|
|
90
|
+
(membership.full_name === null || typeof membership.full_name === 'string') &&
|
|
91
|
+
typeof membership.role_display_name === 'string' &&
|
|
92
|
+
stringArray(membership.scopes) &&
|
|
93
|
+
typeof membership.created_at === 'string' &&
|
|
94
|
+
typeof membership.updated_at === 'string');
|
|
95
|
+
}
|
|
96
|
+
function isInvitation(value, organizationID) {
|
|
97
|
+
if (typeof value !== 'object' || value === null)
|
|
98
|
+
return false;
|
|
99
|
+
const invitation = value;
|
|
100
|
+
return (invitation.organization_id === organizationID &&
|
|
101
|
+
typeof invitation.id === 'string' &&
|
|
102
|
+
invitation.id.length > 0 &&
|
|
103
|
+
typeof invitation.organization_name === 'string' &&
|
|
104
|
+
typeof invitation.email === 'string' &&
|
|
105
|
+
typeof invitation.role_display_name === 'string' &&
|
|
106
|
+
stringArray(invitation.scopes) &&
|
|
107
|
+
typeof invitation.expires_at === 'string' &&
|
|
108
|
+
(invitation.created_by === null || typeof invitation.created_by === 'string') &&
|
|
109
|
+
(invitation.inviter_name === null || typeof invitation.inviter_name === 'string') &&
|
|
110
|
+
typeof invitation.created_at === 'string');
|
|
111
|
+
}
|
|
112
|
+
function stringArray(value) {
|
|
113
|
+
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
114
|
+
}
|
|
@@ -7,3 +7,4 @@ export interface Project {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function listProjects(token: string, organizationID: string): Promise<Project[]>;
|
|
9
9
|
export declare function createProject(token: string, organizationID: string, name: string): Promise<Project>;
|
|
10
|
+
export declare function deleteProject(token: string, organizationID: string, projectID: string): Promise<void>;
|
package/dist/projects/client.js
CHANGED
|
@@ -17,6 +17,12 @@ export async function createProject(token, organizationID, name) {
|
|
|
17
17
|
throw new Error('Ardent API returned an invalid project response.');
|
|
18
18
|
return project;
|
|
19
19
|
}
|
|
20
|
+
export async function deleteProject(token, organizationID, projectID) {
|
|
21
|
+
const response = await request(token, `/projects/${encodeURIComponent(projectID)}?organization_id=${encodeURIComponent(organizationID)}`, { method: 'DELETE' });
|
|
22
|
+
if (response !== undefined) {
|
|
23
|
+
throw new Error('Ardent API did not confirm project deletion. Run ardent project list before retrying.');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
20
26
|
function isProject(value, organizationID) {
|
|
21
27
|
if (typeof value !== 'object' || value === null)
|
|
22
28
|
return false;
|
package/oclif.manifest.json
CHANGED
|
@@ -95,6 +95,122 @@
|
|
|
95
95
|
"status.js"
|
|
96
96
|
]
|
|
97
97
|
},
|
|
98
|
+
"member:delete": {
|
|
99
|
+
"aliases": [],
|
|
100
|
+
"args": {
|
|
101
|
+
"email": {
|
|
102
|
+
"description": "Member or pending invitation email",
|
|
103
|
+
"name": "email",
|
|
104
|
+
"required": true
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"description": "Delete a member or pending invitation by email",
|
|
108
|
+
"flags": {
|
|
109
|
+
"json": {
|
|
110
|
+
"description": "Format output as json.",
|
|
111
|
+
"helpGroup": "GLOBAL",
|
|
112
|
+
"name": "json",
|
|
113
|
+
"allowNo": false,
|
|
114
|
+
"type": "boolean"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"hasDynamicHelp": false,
|
|
118
|
+
"hiddenAliases": [],
|
|
119
|
+
"id": "member:delete",
|
|
120
|
+
"pluginAlias": "ardent-cli-beta",
|
|
121
|
+
"pluginName": "ardent-cli-beta",
|
|
122
|
+
"pluginType": "core",
|
|
123
|
+
"strict": true,
|
|
124
|
+
"enableJsonFlag": true,
|
|
125
|
+
"helpGroup": "Members",
|
|
126
|
+
"isESM": true,
|
|
127
|
+
"relativePath": [
|
|
128
|
+
"dist",
|
|
129
|
+
"commands",
|
|
130
|
+
"member",
|
|
131
|
+
"delete.js"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"member:invite": {
|
|
135
|
+
"aliases": [],
|
|
136
|
+
"args": {
|
|
137
|
+
"email": {
|
|
138
|
+
"description": "Email address to invite",
|
|
139
|
+
"name": "email",
|
|
140
|
+
"required": true
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"description": "Invite a member to the organization",
|
|
144
|
+
"flags": {
|
|
145
|
+
"json": {
|
|
146
|
+
"description": "Format output as json.",
|
|
147
|
+
"helpGroup": "GLOBAL",
|
|
148
|
+
"name": "json",
|
|
149
|
+
"allowNo": false,
|
|
150
|
+
"type": "boolean"
|
|
151
|
+
},
|
|
152
|
+
"role": {
|
|
153
|
+
"description": "Role to grant",
|
|
154
|
+
"name": "role",
|
|
155
|
+
"default": "member",
|
|
156
|
+
"hasDynamicHelp": false,
|
|
157
|
+
"multiple": false,
|
|
158
|
+
"options": [
|
|
159
|
+
"admin",
|
|
160
|
+
"member",
|
|
161
|
+
"owner",
|
|
162
|
+
"viewer"
|
|
163
|
+
],
|
|
164
|
+
"type": "option"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"hasDynamicHelp": false,
|
|
168
|
+
"hiddenAliases": [],
|
|
169
|
+
"id": "member:invite",
|
|
170
|
+
"pluginAlias": "ardent-cli-beta",
|
|
171
|
+
"pluginName": "ardent-cli-beta",
|
|
172
|
+
"pluginType": "core",
|
|
173
|
+
"strict": true,
|
|
174
|
+
"enableJsonFlag": true,
|
|
175
|
+
"helpGroup": "Members",
|
|
176
|
+
"isESM": true,
|
|
177
|
+
"relativePath": [
|
|
178
|
+
"dist",
|
|
179
|
+
"commands",
|
|
180
|
+
"member",
|
|
181
|
+
"invite.js"
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
"member:list": {
|
|
185
|
+
"aliases": [],
|
|
186
|
+
"args": {},
|
|
187
|
+
"description": "List organization members and pending invitations",
|
|
188
|
+
"flags": {
|
|
189
|
+
"json": {
|
|
190
|
+
"description": "Format output as json.",
|
|
191
|
+
"helpGroup": "GLOBAL",
|
|
192
|
+
"name": "json",
|
|
193
|
+
"allowNo": false,
|
|
194
|
+
"type": "boolean"
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"hasDynamicHelp": false,
|
|
198
|
+
"hiddenAliases": [],
|
|
199
|
+
"id": "member:list",
|
|
200
|
+
"pluginAlias": "ardent-cli-beta",
|
|
201
|
+
"pluginName": "ardent-cli-beta",
|
|
202
|
+
"pluginType": "core",
|
|
203
|
+
"strict": true,
|
|
204
|
+
"enableJsonFlag": true,
|
|
205
|
+
"helpGroup": "Members",
|
|
206
|
+
"isESM": true,
|
|
207
|
+
"relativePath": [
|
|
208
|
+
"dist",
|
|
209
|
+
"commands",
|
|
210
|
+
"member",
|
|
211
|
+
"list.js"
|
|
212
|
+
]
|
|
213
|
+
},
|
|
98
214
|
"project:create": {
|
|
99
215
|
"aliases": [],
|
|
100
216
|
"args": {
|
|
@@ -131,6 +247,42 @@
|
|
|
131
247
|
"create.js"
|
|
132
248
|
]
|
|
133
249
|
},
|
|
250
|
+
"project:delete": {
|
|
251
|
+
"aliases": [],
|
|
252
|
+
"args": {
|
|
253
|
+
"name": {
|
|
254
|
+
"description": "Project name",
|
|
255
|
+
"name": "name",
|
|
256
|
+
"required": true
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"description": "Delete a project by name",
|
|
260
|
+
"flags": {
|
|
261
|
+
"json": {
|
|
262
|
+
"description": "Format output as json.",
|
|
263
|
+
"helpGroup": "GLOBAL",
|
|
264
|
+
"name": "json",
|
|
265
|
+
"allowNo": false,
|
|
266
|
+
"type": "boolean"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
"hasDynamicHelp": false,
|
|
270
|
+
"hiddenAliases": [],
|
|
271
|
+
"id": "project:delete",
|
|
272
|
+
"pluginAlias": "ardent-cli-beta",
|
|
273
|
+
"pluginName": "ardent-cli-beta",
|
|
274
|
+
"pluginType": "core",
|
|
275
|
+
"strict": true,
|
|
276
|
+
"enableJsonFlag": true,
|
|
277
|
+
"helpGroup": "Projects",
|
|
278
|
+
"isESM": true,
|
|
279
|
+
"relativePath": [
|
|
280
|
+
"dist",
|
|
281
|
+
"commands",
|
|
282
|
+
"project",
|
|
283
|
+
"delete.js"
|
|
284
|
+
]
|
|
285
|
+
},
|
|
134
286
|
"project:list": {
|
|
135
287
|
"aliases": [],
|
|
136
288
|
"args": {},
|
|
@@ -198,5 +350,5 @@
|
|
|
198
350
|
]
|
|
199
351
|
}
|
|
200
352
|
},
|
|
201
|
-
"version": "0.0.
|
|
353
|
+
"version": "0.0.10"
|
|
202
354
|
}
|