@@ -67,6 +69,7 @@ import Cta from '@fragments/cta.mdx';
*/}
-import SponsorList from '@components/SponsorList.astro';
+
+
diff --git a/src/utils/fetchOpenCollectiveData.ts b/src/utils/fetchOpenCollectiveData.ts
new file mode 100644
index 000000000..96ee07715
--- /dev/null
+++ b/src/utils/fetchOpenCollectiveData.ts
@@ -0,0 +1,84 @@
+import {
+ IMAGE_DIMENSION,
+ type Sponsor,
+ type Tier,
+} from '@components/sponsors/OpenCollective/_types';
+
+export const PLATINUM_THRESHOLD = 5_000;
+export const GOLD_THRESHOLD = 500;
+export const SILVER_THRESHOLD = 100;
+
+export async function fetchOpenCollectiveData() {
+ const filteredSlugs = ['github-sponsors'];
+
+ // Documentation at https://graphql-docs-v2.opencollective.com/welcome
+ const query = `query account {
+ collective(slug: "tauri") {
+ contributors(limit: 1000) {
+ nodes {
+ account {
+ name
+ type
+ imageUrl(height: ${IMAGE_DIMENSION})
+ slug
+ isIncognito
+ }
+ totalAmountContributed {
+ value
+ currency
+ }
+ }
+ }
+ }
+}`;
+
+ const res = await fetch('https://api.opencollective.com/graphql/v2', {
+ method: 'POST',
+ body: JSON.stringify({ query }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (!res.ok) {
+ throw Error(
+ `Open Collective query failed: ${res.status} ${res.statusText} \n ${JSON.stringify(await res.json(), null, 2)}, `
+ );
+ }
+
+ // TODO: handle currency
+
+ const openCollectiveData = (await res.json()).data;
+ return openCollectiveData.collective.contributors.nodes
+ .filter(
+ (node: any) =>
+ !node.account.isIncognito &&
+ node.totalAmountContributed.value > 0 &&
+ !filteredSlugs.includes(node.account.slug) &&
+ node.account.name != 'Guest'
+ )
+ .sort((a: any, b: any) => b.totalAmountContributed.value - a.totalAmountContributed.value)
+ .map((node: any): Sponsor => {
+ let tier: Tier;
+ let amount = node.totalAmountContributed.value;
+ if (amount >= PLATINUM_THRESHOLD) {
+ tier = 'platinum';
+ } else if (amount >= GOLD_THRESHOLD) {
+ tier = 'gold';
+ } else if (amount >= SILVER_THRESHOLD) {
+ tier = 'silver';
+ } else {
+ tier = 'bronze';
+ }
+ const { slug, name, type, isIncognito, imageUrl } = node.account;
+
+ return {
+ name,
+ id: name,
+ avatarUrl: imageUrl,
+ profileUrl: `https://opencollective.com/${slug}`,
+ tier,
+ type,
+ };
+ });
+}
diff --git a/tauri-docs.code-workspace b/tauri-docs.code-workspace
new file mode 100644
index 000000000..f704189b0
--- /dev/null
+++ b/tauri-docs.code-workspace
@@ -0,0 +1,46 @@
+{
+ "folders": [
+ {
+ "path": ".",
+ "name": "docs"
+ },
+ {
+ "path": "packages",
+ "name": "packages",
+ "folders": [
+ {
+ "path": "js-api-generator",
+ },
+ {
+ "path": "config-generator",
+ },
+ {
+ "path": "cli-generator",
+ },
+ {
+ "path": "releases-generator",
+ },
+ {
+ "path": "compatibility-table",
+ }
+ ]
+ },
+ // todo: fix paths so that we can see docs, packages and submodules
+ {
+ "path": "packages",
+ "name": "submodules",
+ "folders": [
+ {
+ "path": "awesome-tauri",
+ },
+ {
+ "path": "tauri",
+ },
+ {
+ "path": "plugins-workspace",
+ }
+ ]
+ }
+ ],
+ "settings": {}
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 66f233edb..503d85dd4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,7 +5,8 @@
"paths": {
"@components/*": ["src/components/*"],
"@assets/*": ["src/assets/*"],
- "@fragments/*": ["src/content/docs/_fragments/*"]
+ "@fragments/*": ["src/content/docs/_fragments/*"],
+ "@utils/*": ["src/utils/*"]
}
},
"include": [".astro/types.d.ts", "**/*"],