diff --git a/.changeset/dirty-goats-prove.md b/.changeset/dirty-goats-prove.md
new file mode 100644
index 0000000..e2d9f65
--- /dev/null
+++ b/.changeset/dirty-goats-prove.md
@@ -0,0 +1,8 @@
+---
+"astro-loader-github-prs": minor
+---
+
+Add `monthsBack` option to specify the recent months for loading pull requests
+Support returning the `` component via `render(entry)` to render the PR content
+Errors no longer force the entire Astro project to terminate
+No longer calls `store.clear()` internally
diff --git a/packages/astro-loader-github-prs/README.md b/packages/astro-loader-github-prs/README.md
index eb4ad20..9ac77aa 100644
--- a/packages/astro-loader-github-prs/README.md
+++ b/packages/astro-loader-github-prs/README.md
@@ -4,7 +4,7 @@
[![jsDocs.io][jsdocs-src]][jsdocs-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
-This package provides a GitHub PRs loader for Astro, fetching pull requests via a GitHub search query for use in Astro projects.
+This package provides a GitHub PRs loader for Astro, fetching pull requests with a search query for use in Astro projects.
## Installation
@@ -21,55 +21,62 @@ export default defineConfig({
experimental: {
contentLayer: true,
},
-});
+})
```
-In `src/content/config.ts`, import and configure the GitHub PRs loader to define a new content collection:
+In `src/content/config.ts` (for `^4.14.0`) or `src/content.config.ts` (for `^5.0.0`), import and configure the GitHub PRs loader to define a new content collection:
```ts
-import { defineCollection } from "astro:content";
-import { githubPrsLoader } from "astro-loader-github-prs";
+import { defineCollection } from "astro:content"
+import { githubPrsLoader } from "astro-loader-github-prs"
const githubPrs = defineCollection({
loader: githubPrsLoader({
search: 'author:username created:>=2024-10-01',
}),
-});
+})
-export const collections = { githubPrs };
+export const collections = { githubPrs }
```
[Query the content collection](https://docs.astro.build/en/guides/content-collections/#querying-collections) like any other Astro content collection to render the loaded GitHub PRs:
```astro
---
-import { getCollection } from "astro:content";
+import { getCollection } from "astro:content"
-const prs = await getCollection("githubPrs");
+const prs = await getCollection("githubPrs")
---
-
+{
+ prs.map(async (pr) => {
+ const { Content } = await render(pr)
+ return (
+
+ )
+ })
+}
```
-To update the data, trigger a site rebuild, as [the loader fetches data only at build time](https://docs.astro.build/en/reference/content-loader-reference/#object-loaders).
+To update the data, trigger a site rebuild (e.g., using a third-party cron job service), as [the loader fetches data only at build time](https://docs.astro.build/en/reference/content-loader-reference/#object-loaders).
## Configuration
-The loader fetches PRs via the GitHub GraphQL API with a search string, requiring a `repo`-scoped PAT, and returns up to 1,000 results. Options include:
+The loader fetches PRs via the GitHub GraphQL API with a search string, requiring a repo-scoped PAT, and [returns up to 1,000 results](https://docs.github.com/en/graphql/reference/objects#searchresultitemconnection). Options include:
-| Option (* required) | Type (defaults) | Description |
-| ------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `search`* | `string` | The search string for querying pull requests on GitHub. This string will be concatenated with `type:pr` to form the complete search query. See [how to search pull requests](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests). For examples:
`'author:xxx created:>=2024-01-01'`: matches prs written by xxx that were created after 2024.
`'author:xxx -user:xxx'`: matches prs written by xxx, but not to their own repositories. |
-| `githubToken` | `string` (defaults: `'import.meta.env.GITHUB_TOKEN'`) | A GitHub PAT with at least `repo` scope permissions. Defaults to the `GITHUB_TOKEN` environment variable. **If configured here, keep confidential and avoid public exposure.** See [how to create one](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) and [configure env vars in an Astro project](https://docs.astro.build/en/guides/environment-variables/#setting-environment-variables). |
+| Option (* required) | Type (default) | Description |
+| ------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `search`* | `string` | The search string for querying pull requests on GitHub. This string will be concatenated with `type:pr` to form the complete search query. See [how to search pull requests](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests). For examples:
`'author:xxx created:>=2024-01-01'`: matches prs written by xxx that were created after 2024.
`'author:xxx -user:xxx'`: matches prs written by xxx, but not to their own repositories. |
+| `monthsBack` | `number` | The number of recent months to load pull requests, including the current month. The loader automatically converts this to a date for the 'created' qualifier in the search query. If the `'created'` qualifier is defined in search option, it will override this value. |
+| `githubToken` | `string` (Defaults to the `GITHUB_TOKEN` environment variable) | A GitHub PAT with at least `repo` scope permissions. Defaults to the `GITHUB_TOKEN` environment variable. **If configured here, keep confidential and avoid public exposure.** See [how to create one](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) and [configure env vars in an Astro project](https://docs.astro.build/en/guides/environment-variables/#setting-environment-variables). |
## Schema
@@ -109,15 +116,20 @@ const GithubPrSchema = z.object({
})
```
-Astro automatically applies this schema to generate TypeScript interfaces, providing full support for autocompletion and type-checking when querying the collection.
+Astro automatically applies these schemas to generate TypeScript interfaces, enabling autocompletion and type-checking for collection queries. If you [customize the collection schema](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema), ensure compatibility with the loader's built-in Zod schema to prevent errors. For additional fields, consider opening an issue.
+
+## Changelog
-If you need to [customize the collection schema](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema), ensure it remains compatible with the built-in Zod schema of the loader to avoid errors. For additional fields you'd like to fetch, feel free to [open an issue](https://github.com/lin-stephanie/astro-loaders/issues).
+See [CHANGELOG.md](CHANGELOG.md) for the change history of this loader.
+## Contribution
-[version-badge]: https://img.shields.io/npm/v/astro-loader-github-prs?label=release&style=flat&colorA=080f12&colorB=ef7575
+If you see any errors or room for improvement, feel free to open an [issues](https://github.com/lin-stephanie/astro-loaders/issues) or [pull request](https://github.com/lin-stephanie/astro-loaders/pulls) . Thank you in advance for contributing! ❤️
+
+
+[version-badge]: https://img.shields.io/npm/v/astro-loader-github-prs?label=release&style=flat&colorA=080f12&colorB=f87171
[version-link]: https://www.npmjs.com/package/astro-loader-github-prs
-[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=ef7575
+[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=f87171
[jsdocs-href]: https://www.jsdocs.io/package/astro-loader-github-prs
-[npm-downloads-src]: https://img.shields.io/npm/dm/astro-loader-github-prs?style=flat&colorA=080f12&colorB=ef7575
+[npm-downloads-src]: https://img.shields.io/npm/dm/astro-loader-github-prs?style=flat&colorA=080f12&colorB=f87171
[npm-downloads-href]: https://npmjs.com/package/astro-loader-github-prs
-
diff --git a/packages/astro-loader-github-prs/package.json b/packages/astro-loader-github-prs/package.json
index 2f6d296..700c567 100644
--- a/packages/astro-loader-github-prs/package.json
+++ b/packages/astro-loader-github-prs/package.json
@@ -1,7 +1,7 @@
{
"name": "astro-loader-github-prs",
"version": "1.0.2",
- "description": "Aatro loader for loading GitHub pull reuqests from a given search string.",
+ "description": "Astro loader for loading GitHub pull requests with a search query.",
"author": "Stephanie Lin ",
"license": "MIT",
"keywords": [
diff --git a/packages/astro-loader-github-prs/src/config.ts b/packages/astro-loader-github-prs/src/config.ts
index e46bf1f..c281331 100644
--- a/packages/astro-loader-github-prs/src/config.ts
+++ b/packages/astro-loader-github-prs/src/config.ts
@@ -15,6 +15,21 @@ export const GithubPrsLoaderConfigSchema = z.object({
*/
search: z.string(),
+ /**
+ * The number of recent months to load pull requests, including the current month.
+ * The loader automatically converts this to a date for the 'created' qualifier in the search query.
+ *
+ * If the {@link https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-when-an-issue-or-pull-request-was-created-or-last-updated 'created'}
+ * qualifier is defined in `search` option, it will override this value.
+ *
+ * For example, setting to `3` on December 4, 2024, would yield: 'type:pr created:>=2024-10-01 ...'.
+ */
+ monthsBack: z
+ .number()
+ .int({ message: '`monthsBack` must be an integer' })
+ .positive({ message: '`monthsBack` must be a positive integer' })
+ .optional(),
+
/**
* You need to {@link https://github.com/settings/tokens create a GitHub PAT}
* with at least `repo` scope permissions to authenticate requests to the GraphQL API.
@@ -27,7 +42,7 @@ export const GithubPrsLoaderConfigSchema = z.object({
* - {@link https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic How to create a GitHub PAT (classic)}
* - {@link https://docs.astro.build/en/guides/environment-variables/#setting-environment-variables How to store GitHub PAT in Astro project environment variables}
*/
- githubToken: z.string().default(import.meta.env.GITHUB_TOKEN),
+ githubToken: z.string().optional(),
})
export type GithubPrsLoaderUserConfig = z.input<
diff --git a/packages/astro-loader-github-prs/src/index.ts b/packages/astro-loader-github-prs/src/index.ts
index dba9712..1baedcd 100644
--- a/packages/astro-loader-github-prs/src/index.ts
+++ b/packages/astro-loader-github-prs/src/index.ts
@@ -1,11 +1,11 @@
-import { AstroError } from 'astro/errors'
-import { Octokit } from 'octokit'
-
import { readFileSync } from 'node:fs'
+import { Octokit } from 'octokit'
+
import pkg from '../package.json' with { type: 'json' }
import { GithubPrsLoaderConfigSchema } from './config.js'
import { GithubPrSchema } from './schema.js'
+import { getQueryWithMonthsBack } from './utils.js'
import type { Loader } from 'astro/loaders'
import type { GithubPrsLoaderUserConfig } from './config.js'
@@ -13,47 +13,52 @@ import type { GetPrsQuery, GetPrsQueryVariables } from './graphql/types.js'
import type { GithubPr } from './schema.js'
/**
- * Aatro loader for loading GitHub pull reuqests from a given search string.
+ * Astro loader for loading GitHub pull requests with a search query.
*
* @see https://github.com/lin-stephanie/astro-loaders/tree/main/packages/astro-loader-github-prs
*/
function githubPrsLoader(userConfig: GithubPrsLoaderUserConfig): Loader {
- const parsedConfig = GithubPrsLoaderConfigSchema.safeParse(userConfig)
- if (!parsedConfig.success) {
- throw new AstroError(
- `The configuration provided in '${pkg.name}' is invalid. Refer to the following error report or access configuration details for this loader here: ${pkg.homepage}#configuration.`,
- `${parsedConfig.error.issues.map((issue) => issue.message).join('\n')}`
- )
- }
- const parsedUserConfig = parsedConfig.data
-
return {
name: pkg.name,
schema: GithubPrSchema,
- async load({ logger, store, parseData }) {
- const { search, githubToken } = parsedUserConfig
- const prs: GithubPr[] = []
- const query = `type:pr ${search}`
- logger.info(
- `Loading GitHub pull reuqests based on the search string: '${query}'`
- )
+ async load({ logger, store, parseData, generateDigest }) {
+ const parsedConfig = GithubPrsLoaderConfigSchema.safeParse(userConfig)
+ if (!parsedConfig.success) {
+ logger.error(
+ `The configuration provided is invalid. ${parsedConfig.error.issues.map((issue) => issue.message).join('\n')}.
+Check out the configuration: ${pkg.homepage}README.md#configuration.`
+ )
+ return
+ }
+ const { search, monthsBack, githubToken } = parsedConfig.data
const token = githubToken || import.meta.env.GITHUB_TOKEN
+
+ if (search.length === 0) {
+ logger.warn(
+ 'Search string is empty and no pull requests will be loaded'
+ )
+ return
+ }
+
if (!token) {
- throw new AstroError(
- 'No GitHub token provided. Please provide a `githubToken` or set the `GITHUB_TOKEN` environment variable.',
- `How to create a GitHub PAT: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic.
-How to store GitHub PAT in Astro project environment variables: https://docs.astro.build/en/guides/environment-variables/#setting-environment-variables`
+ logger.error(
+ 'No GitHub token provided. Please provide a `githubToken` or set the `GITHUB_TOKEN` environment variable.\nHow to create a GitHub PAT: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic.\nHow to store token in Astro project environment variables: https://docs.astro.build/en/guides/environment-variables/#setting-environment-variables.'
)
+ return
}
- const octokit = new Octokit({
- auth: githubToken || import.meta.env.GITHUB_TOKEN,
- })
+ const prs: GithubPr[] = []
+ const parsedSearch = getQueryWithMonthsBack(search, monthsBack)
const getPrsQuery = readFileSync(
new URL('./graphql/query.graphql', import.meta.url),
'utf8'
)
+ const octokit = new Octokit({ auth: token })
+
+ logger.info(
+ `Loading GitHub pull requests with a search query: '${parsedSearch}'`
+ )
try {
let hasNextPage = true
@@ -61,7 +66,7 @@ How to store GitHub PAT in Astro project environment variables: https://docs.ast
while (hasNextPage) {
const variables: GetPrsQueryVariables = {
- search: query,
+ search: parsedSearch,
first: 100,
cursor,
}
@@ -115,20 +120,23 @@ How to store GitHub PAT in Astro project environment variables: https://docs.ast
hasNextPage = res.search.pageInfo.hasNextPage || false
cursor = res.search.pageInfo.endCursor || null
}
- } catch (error) {
- throw new AstroError(
- `Failed to load GitHub pull requests: ${(error as Error).message}`
- )
- }
- store.clear()
+ for (const item of prs) {
+ const parsedItem = await parseData({ id: item.id, data: item })
+ store.set({
+ id: item.id,
+ data: parsedItem,
+ rendered: { html: item.bodyHTML },
+ digest: generateDigest(parsedItem),
+ })
+ }
- for (const item of prs) {
- const parsedItem = await parseData({ id: item.id, data: item })
- store.set({ id: item.id, data: parsedItem })
+ logger.info('Successfully loaded GitHub pull requests')
+ } catch (error) {
+ logger.error(
+ `Failed to load GitHub pull requests. ${(error as Error).message}`
+ )
}
-
- logger.info('Successfully loaded GitHub pull requests')
},
}
}
diff --git a/packages/astro-loader-github-prs/src/utils.ts b/packages/astro-loader-github-prs/src/utils.ts
new file mode 100644
index 0000000..84efe62
--- /dev/null
+++ b/packages/astro-loader-github-prs/src/utils.ts
@@ -0,0 +1,16 @@
+/**
+ * Get the search query with `monthsBack`.
+ */
+export function getQueryWithMonthsBack(
+ search: string,
+ monthsBack: number | undefined
+) {
+ if (!search.includes('created') && monthsBack) {
+ const startDate = new Date()
+ startDate.setMonth(startDate.getMonth() - monthsBack + 1)
+ startDate.setDate(1)
+
+ return `${search} created:>=${startDate.toISOString().split('T')[0]}`
+ }
+ return search
+}