Skip to content

Commit

Permalink
Feat: OCS registry api (#539)
Browse files Browse the repository at this point in the history
* Attempt DB query

* Super basic demo

* Clean up

* Remove content nesting

* Fix lint

* Update for API compatibility

* Add pagination to entries api

* Add featured API and entries pagination

* Add category filtering

* Pass through formatted data, no need to transform

* Make category filtering case insensitive

* add curation filter

* Move ocsRegistry -> /api/registry

---------

Co-authored-by: Ricardo Moguel <[email protected]>
  • Loading branch information
zencephalon and ricardoMogg authored Jun 27, 2024
1 parent a5370a1 commit 01c05e2
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 4 deletions.
2 changes: 2 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"framer-motion": "^8.5.5",
"kysely": "^0.27.3",
"next": "^13.2.0",
"pg": "^8.12.0",
"react": "^18.2.0",
"react-blockies": "^1.4.1",
"react-copy-to-clipboard": "^5.1.0",
Expand All @@ -37,6 +38,7 @@
},
"devDependencies": {
"@types/node": "18.11.18",
"@types/pg": "^8.11.6",
"@types/react-copy-to-clipboard": "^5.0.7",
"autoprefixer": "^10.4.13",
"csv-parser": "^3.0.0",
Expand Down
46 changes: 46 additions & 0 deletions apps/web/pages/api/registry/entries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { db } from 'apps/web/src/utils/ocsRegistry';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { page = '1', limit = '10', category, curation } = req.query;

const pageNum = parseInt(page as string, 10);
const limitNum = parseInt(limit as string, 10);
const offset = (pageNum - 1) * limitNum;

// Base query for filtering by category if provided
let baseQuery = db.selectFrom('content');

if (category) {
baseQuery = baseQuery.where('category', 'ilike', `%${category}%`);
}

if (curation) {
baseQuery = baseQuery.where('curation', 'ilike', `%${curation}%`);
}

// Fetch total records count
const totalRecordsQuery = baseQuery.select(db.fn.count('id').as('count'));
const totalRecords = await totalRecordsQuery.execute();
const totalRecordsCount = parseInt(totalRecords[0].count as string, 10);

// Fetch paginated content
const contentQuery = baseQuery.selectAll().limit(limitNum).offset(offset);
const content = await contentQuery.execute();

const response = {
data: content.map((row) => ({
id: row.id,
category: row.category,
content: row.content,
})),
pagination: {
total_records: totalRecordsCount,
current_page: pageNum,
total_pages: Math.ceil(totalRecordsCount / limitNum),
limit: limitNum,
},
};

res.status(200).json(response);
}
19 changes: 19 additions & 0 deletions apps/web/pages/api/registry/featured.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { db } from 'apps/web/src/utils/ocsRegistry';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const content = await db
.selectFrom('content')
.where('is_featured', '=', true)
.selectAll()
.limit(1)
.execute();

const row = content[0];

const response = {
data: row,
};

res.status(200).json(response);
}
31 changes: 31 additions & 0 deletions apps/web/src/utils/ocsRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ColumnType, JSONColumnType } from 'kysely';
import { createKysely } from '@vercel/postgres-kysely';

type Database = {
content: ContentTable;
};

type OcsChallengeCard = {
title: string;
short_description: string;
full_description: string;
image_url: string;
target_url: string;
cta_text: string;
function_signature: string;
contract_address: string;
token_id: string;
token_amount: string;
creator_name: string;
creator_image_url: string;
};

type ContentTable = {
id: string;
category: string;
created_at: ColumnType<Date, string | undefined, never>;
is_featured: boolean;
content: JSONColumnType<OcsChallengeCard>;
};

export const db = createKysely<Database>();
134 changes: 130 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ __metadata:
"@rainbow-me/rainbowkit": ^2.1.2
"@tanstack/react-query": ^5.29.2
"@types/node": 18.11.18
"@types/pg": ^8.11.6
"@types/react-copy-to-clipboard": ^5.0.7
"@vercel/kv": ^1.0.1
"@vercel/postgres-kysely": ^0.8.0
Expand All @@ -324,6 +325,7 @@ __metadata:
kysely: ^0.27.3
next: ^13.2.0
node-fetch: ^3.3.0
pg: ^8.12.0
postcss: ^8.4.21
prettier-plugin-tailwindcss: ^0.2.5
react: ^18.2.0
Expand Down Expand Up @@ -7407,6 +7409,17 @@ __metadata:
languageName: node
linkType: hard

"@types/pg@npm:^8.11.6":
version: 8.11.6
resolution: "@types/pg@npm:8.11.6"
dependencies:
"@types/node": "*"
pg-protocol: "*"
pg-types: ^4.0.1
checksum: 231f7e5bfe8b4d14cca398d24cd55f4f14f582f815b62059e6f3ee74108cf92089fbd946568ebc35fa402f238ed9c8a8c1e10e7084e83e4ca3aff75957243014
languageName: node
linkType: hard

"@types/prop-types@npm:*":
version: 15.7.9
resolution: "@types/prop-types@npm:15.7.9"
Expand Down Expand Up @@ -18894,7 +18907,7 @@ __metadata:
languageName: node
linkType: hard

"obuf@npm:^1.0.0, obuf@npm:^1.1.2":
"obuf@npm:^1.0.0, obuf@npm:^1.1.2, obuf@npm:~1.1.2":
version: 1.1.2
resolution: "obuf@npm:1.1.2"
checksum: 41a2ba310e7b6f6c3b905af82c275bf8854896e2e4c5752966d64cbcd2f599cfffd5932006bcf3b8b419dfdacebb3a3912d5d94e10f1d0acab59876c8757f27f
Expand Down Expand Up @@ -19341,21 +19354,51 @@ __metadata:
languageName: node
linkType: hard

"pg-cloudflare@npm:^1.1.1":
version: 1.1.1
resolution: "pg-cloudflare@npm:1.1.1"
checksum: 32aac06b5dc4588bbf78801b6267781bc7e13be672009df949d08e9627ba9fdc26924916665d4de99d47f9b0495301930547488dad889d826856976c7b3f3731
languageName: node
linkType: hard

"pg-connection-string@npm:^2.6.4":
version: 2.6.4
resolution: "pg-connection-string@npm:2.6.4"
checksum: 2c1d2ac1add1f93076f1594d217a0980f79add05dc48de6363e1c550827c78a6ee3e3b5420da9c54858f6b678cdb348aed49732ee68158b6cdb70f1d1c748cf9
languageName: node
linkType: hard

"pg-int8@npm:1.0.1":
version: 1.0.1
resolution: "pg-int8@npm:1.0.1"
checksum: a1e3a05a69005ddb73e5f324b6b4e689868a447c5fa280b44cd4d04e6916a344ac289e0b8d2695d66e8e89a7fba023affb9e0e94778770ada5df43f003d664c9
languageName: node
linkType: hard

"pg-protocol@npm:*":
"pg-numeric@npm:1.0.2":
version: 1.0.2
resolution: "pg-numeric@npm:1.0.2"
checksum: 8899f8200caa1744439a8778a9eb3ceefb599d893e40a09eef84ee0d4c151319fd416634a6c0fc7b7db4ac268710042da5be700b80ef0de716fe089b8652c84f
languageName: node
linkType: hard

"pg-pool@npm:^3.6.2":
version: 3.6.2
resolution: "pg-pool@npm:3.6.2"
peerDependencies:
pg: ">=8.0"
checksum: 5ceee4320a35fce08777d085d50a30a1253574257e1e7c5c56c915056d387d340f797115580c8d90a46691f83c39a9b4da1fd810d9ad168cc455c79c289116f4
languageName: node
linkType: hard

"pg-protocol@npm:*, pg-protocol@npm:^1.6.1":
version: 1.6.1
resolution: "pg-protocol@npm:1.6.1"
checksum: cce3f72cc4bdc04db9ce3fa38b2c45b745f0a95a925847b349087f52c02c4d51b7c74d8867e40639699d0c7609accfaffb6b1d221b3268d2bdc4bb8d6a2995a3
languageName: node
linkType: hard

"pg-types@npm:^2.2.0":
"pg-types@npm:^2.1.0, pg-types@npm:^2.2.0":
version: 2.2.0
resolution: "pg-types@npm:2.2.0"
dependencies:
Expand All @@ -19368,6 +19411,52 @@ __metadata:
languageName: node
linkType: hard

"pg-types@npm:^4.0.1":
version: 4.0.2
resolution: "pg-types@npm:4.0.2"
dependencies:
pg-int8: 1.0.1
pg-numeric: 1.0.2
postgres-array: ~3.0.1
postgres-bytea: ~3.0.0
postgres-date: ~2.1.0
postgres-interval: ^3.0.0
postgres-range: ^1.1.1
checksum: c4b813382d4a75f87462fab3245d5422b86ba1a54a1b330e6b43a459c127b4d02553dc7e5b4ae4fa0f5f17971d416eb393810f69ff6d30d986e45c2f20778c55
languageName: node
linkType: hard

"pg@npm:^8.12.0":
version: 8.12.0
resolution: "pg@npm:8.12.0"
dependencies:
pg-cloudflare: ^1.1.1
pg-connection-string: ^2.6.4
pg-pool: ^3.6.2
pg-protocol: ^1.6.1
pg-types: ^2.1.0
pgpass: 1.x
peerDependencies:
pg-native: ">=3.0.1"
dependenciesMeta:
pg-cloudflare:
optional: true
peerDependenciesMeta:
pg-native:
optional: true
checksum: 8450b61c787f360e22182aa853548f834f13622714868d0789a60f63743d66ae28930cdca0ef0251bfc89b04679e9074c1398f172c2937bf59b5a360337f4149
languageName: node
linkType: hard

"pgpass@npm:1.x":
version: 1.0.5
resolution: "pgpass@npm:1.0.5"
dependencies:
split2: ^4.1.0
checksum: 947ac096c031eebdf08d989de2e9f6f156b8133d6858c7c2c06c041e1e71dda6f5f3bad3c0ec1e96a09497bbc6ef89e762eefe703b5ef9cb2804392ec52ec400
languageName: node
linkType: hard

"picocolors@npm:^1.0.0":
version: 1.0.0
resolution: "picocolors@npm:1.0.0"
Expand Down Expand Up @@ -20050,20 +20139,43 @@ __metadata:
languageName: node
linkType: hard

"postgres-array@npm:~3.0.1":
version: 3.0.2
resolution: "postgres-array@npm:3.0.2"
checksum: 5955f9dffeb6fa960c1a0b04fd4b2ba16813ddb636934ad26f902e4d76a91c0b743dcc6edc4cffc52deba7d547505e0020adea027c1d50a774f989cf955420d1
languageName: node
linkType: hard

"postgres-bytea@npm:~1.0.0":
version: 1.0.0
resolution: "postgres-bytea@npm:1.0.0"
checksum: d844ae4ca7a941b70e45cac1261a73ee8ed39d72d3d74ab1d645248185a1b7f0ac91a3c63d6159441020f4e1f7fe64689ac56536a307b31cef361e5187335090
languageName: node
linkType: hard

"postgres-bytea@npm:~3.0.0":
version: 3.0.0
resolution: "postgres-bytea@npm:3.0.0"
dependencies:
obuf: ~1.1.2
checksum: 5f917a003fcaa0df7f285e1c37108ad474ce91193466b9bd4bcaecef2cdea98ca069c00aa6a8dbe6d2e7192336cadc3c9b36ae48d1555a299521918e00e2936b
languageName: node
linkType: hard

"postgres-date@npm:~1.0.4":
version: 1.0.7
resolution: "postgres-date@npm:1.0.7"
checksum: 5745001d47e51cd767e46bcb1710649cd705d91a24d42fa661c454b6dcbb7353c066a5047983c90a626cd3bbfea9e626cc6fa84a35ec57e5bbb28b49f78e13ed
languageName: node
linkType: hard

"postgres-date@npm:~2.1.0":
version: 2.1.0
resolution: "postgres-date@npm:2.1.0"
checksum: 5c573b0602e17c6134fd8bc8ac7689ac0302e1b199f15dd3578fc45186f206dbd0609f97bf0e4bd1db62234d7a37f29c04f4df525f7efebb9304363b2efca272
languageName: node
linkType: hard

"postgres-interval@npm:^1.1.0":
version: 1.2.0
resolution: "postgres-interval@npm:1.2.0"
Expand All @@ -20073,6 +20185,20 @@ __metadata:
languageName: node
linkType: hard

"postgres-interval@npm:^3.0.0":
version: 3.0.0
resolution: "postgres-interval@npm:3.0.0"
checksum: c7a1cf006de97de663b6b8c4d2b167aa9909a238c4866a94b15d303762f5ac884ff4796cd6e2111b7f0a91302b83c570453aa8506fd005b5a5d5dfa87441bebc
languageName: node
linkType: hard

"postgres-range@npm:^1.1.1":
version: 1.1.4
resolution: "postgres-range@npm:1.1.4"
checksum: 460af8c882a50e2c3d08ede5d5ee9e5e5a99dcf471e3ed55b4c17cad62dc85177b51bb8105b626a9c73de9edcba934e86665923b0d86e1c8e1f55d3e0f3530c6
languageName: node
linkType: hard

"preact@npm:^10.12.0, preact@npm:^10.5.9":
version: 10.18.1
resolution: "preact@npm:10.18.1"
Expand Down Expand Up @@ -22528,7 +22654,7 @@ __metadata:
languageName: node
linkType: hard

"split2@npm:^4.0.0":
"split2@npm:^4.0.0, split2@npm:^4.1.0":
version: 4.2.0
resolution: "split2@npm:4.2.0"
checksum: 05d54102546549fe4d2455900699056580cca006c0275c334611420f854da30ac999230857a85fdd9914dc2109ae50f80fda43d2a445f2aa86eccdc1dfce779d
Expand Down

0 comments on commit 01c05e2

Please sign in to comment.