Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,139 @@ Map of internal field names to their values.
</tbody>
</table>

### `project.items.archive()`

```js
await project.items.archive(itemNodeId);
```

Archives a single item. Resolves with the archived item or with `undefined` if item was not found.

<table>
<thead align=left>
<tr>
<th>
name
</th>
<th>
type
</th>
<th width=100%>
description
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>itemNodeId</code>
</th>
<td>
<code>string</code>
</td>
<td>

**Required**. The graphql node ID of the project item

</td>
</tr>
</tbody>
</table>

### `project.items.archiveByContentId()`

```js
await project.items.archiveByContentId(contentId);
```

Archives a single item based on the Node ID of its linked issue or pull request. Resolves with the archived item or with `undefined` if item was not found.

<table>
<thead align=left>
<tr>
<th>
name
</th>
<th>
type
</th>
<th width=100%>
description
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>contentId</code>
</th>
<td>
<code>string</code>
</td>
<td>

**Required**. The graphql node ID of the issue/pull request the item is linked to.

</td>
</tr>
</tbody>
</table>

### `project.items.archiveByContentRepositoryAndNumber()`

```js
await project.items.archiveByContentRepositoryAndNumber(
repositoryName,
issueOrPullRequestNumber
);
```

Archives a single item based on the Node ID of its linked issue or pull request. Resolves with the archived item or with `undefined` if item was not found.

<table>
<thead align=left>
<tr>
<th>
name
</th>
<th>
type
</th>
<th width=100%>
description
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>repositoryName</code>
</th>
<td>
<code>string</code>
</td>
<td>

**Required**. The repository name, without the `owner/`.

</td>
</tr>
<tr>
<th>
<code>issueOrPullRequestNumber</code>
</th>
<td>
<code>number</code>
</td>
<td>

**Required**. The number of the issue or pull request.

</td>
</tr>
</tbody>
</table>

### `project.items.remove()`

```js
Expand Down
24 changes: 24 additions & 0 deletions api/items.archive-by-content-id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// @ts-check

import { getItemByContentId } from "./items.get-by-content-id.js";
import { archiveProjectItem } from "./lib/archive-project-item.js";

/**
* Archives an item based on content ID. Resolves with the archived item
* or with `undefined` if item was not found.
*
* @param {import("..").default} project
* @param {import("..").GitHubProjectState} state
* @param {string} contentId
*
* @returns {Promise<import("..").GitHubProjectItem | undefined>}
*/
export async function archiveItemByContentId(project, state, contentId) {
const item = await getItemByContentId(project, state, contentId);
if (!item) return;

if (item.isArchived) return item;

await archiveProjectItem(project, state, item.id);
return { ...item, isArchived: true };
}
35 changes: 35 additions & 0 deletions api/items.archive-by-content-repository-and-number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-check

import { getItemByContentRepositoryAndNumber } from "./items.get-by-content-repository-and-number.js";
import { archiveProjectItem } from "./lib/archive-project-item.js";

/**
* Removes an item based on content repository name and number.
* Resolves with the archived item or with `undefined` if item was not found.
*
* @param {import("..").default} project
* @param {import("..").GitHubProjectState} state
* @param {string} repositoryName
* @param {number} issueOrPullRequestNumber
*
* @returns {Promise<import("..").GitHubProjectItem | undefined>}
*/
export async function archiveItemByContentRepositoryAndNumber(
project,
state,
repositoryName,
issueOrPullRequestNumber
) {
const item = await getItemByContentRepositoryAndNumber(
project,
state,
repositoryName,
issueOrPullRequestNumber
);
if (!item) return;

if (item.isArchived) return item;

await archiveProjectItem(project, state, item.id);
return { ...item, isArchived: true };
}
24 changes: 24 additions & 0 deletions api/items.archive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// @ts-check

import { getItem } from "./items.get.js";
import { archiveProjectItem } from "./lib/archive-project-item.js";

/**
* Archives an item if it exists. Resolves with the archived item
* or with `undefined` if item was not found.
*
* @param {import("..").default} project
* @param {import("..").GitHubProjectState} state
* @param {string} itemNodeId
*
* @returns {Promise<import("..").GitHubProjectItem | undefined>}
*/
export async function archiveItem(project, state, itemNodeId) {
const item = await getItem(project, state, itemNodeId);
if (!item) return;

if (item.isArchived) return item;

await archiveProjectItem(project, state, item.id);
return { ...item, isArchived: true };
}
4 changes: 0 additions & 4 deletions api/items.get-by-content-id.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ import { handleNotFoundGraphqlError } from "./lib/handle-not-found-graphql-error
export async function getItemByContentId(project, state, contentId) {
const stateWithFields = await getStateWithProjectFields(project, state);

// TODO: ideally we would retrieve a project item directly based on a content id
// and the project number, but GitHub's GraphQL Schema does not support that
// as of 2022-08-14. As a workaround, we load all project items and filter
// them by project number afterwards.
const result = await project.octokit
.graphql(getItemByContentIdQuery, {
id: contentId,
Expand Down
4 changes: 0 additions & 4 deletions api/items.get-by-content-repository-and-number.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export async function getItemByContentRepositoryAndNumber(
) {
const stateWithFields = await getStateWithProjectFields(project, state);

// TODO: ideally we would retrieve a project item directly based on a content id
// and the project number, but GitHub's GraphQL Schema does not support that
// as of 2022-08-14. As a workaround, we load all project items and filter
// them by project number afterwards.
const result = await project.octokit
.graphql(getItemByContentRepositoryAndNameQuery, {
owner: project.owner,
Expand Down
26 changes: 26 additions & 0 deletions api/lib/archive-project-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @ts-check

import { getStateWithProjectFields } from "./get-state-with-project-fields.js";
import { handleNotFoundGraphqlError } from "./handle-not-found-graphql-error.js";
import { archiveItemMutation } from "./queries.js";

/**
* Helper method to archive an item from a project which is used
* by all the `project.items.archive*` methods.
*
* @param {import("../..").default} project
* @param {import("../..").GitHubProjectState} state
* @param {string} itemNodeId
*
* @returns {Promise<void>}
*/
export async function archiveProjectItem(project, state, itemNodeId) {
const stateWithFields = await getStateWithProjectFields(project, state);

await project.octokit
.graphql(archiveItemMutation, {
projectId: stateWithFields.id,
itemId: itemNodeId,
})
.catch(handleNotFoundGraphqlError);
}
8 changes: 8 additions & 0 deletions api/lib/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,11 @@ export const removeItemFromProjectMutation = `
}
}
`;

export const archiveItemMutation = `
mutation archiveItem($projectId: ID!, $itemId: ID!) {
archiveProjectV2Item(input:{projectId: $projectId, itemId: $itemId }) {
clientMutationId
}
}
`;
10 changes: 10 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ export default class GitHubProject<
issueOrPullRequestNumber: number,
fields: Partial<TItemFields>
): Promise<GitHubProjectItem<TItemFields> | undefined>;
archive(
itemNodeId: string
): Promise<GitHubProjectItem<TItemFields> | undefined>;
archiveByContentId(
contentNodeId: string
): Promise<GitHubProjectItem<TItemFields> | undefined>;
archiveByContentRepositoryAndNumber(
repositoryName: string,
issueOrPullRequestNumber: number
): Promise<GitHubProjectItem<TItemFields> | undefined>;
remove(
itemNodeId: string
): Promise<GitHubProjectItem<TItemFields> | undefined>;
Expand Down
7 changes: 7 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { getItemByContentRepositoryAndNumber } from "./api/items.get-by-content-
import { updateItem } from "./api/items.update.js";
import { updateItemByContentId } from "./api/items.update-by-content-id.js";
import { updateItemByContentRepositoryAndNumber } from "./api/items.update-by-content-repository-and-number.js";
import { archiveItem } from "./api/items.archive.js";
import { archiveItemByContentId } from "./api/items.archive-by-content-id.js";
import { archiveItemByContentRepositoryAndNumber } from "./api/items.archive-by-content-repository-and-number.js";
import { removeItem } from "./api/items.remove.js";
import { removeItemByContentId } from "./api/items.remove-by-content-id.js";
import { removeItemByContentRepositoryAndNumber } from "./api/items.remove-by-content-repository-and-name.js";
Expand Down Expand Up @@ -60,6 +63,10 @@ export default class GitHubProject {
updateByContentId: updateItemByContentId.bind(null, this, state),
updateByContentRepositoryAndNumber:
updateItemByContentRepositoryAndNumber.bind(null, this, state),
archive: archiveItem.bind(null, this, state),
archiveByContentId: archiveItemByContentId.bind(null, this, state),
archiveByContentRepositoryAndNumber:
archiveItemByContentRepositoryAndNumber.bind(null, this, state),
remove: removeItem.bind(null, this, state),
removeByContentId: removeItemByContentId.bind(null, this, state),
removeByContentRepositoryAndNumber:
Expand Down
51 changes: 51 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,57 @@ export async function updateItemByContentRepositoryAndNumberTest() {
}
}

export async function archiveItemTest() {
const project = new GitHubProject({
owner: "owner",
number: 1,
token: "gpg_secret123",
});
const item = await project.items.archive("item node id");

if (typeof item === "undefined") {
expectType<undefined>(item);
return;
}

expectType<string>(item.id);
}

export async function archiveItemByContentIdTest() {
const project = new GitHubProject({
owner: "owner",
number: 1,
token: "gpg_secret123",
});
const item = await project.items.archiveByContentId("content node id");

if (typeof item === "undefined") {
expectType<undefined>(item);
return;
}

expectType<string>(item.id);
}

export async function archiveItemByContentRepositoryAndNameTest() {
const project = new GitHubProject({
owner: "owner",
number: 1,
token: "gpg_secret123",
});
const item = await project.items.archiveByContentRepositoryAndNumber(
"repository-name",
1
);

if (typeof item === "undefined") {
expectType<undefined>(item);
return;
}

expectType<string>(item.id);
}

export async function removeItemTest() {
const project = new GitHubProject({
owner: "owner",
Expand Down
Loading