From 674bf84fe0f87012056cceac41a2ad0be5a0432d Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Tue, 10 Feb 2026 19:17:30 +0100 Subject: [PATCH] feat: init public notes --- package.json | 4 ++ pnpm-lock.yaml | 105 ++++++++++++++++++++++++++++++++ pnpm-workspace.yaml | 5 -- src/components/WelcomeWorld.vue | 3 + src/main.ts | 28 +++++---- src/modules/post/data/client.ts | 64 +++++++++++++++++++ src/router/router.ts | 5 ++ src/views/PublicNoteList.vue | 18 ++++++ 8 files changed, 216 insertions(+), 16 deletions(-) delete mode 100644 pnpm-workspace.yaml create mode 100644 src/modules/post/data/client.ts create mode 100644 src/views/PublicNoteList.vue diff --git a/package.json b/package.json index e88ea88..926c575 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,14 @@ "@octokit/core": "^7.0.6", "@octokit/rest": "^22.0.1", "@tailwindcss/postcss": "^4.1.16", + "@tanstack/vue-query": "^5.92.9", "@toycode/markdown-it-class": "^1.2.4", + "@ts-rest/core": "^3.52.1", + "@ts-rest/vue-query": "^3.52.1", "@vscode/markdown-it-katex": "^1.1.2", "@vueuse/core": "^13.6.0", "@vueuse/router": "^13.6.0", + "arktype": "^2.1.29", "date-fns": "^4.1.0", "events": "^3.3.0", "font-color-contrast": "^11.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac429f7..ee16d41 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,9 +20,18 @@ importers: '@tailwindcss/postcss': specifier: ^4.1.16 version: 4.1.16 + '@tanstack/vue-query': + specifier: ^5.92.9 + version: 5.92.9(vue@3.5.18(typescript@5.9.3)) '@toycode/markdown-it-class': specifier: ^1.2.4 version: 1.2.4 + '@ts-rest/core': + specifier: ^3.52.1 + version: 3.52.1(@types/node@22.15.24) + '@ts-rest/vue-query': + specifier: ^3.52.1 + version: 3.52.1(@tanstack/vue-query@5.92.9(vue@3.5.18(typescript@5.9.3)))(@ts-rest/core@3.52.1(@types/node@22.15.24)) '@vscode/markdown-it-katex': specifier: ^1.1.2 version: 1.1.2 @@ -32,6 +41,9 @@ importers: '@vueuse/router': specifier: ^13.6.0 version: 13.6.0(vue-router@4.5.1(vue@3.5.18(typescript@5.9.3)))(vue@3.5.18(typescript@5.9.3)) + arktype: + specifier: ^2.1.29 + version: 2.1.29 date-fns: specifier: ^4.1.0 version: 4.1.0 @@ -227,6 +239,12 @@ packages: peerDependencies: ajv: '>=8' + '@ark/schema@0.56.0': + resolution: {integrity: sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA==} + + '@ark/util@0.56.0': + resolution: {integrity: sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1491,9 +1509,46 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + '@tanstack/match-sorter-utils@8.19.4': + resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} + engines: {node: '>=12'} + + '@tanstack/query-core@5.90.20': + resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + + '@tanstack/vue-query@5.92.9': + resolution: {integrity: sha512-jjAZcqKveyX0C4w/6zUqbnqk/XzuxNWaFsWjGTJWULVFizUNeLGME2gf9vVSDclIyiBhR13oZJPPs6fJgfpIJQ==} + peerDependencies: + '@vue/composition-api': ^1.1.2 + vue: ^2.6.0 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + '@toycode/markdown-it-class@1.2.4': resolution: {integrity: sha512-hA4gHBK8moObkOYdWTjhy1wYcYy0MJeM3JjSKbsXHRpRMvIKhk6Jm+t3bXsSScTdz/byWqQbs8YIwVYjHp+SlQ==} + '@ts-rest/core@3.52.1': + resolution: {integrity: sha512-tAjz7Kxq/grJodcTA1Anop4AVRDlD40fkksEV5Mmal88VoZeRKAG8oMHsDwdwPZz+B/zgnz0q2sF+cm5M7Bc7g==} + peerDependencies: + '@types/node': ^18.18.7 || >=20.8.4 + zod: ^3.22.3 + peerDependenciesMeta: + '@types/node': + optional: true + zod: + optional: true + + '@ts-rest/vue-query@3.52.1': + resolution: {integrity: sha512-89u7aS9LGDC7uNUC5CagWX1EB7vTwyXohYcizLi1D9v7MD/Cnu5OTQNf8SY3PuAK62RcFJXB2XZGsMAPC0svNw==} + peerDependencies: + '@tanstack/vue-query': ^4.0.0 + '@ts-rest/core': ~3.52.0 + zod: ^3.22.3 + peerDependenciesMeta: + zod: + optional: true + '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -1955,6 +2010,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + arkregex@0.0.5: + resolution: {integrity: sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw==} + + arktype@2.1.29: + resolution: {integrity: sha512-jyfKk4xIOzvYNayqnD8ZJQqOwcrTOUbIU4293yrzAjA3O1dWh61j71ArMQ6tS/u4pD7vabSPe7nG3RCyoXW6RQ==} + array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -3675,6 +3736,9 @@ packages: resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} hasBin: true + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -4415,6 +4479,12 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 + '@ark/schema@0.56.0': + dependencies: + '@ark/util': 0.56.0 + + '@ark/util@0.56.0': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -5762,8 +5832,31 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 4.1.16 + '@tanstack/match-sorter-utils@8.19.4': + dependencies: + remove-accents: 0.5.0 + + '@tanstack/query-core@5.90.20': {} + + '@tanstack/vue-query@5.92.9(vue@3.5.18(typescript@5.9.3))': + dependencies: + '@tanstack/match-sorter-utils': 8.19.4 + '@tanstack/query-core': 5.90.20 + '@vue/devtools-api': 6.6.4 + vue: 3.5.18(typescript@5.9.3) + vue-demi: 0.14.10(vue@3.5.18(typescript@5.9.3)) + '@toycode/markdown-it-class@1.2.4': {} + '@ts-rest/core@3.52.1(@types/node@22.15.24)': + optionalDependencies: + '@types/node': 22.15.24 + + '@ts-rest/vue-query@3.52.1(@tanstack/vue-query@5.92.9(vue@3.5.18(typescript@5.9.3)))(@ts-rest/core@3.52.1(@types/node@22.15.24))': + dependencies: + '@tanstack/vue-query': 5.92.9(vue@3.5.18(typescript@5.9.3)) + '@ts-rest/core': 3.52.1(@types/node@22.15.24) + '@types/chai@5.2.2': dependencies: '@types/deep-eql': 4.0.2 @@ -6389,6 +6482,16 @@ snapshots: argparse@2.0.1: {} + arkregex@0.0.5: + dependencies: + '@ark/util': 0.56.0 + + arktype@2.1.29: + dependencies: + '@ark/schema': 0.56.0 + '@ark/util': 0.56.0 + arkregex: 0.0.5 + array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -8205,6 +8308,8 @@ snapshots: dependencies: jsesc: 3.1.0 + remove-accents@0.5.0: {} + require-from-string@2.0.2: {} resolve-from@4.0.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index c7aa842..0000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,5 +0,0 @@ -onlyBuiltDependencies: - - '@parcel/watcher' - - '@tailwindcss/oxide' - - esbuild - - vue-demi diff --git a/src/components/WelcomeWorld.vue b/src/components/WelcomeWorld.vue index 49e357b..e065648 100644 --- a/src/components/WelcomeWorld.vue +++ b/src/components/WelcomeWorld.vue @@ -19,6 +19,9 @@ Manage your repos + Public notes
diff --git a/src/main.ts b/src/main.ts index 0db387f..2fc3b4c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,18 +1,24 @@ -import 'notyf/notyf.min.css' -import './styles/app.css' +import "notyf/notyf.min.css" +import "./styles/app.css" -import { createPinia } from 'pinia' -import { createApp } from 'vue' -import { createI18n } from 'vue-i18n' +import { createPinia } from "pinia" +import { createApp } from "vue" +import { createI18n } from "vue-i18n" -import { messages } from '@/locales/message' -import { router } from '@/router/router' +import { messages } from "@/locales/message" +import { router } from "@/router/router" +import { VueQueryPlugin } from "@tanstack/vue-query" -import App from './App.vue' +import App from "./App.vue" const i18n = createI18n({ - locale: 'en', - messages + locale: "en", + messages, }) -createApp(App).use(router).use(i18n).use(createPinia()).mount('#app') +createApp(App) + .use(router) + .use(VueQueryPlugin) + .use(i18n) + .use(createPinia()) + .mount("#app") diff --git a/src/modules/post/data/client.ts b/src/modules/post/data/client.ts new file mode 100644 index 0000000..9fe2a11 --- /dev/null +++ b/src/modules/post/data/client.ts @@ -0,0 +1,64 @@ +import { initContract } from "@ts-rest/core" +import { type } from "arktype" +import { initQueryClient } from "@ts-rest/vue-query" + +const PublicNoteListItem = type({ + did: "string", + rkey: "string", + title: "string", + publishedAt: "string", + createdAt: "string", +}) + +export type PublicNoteListItem = typeof PublicNoteListItem.infer + +const PublicNote = type({ + did: "string", + rkey: "string", + title: "string", + content: "string", + publishedAt: "string", + createdAt: "string", +}) + +export type PublicNote = typeof PublicNote.infer + +const contract = initContract() + +export const noteRouter = contract.router({ + noteLists: { + method: "GET", + path: "/notes", + query: type({ + cursor: "string | undefined", + limit: "number | undefined", + }), + responses: { + 200: type({ + notes: PublicNoteListItem.array(), + }), + }, + summary: "List all notes", + }, + noteListsByDid: { + method: "GET", + path: "/:did/notes", + pathParams: type({ + did: "string", + }), + query: type({ + cursor: "string | undefined", + limit: "number | undefined", + }), + responses: { + 200: type({ + notes: PublicNoteListItem.array(), + }), + }, + summary: "List all notes", + }, +}) + +export const client = initQueryClient(noteRouter, { + baseUrl: "https://api.litenote.li212.fr", +}) diff --git a/src/router/router.ts b/src/router/router.ts index a19256e..04d5c1d 100644 --- a/src/router/router.ts +++ b/src/router/router.ts @@ -8,6 +8,11 @@ const routes: Array = [ name: "RepoList", component: () => import("@/views/RepoList.vue"), }, + { + path: "/notes", + name: "PublicNoteList", + component: () => import("@/views/PublicNoteList.vue"), + }, { path: "/:user/:repo", name: "FluxNoteView", diff --git a/src/views/PublicNoteList.vue b/src/views/PublicNoteList.vue new file mode 100644 index 0000000..82b74f0 --- /dev/null +++ b/src/views/PublicNoteList.vue @@ -0,0 +1,18 @@ + + + + +