diff --git a/directus-schema.ts b/directus-schema.ts deleted file mode 100644 index ccf9c36..0000000 --- a/directus-schema.ts +++ /dev/null @@ -1,658 +0,0 @@ -export interface Article { - /** @primaryKey */ - id: number; - /** @required */ - translations: ArticleTranslation[] | null; -} - -export interface ArticleTag { - /** @primaryKey */ - id: number; - article_id?: Article | string | null; - tag_id?: Tag | string | null; -} - -export interface ArticleTranslation { - /** @primaryKey */ - id: number; - article_id?: Article | string | null; - /** @required */ - languages_code: Language | string; - /** @required */ - title: string; - /** @required */ - description: string; - /** @required */ - slug: string; - /** @required */ - content: string; - /** @required */ - status: 'published' | 'draft' | 'archived'; - /** @required */ - author: DirectusUser | string; - /** @required */ - pub_date: string; - /** @required */ - views: number; - cover_image?: DirectusFile | string | null; - /** @required */ - tags: ArticleTranslationsTag[] | string[]; -} - -export interface ArticleTranslationsTag { - /** @primaryKey */ - id: number; - article_translations_id?: ArticleTranslation | string | null; - tag_id?: Tag | string | null; -} - -export interface Global { - /** @primaryKey */ - id: number; - /** @required */ - title: string; - ym_counter?: number | null; - github?: string | null; - telegram?: string | null; - email?: string | null; - /** @required */ - recent_articles_limit: number; - translations?: GlobalTranslation[] | null; -} - -export interface GlobalTranslation { - /** @primaryKey */ - id: number; - global_id?: Global | string | null; - languages_code?: Language | string | null; - description?: string | null; - navigation?: Array<{ name: string; link: string }> | null; -} - -export interface HomePage { - /** @primaryKey */ - id: number; - translations?: HomePageTranslation[] | null; -} - -export interface HomePageTranslation { - /** @primaryKey */ - id: number; - home_page_id?: HomePage | string | null; - languages_code?: Language | string | null; - /** @required */ - headline: string; - /** @required */ - subheadline: string; - /** @required */ - description: string; -} - -export interface Language { - /** @primaryKey */ - code: string; - /** @required */ - name: string; - /** @required */ - direction: 'ltr' | 'rtl'; -} - -export interface Project { - /** @primaryKey */ - id: number; - /** @required */ - translations: ProjectTranslation[] | null; -} - -export interface ProjectTranslation { - /** @primaryKey */ - id: number; - project_id?: Project | string | null; - languages_code?: Language | string | null; - /** @required */ - title: string; - /** @required */ - year: string; - /** @required */ - description: string; - /** @required */ - source_url: string; -} - -export interface Tag { - /** @primaryKey */ - id: number; - /** @required */ - title: string; -} - -export interface DirectusAccess { - /** @primaryKey */ - id: string; - role?: DirectusRole | string | null; - user?: DirectusUser | string | null; - policy?: DirectusPolicy | string; - sort?: number | null; -} - -export interface DirectusActivity { - /** @primaryKey */ - id: number; - action?: string; - user?: DirectusUser | string | null; - timestamp?: string; - ip?: string | null; - user_agent?: string | null; - collection?: string; - item?: string; - origin?: string | null; - revisions?: DirectusRevision[] | string[]; -} - -export interface DirectusCollection { - /** @primaryKey */ - collection: string; - icon?: string | null; - note?: string | null; - display_template?: string | null; - hidden?: boolean; - singleton?: boolean; - translations?: Array<{ language: string; translation: string; singular: string; plural: string }> | null; - archive_field?: string | null; - archive_app_filter?: boolean; - archive_value?: string | null; - unarchive_value?: string | null; - sort_field?: string | null; - accountability?: 'all' | 'activity' | null | null; - color?: string | null; - item_duplication_fields?: 'json' | null; - sort?: number | null; - group?: DirectusCollection | string | null; - collapse?: string; - preview_url?: string | null; - versioning?: boolean; -} - -export interface DirectusComment { - /** @primaryKey */ - id: string; - collection?: DirectusCollection | string; - item?: string; - comment?: string; - date_created?: string | null; - date_updated?: string | null; - user_created?: DirectusUser | string | null; - user_updated?: DirectusUser | string | null; -} - -export interface DirectusField { - /** @primaryKey */ - id: number; - collection?: DirectusCollection | string; - field?: string; - special?: string[] | null; - interface?: string | null; - options?: 'json' | null; - display?: string | null; - display_options?: 'json' | null; - readonly?: boolean; - hidden?: boolean; - sort?: number | null; - width?: string | null; - translations?: 'json' | null; - note?: string | null; - conditions?: 'json' | null; - required?: boolean | null; - group?: DirectusField | string | null; - validation?: 'json' | null; - validation_message?: string | null; - searchable?: boolean; -} - -export interface DirectusFile { - /** @primaryKey */ - id: string; - storage?: string; - filename_disk?: string | null; - filename_download?: string; - title?: string | null; - type?: string | null; - folder?: DirectusFolder | string | null; - uploaded_by?: DirectusUser | string | null; - created_on?: string; - modified_by?: DirectusUser | string | null; - modified_on?: string; - charset?: string | null; - filesize?: number | null; - width?: number | null; - height?: number | null; - duration?: number | null; - embed?: string | null; - description?: string | null; - location?: string | null; - tags?: string[] | null; - metadata?: 'json' | null; - focal_point_x?: number | null; - focal_point_y?: number | null; - tus_id?: string | null; - tus_data?: 'json' | null; - uploaded_on?: string | null; -} - -export interface DirectusFolder { - /** @primaryKey */ - id: string; - name?: string; - parent?: DirectusFolder | string | null; -} - -export interface DirectusMigration { - /** @primaryKey */ - version: string; - name?: string; - timestamp?: string | null; -} - -export interface DirectusPermission { - /** @primaryKey */ - id: number; - collection?: string; - action?: string; - permissions?: 'json' | null; - validation?: 'json' | null; - presets?: 'json' | null; - fields?: string[] | null; - policy?: DirectusPolicy | string; -} - -export interface DirectusPolicy { - /** @primaryKey */ - id: string; - /** @required */ - name: string; - icon?: string; - description?: string | null; - ip_access?: string[] | null; - enforce_tfa?: boolean; - admin_access?: boolean; - app_access?: boolean; - permissions?: DirectusPermission[] | string[]; - users?: DirectusAccess[] | string[]; - roles?: DirectusAccess[] | string[]; -} - -export interface DirectusPreset { - /** @primaryKey */ - id: number; - bookmark?: string | null; - user?: DirectusUser | string | null; - role?: DirectusRole | string | null; - collection?: string | null; - search?: string | null; - layout?: string | null; - layout_query?: 'json' | null; - layout_options?: 'json' | null; - refresh_interval?: number | null; - filter?: 'json' | null; - icon?: string | null; - color?: string | null; -} - -export interface DirectusRelation { - /** @primaryKey */ - id: number; - many_collection?: string; - many_field?: string; - one_collection?: string | null; - one_field?: string | null; - one_collection_field?: string | null; - one_allowed_collections?: string[] | null; - junction_field?: string | null; - sort_field?: string | null; - one_deselect_action?: string; -} - -export interface DirectusRevision { - /** @primaryKey */ - id: number; - activity?: DirectusActivity | string; - collection?: string; - item?: string; - data?: 'json' | null; - delta?: 'json' | null; - parent?: DirectusRevision | string | null; - version?: DirectusVersion | string | null; -} - -export interface DirectusRole { - /** @primaryKey */ - id: string; - /** @required */ - name: string; - icon?: string; - description?: string | null; - parent?: DirectusRole | string | null; - children?: DirectusRole[] | string[]; - policies?: DirectusAccess[] | string[]; - users?: DirectusUser[] | string[]; -} - -export interface DirectusSession { - /** @primaryKey */ - token: string; - user?: DirectusUser | string | null; - expires?: string; - ip?: string | null; - user_agent?: string | null; - share?: DirectusShare | string | null; - origin?: string | null; - next_token?: string | null; -} - -export interface DirectusSettings { - /** @primaryKey */ - id: number; - project_name?: string; - project_url?: string | null; - project_color?: string; - project_logo?: DirectusFile | string | null; - public_foreground?: DirectusFile | string | null; - public_background?: DirectusFile | string | null; - public_note?: string | null; - auth_login_attempts?: number | null; - auth_password_policy?: null | `/^.{8,}$/` | `/(?=^.{8,}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{';'?>.<,])(?!.*\\s).*$/` | null; - storage_asset_transform?: 'all' | 'none' | 'presets' | null; - storage_asset_presets?: Array<{ key: string; fit: 'contain' | 'cover' | 'inside' | 'outside'; width: number; height: number; quality: number; withoutEnlargement: boolean; format: 'auto' | 'jpeg' | 'png' | 'webp' | 'tiff' | 'avif'; transforms: 'json' }> | null; - custom_css?: string | null; - storage_default_folder?: DirectusFolder | string | null; - basemaps?: Array<{ name: string; type: 'raster' | 'tile' | 'style'; url: string; tileSize: number; attribution: string }> | null; - mapbox_key?: string | null; - module_bar?: 'json' | null; - project_descriptor?: string | null; - default_language?: string; - custom_aspect_ratios?: Array<{ text: string; value: number }> | null; - public_favicon?: DirectusFile | string | null; - default_appearance?: 'auto' | 'light' | 'dark'; - default_theme_light?: string | null; - theme_light_overrides?: 'json' | null; - default_theme_dark?: string | null; - theme_dark_overrides?: 'json' | null; - report_error_url?: string | null; - report_bug_url?: string | null; - report_feature_url?: string | null; - public_registration?: boolean; - public_registration_verify_email?: boolean; - public_registration_role?: DirectusRole | string | null; - public_registration_email_filter?: 'json' | null; - visual_editor_urls?: Array<{ url: string }> | null; - project_id?: string | null; - mcp_enabled?: boolean; - mcp_allow_deletes?: boolean; - mcp_prompts_collection?: string | null; - mcp_system_prompt_enabled?: boolean; - mcp_system_prompt?: string | null; - project_owner?: string | null; - project_usage?: string | null; - org_name?: string | null; - product_updates?: boolean | null; - project_status?: string | null; -} - -export interface DirectusUser { - /** @primaryKey */ - id: string; - first_name?: string | null; - last_name?: string | null; - email?: string | null; - password?: string | null; - location?: string | null; - title?: string | null; - description?: string | null; - tags?: string[] | null; - avatar?: DirectusFile | string | null; - language?: string | null; - tfa_secret?: string | null; - status?: 'draft' | 'invited' | 'unverified' | 'active' | 'suspended' | 'archived'; - role?: DirectusRole | string | null; - token?: string | null; - last_access?: string | null; - last_page?: string | null; - provider?: string; - external_identifier?: string | null; - auth_data?: 'json' | null; - email_notifications?: boolean | null; - appearance?: null | 'auto' | 'light' | 'dark' | null; - theme_dark?: string | null; - theme_light?: string | null; - theme_light_overrides?: 'json' | null; - theme_dark_overrides?: 'json' | null; - text_direction?: 'auto' | 'ltr' | 'rtl'; - policies?: DirectusAccess[] | string[]; -} - -export interface DirectusWebhook { - /** @primaryKey */ - id: number; - name?: string; - method?: null; - url?: string; - status?: 'active' | 'inactive'; - data?: boolean; - actions?: 'create' | 'update' | 'delete'; - collections?: string[]; - headers?: Array<{ header: string; value: string }> | null; - was_active_before_deprecation?: boolean; - migrated_flow?: DirectusFlow | string | null; -} - -export interface DirectusDashboard { - /** @primaryKey */ - id: string; - name?: string; - icon?: string; - note?: string | null; - date_created?: string | null; - user_created?: DirectusUser | string | null; - color?: string | null; - panels?: DirectusPanel[] | string[]; -} - -export interface DirectusPanel { - /** @primaryKey */ - id: string; - dashboard?: DirectusDashboard | string; - name?: string | null; - icon?: string | null; - color?: string | null; - show_header?: boolean; - note?: string | null; - type?: string; - position_x?: number; - position_y?: number; - width?: number; - height?: number; - options?: 'json' | null; - date_created?: string | null; - user_created?: DirectusUser | string | null; -} - -export interface DirectusNotification { - /** @primaryKey */ - id: number; - timestamp?: string | null; - status?: string | null; - recipient?: DirectusUser | string; - sender?: DirectusUser | string | null; - subject?: string; - message?: string | null; - collection?: string | null; - item?: string | null; -} - -export interface DirectusShare { - /** @primaryKey */ - id: string; - name?: string | null; - collection?: DirectusCollection | string; - item?: string; - role?: DirectusRole | string | null; - password?: string | null; - user_created?: DirectusUser | string | null; - date_created?: string | null; - date_start?: string | null; - date_end?: string | null; - times_used?: number | null; - max_uses?: number | null; -} - -export interface DirectusFlow { - /** @primaryKey */ - id: string; - name?: string; - icon?: string | null; - color?: string | null; - description?: string | null; - status?: string; - trigger?: string | null; - accountability?: string | null; - options?: 'json' | null; - operation?: DirectusOperation | string | null; - date_created?: string | null; - user_created?: DirectusUser | string | null; - operations?: DirectusOperation[] | string[]; -} - -export interface DirectusOperation { - /** @primaryKey */ - id: string; - name?: string | null; - key?: string; - type?: string; - position_x?: number; - position_y?: number; - options?: 'json' | null; - resolve?: DirectusOperation | string | null; - reject?: DirectusOperation | string | null; - flow?: DirectusFlow | string; - date_created?: string | null; - user_created?: DirectusUser | string | null; -} - -export interface DirectusTranslation { - /** @primaryKey */ - id: string; - /** @required */ - language: string; - /** @required */ - key: string; - /** @required */ - value: string; -} - -export interface DirectusVersion { - /** @primaryKey */ - id: string; - key?: string; - name?: string | null; - collection?: DirectusCollection | string; - item?: string; - hash?: string | null; - date_created?: string | null; - date_updated?: string | null; - user_created?: DirectusUser | string | null; - user_updated?: DirectusUser | string | null; - delta?: 'json' | null; -} - -export interface DirectusExtension { - enabled?: boolean; - /** @primaryKey */ - id: string; - folder?: string; - source?: string; - bundle?: string | null; -} - -export interface Schema { - article: Article[]; - article_tag: ArticleTag[]; - article_translations: ArticleTranslation[]; - article_translations_tag: ArticleTranslationsTag[]; - global: Global; - global_translations: GlobalTranslation[]; - home_page: HomePage; - home_page_translations: HomePageTranslation[]; - languages: Language[]; - project: Project[]; - project_translations: ProjectTranslation[]; - tag: Tag[]; - directus_access: DirectusAccess[]; - directus_activity: DirectusActivity[]; - directus_collections: DirectusCollection[]; - directus_comments: DirectusComment[]; - directus_fields: DirectusField[]; - directus_files: DirectusFile[]; - directus_folders: DirectusFolder[]; - directus_migrations: DirectusMigration[]; - directus_permissions: DirectusPermission[]; - directus_policies: DirectusPolicy[]; - directus_presets: DirectusPreset[]; - directus_relations: DirectusRelation[]; - directus_revisions: DirectusRevision[]; - directus_roles: DirectusRole[]; - directus_sessions: DirectusSession[]; - directus_settings: DirectusSettings; - directus_users: DirectusUser[]; - directus_webhooks: DirectusWebhook[]; - directus_dashboards: DirectusDashboard[]; - directus_panels: DirectusPanel[]; - directus_notifications: DirectusNotification[]; - directus_shares: DirectusShare[]; - directus_flows: DirectusFlow[]; - directus_operations: DirectusOperation[]; - directus_translations: DirectusTranslation[]; - directus_versions: DirectusVersion[]; - directus_extensions: DirectusExtension[]; -} - -export enum CollectionNames { - article = 'article', - article_tag = 'article_tag', - article_translations = 'article_translations', - article_translations_tag = 'article_translations_tag', - global = 'global', - global_translations = 'global_translations', - home_page = 'home_page', - home_page_translations = 'home_page_translations', - languages = 'languages', - project = 'project', - project_translations = 'project_translations', - tag = 'tag', - directus_access = 'directus_access', - directus_activity = 'directus_activity', - directus_collections = 'directus_collections', - directus_comments = 'directus_comments', - directus_fields = 'directus_fields', - directus_files = 'directus_files', - directus_folders = 'directus_folders', - directus_migrations = 'directus_migrations', - directus_permissions = 'directus_permissions', - directus_policies = 'directus_policies', - directus_presets = 'directus_presets', - directus_relations = 'directus_relations', - directus_revisions = 'directus_revisions', - directus_roles = 'directus_roles', - directus_sessions = 'directus_sessions', - directus_settings = 'directus_settings', - directus_users = 'directus_users', - directus_webhooks = 'directus_webhooks', - directus_dashboards = 'directus_dashboards', - directus_panels = 'directus_panels', - directus_notifications = 'directus_notifications', - directus_shares = 'directus_shares', - directus_flows = 'directus_flows', - directus_operations = 'directus_operations', - directus_translations = 'directus_translations', - directus_versions = 'directus_versions', - directus_extensions = 'directus_extensions' -} \ No newline at end of file diff --git a/directus.ts b/directus.ts deleted file mode 100644 index 608d628..0000000 --- a/directus.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { createDirectus, graphql, staticToken } from "@directus/sdk"; -import { DIRECTUS_TOKEN, DIRECTUS_URL } from "astro:env/server"; -import type { Article, ArticleTranslation, Schema, Tag } from "./directus-schema"; - -const directus = createDirectus(DIRECTUS_URL) - .with(staticToken(DIRECTUS_TOKEN)) - .with(graphql()); - -export async function fetchArticleTranslationsBySlug( - slug: string -): Promise { - const data = await directus.query<{ article_translations: ArticleTranslation[] }>(` - query Article_translations { - article_translations( - filter: { - slug: { - _eq: "${slug}" - } - } - ) { - id - title - tags { - tag_id { - title - } - } - description - slug - content - author { - first_name - last_name - } - pub_date - views - languages_code { - code - name - } - cover_image { - title - filename_disk - } - article_id { - translations { - slug - languages_code { - code - name - } - pub_date - } - } - } - } - `); - - if (data.article_translations.length === 0) return null; - - return { ...data.article_translations[0] }; -} - -export async function fetchArticles(): Promise { - const data = await directus.query<{ article: Article[] }>(` - query Article { - article { - translations( - filter: { - status: { _eq: "published" } - } - ) { - id - title - tags { - tag_id { - title - } - } - description - slug - pub_date - languages_code { - code - name - } - } - } - } - `); - - return data.article; -} - -export async function fetchRecentArticles(): Promise { - const data = await directus.query<{ article: Article[] }>(` - query Article { - article { - translations( - filter: { - status: { _eq: "published" } - } - ) { - title - cover_image { - id - title - } - slug - pub_date - views - languages_code { code } - } - } - } - `); - - return data.article; -} - -export async function incArticleTranslationViews( - article: Pick -): Promise { - const data = await directus.query<{ update_article_translations_item: { views: number } }>(` - mutation Update_article_translations_item { - update_article_translations_item(id: ${article.id}, data: { views: ${article.views + 1} }) { - views - } - } - `); - return data.update_article_translations_item.views; -} - -export async function fetchTags(): Promise { - const data = await directus.query<{ tag: Tag[] }>(` - query Tag { - tag { - id - title - } - } - `); - return data.tag; -} - -export default directus; diff --git a/package-lock.json b/package-lock.json index e1b3141..acde264 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@astrojs/rss": "^4.0.13", "@astrojs/sitemap": "^3.6.0", "@astrojs/solid-js": "^5.1.3", - "@directus/sdk": "^20.1.1", "@iconify-json/mdi": "^1.2.3", "astro": "^5.15.8", "astro-icon": "^1.1.5", @@ -44,7 +43,6 @@ "@types/html-escaper": "^3.0.4", "@types/mime-types": "^2.1.4", "@types/remark-prism": "^1.3.7", - "directus-sdk-typegen": "^0.2.1", "dotenv": "^17.2.3", "sass": "^1.68.0", "typescript": "^5.9.3" @@ -381,6 +379,17 @@ } } }, + "node_modules/@astrojs/solid-js/node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, "node_modules/@astrojs/solid-js/node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -403,7 +412,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -416,7 +424,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -584,7 +591,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -867,18 +873,6 @@ "node": ">=18" } }, - "node_modules/@directus/sdk": { - "version": "20.1.1", - "resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-20.1.1.tgz", - "integrity": "sha512-cCWvxDRKOygVHBkKA7l1I4O4niomK8SKR/+Ul1L9NFF1K2zAf3jRqhjc7JavCECOiiAWME/s2wYatNFqFFh0gQ==", - "license": "MIT", - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/directus/directus?sponsor=1" - } - }, "node_modules/@emmetio/abbreviation": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", @@ -1840,6 +1834,18 @@ } } }, + "node_modules/@graphql-codegen/cli/node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, "node_modules/@graphql-codegen/cli/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2388,7 +2394,6 @@ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -3487,7 +3492,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -5544,7 +5548,6 @@ "resolved": "https://registry.npmjs.org/astro/-/astro-5.15.8.tgz", "integrity": "sha512-QiiRnNPdxCcAGO2UlO07o+QeGgRfEC5Dlm0x35WPB/ixFK1T2bsNB6KaXri70cVkYY1GYgoRtrWv3HCR26o9aw==", "license": "MIT", - "peer": true, "dependencies": { "@astrojs/compiler": "^2.13.0", "@astrojs/internal-helpers": "0.7.4", @@ -5636,6 +5639,17 @@ "@iconify/utils": "^2.1.30" } }, + "node_modules/astro/node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, "node_modules/astro/node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -5679,7 +5693,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -5846,7 +5859,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -6190,7 +6202,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -7208,32 +7219,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/directus-sdk-typegen": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/directus-sdk-typegen/-/directus-sdk-typegen-0.2.1.tgz", - "integrity": "sha512-a0tcgCa4p2kAO8AJ+SBC97legirxdC3An6VztsvoZwtttFilI8YmCgCM4TfgDtCR/sh+QrpPPgh/Tae7mDxYfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "directus-sdk-typegen": "dist/index.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/directus-sdk-typegen/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -8127,7 +8112,6 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", "license": "MIT", - "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -8408,7 +8392,6 @@ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -9306,7 +9289,6 @@ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "devOptional": true, "license": "MIT", - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -12115,7 +12097,6 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.68.0.tgz", "integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==", "devOptional": true, - "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -12225,7 +12206,6 @@ "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.2.tgz", "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -12528,7 +12508,6 @@ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.10.tgz", "integrity": "sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.1.0", "seroval": "~1.3.0", @@ -12951,7 +12930,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13103,7 +13081,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13181,7 +13158,8 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/unicode-properties": { "version": "1.4.1", @@ -13950,7 +13928,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8.3.0" }, @@ -14238,7 +14215,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -14495,6 +14471,16 @@ "vite-plugin-solid": "^2.11.8" }, "dependencies": { + "@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "optional": true, + "peer": true, + "requires": { + "undici-types": "~7.16.0" + } + }, "fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -14504,14 +14490,12 @@ "picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "peer": true + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" }, "vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "peer": true, "requires": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -14584,7 +14568,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "peer": true, "requires": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -14771,11 +14754,6 @@ "fontkit": "^2.0.2" } }, - "@directus/sdk": { - "version": "20.1.1", - "resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-20.1.1.tgz", - "integrity": "sha512-cCWvxDRKOygVHBkKA7l1I4O4niomK8SKR/+Ul1L9NFF1K2zAf3jRqhjc7JavCECOiiAWME/s2wYatNFqFFh0gQ==" - }, "@emmetio/abbreviation": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", @@ -15259,6 +15237,17 @@ "dev": true, "requires": {} }, + "@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "undici-types": "~7.16.0" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -15633,7 +15622,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, - "peer": true, "requires": {} } } @@ -16237,7 +16225,6 @@ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "dev": true, - "peer": true, "requires": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", @@ -17474,7 +17461,6 @@ "version": "5.15.8", "resolved": "https://registry.npmjs.org/astro/-/astro-5.15.8.tgz", "integrity": "sha512-QiiRnNPdxCcAGO2UlO07o+QeGgRfEC5Dlm0x35WPB/ixFK1T2bsNB6KaXri70cVkYY1GYgoRtrWv3HCR26o9aw==", - "peer": true, "requires": { "@astrojs/compiler": "^2.13.0", "@astrojs/internal-helpers": "0.7.4", @@ -17541,6 +17527,16 @@ "zod-to-ts": "^1.2.0" }, "dependencies": { + "@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "optional": true, + "peer": true, + "requires": { + "undici-types": "~7.16.0" + } + }, "chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -17563,8 +17559,7 @@ "picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "peer": true + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" }, "readdirp": { "version": "4.1.2", @@ -17625,7 +17620,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "peer": true, "requires": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -17813,7 +17807,6 @@ "version": "4.28.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", - "peer": true, "requires": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -18489,23 +18482,6 @@ "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==" }, - "directus-sdk-typegen": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/directus-sdk-typegen/-/directus-sdk-typegen-0.2.1.tgz", - "integrity": "sha512-a0tcgCa4p2kAO8AJ+SBC97legirxdC3An6VztsvoZwtttFilI8YmCgCM4TfgDtCR/sh+QrpPPgh/Tae7mDxYfw==", - "dev": true, - "requires": { - "commander": "^8.3.0" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - } - } - }, "dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -19103,8 +19079,7 @@ "graphql": { "version": "16.12.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", - "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", - "peer": true + "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==" }, "graphql-config": { "version": "5.1.5", @@ -19271,7 +19246,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, - "peer": true, "requires": {} } } @@ -19846,8 +19820,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "devOptional": true, - "peer": true + "devOptional": true }, "js-tokens": { "version": "4.0.0", @@ -21696,7 +21669,6 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.68.0.tgz", "integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==", "devOptional": true, - "peer": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -21776,8 +21748,7 @@ "seroval": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.2.tgz", - "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==", - "peer": true + "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==" }, "seroval-plugins": { "version": "1.3.3", @@ -21978,7 +21949,6 @@ "version": "1.9.10", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.10.tgz", "integrity": "sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==", - "peer": true, "requires": { "csstype": "^3.1.0", "seroval": "~1.3.0", @@ -22264,8 +22234,7 @@ "picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "peer": true + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" } } }, @@ -22358,8 +22327,7 @@ "typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "peer": true + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==" }, "typescript-auto-import-cache": { "version": "0.3.6", @@ -22397,9 +22365,11 @@ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" }, "undici-types": { - "version": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "optional": true + "optional": true, + "peer": true }, "unicode-properties": { "version": "1.4.1", @@ -22918,7 +22888,6 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "peer": true, "requires": {} }, "xml-name-validator": { @@ -23099,8 +23068,7 @@ "zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "peer": true + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==" }, "zod-to-json-schema": { "version": "3.24.6", diff --git a/package.json b/package.json index aae4186..db5a600 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Personal website created with Astro.", "author": { "name": "Sergey Yarkov", - "email": "serzh.yarkov@gmail.com", + "email": "email@yarkov.tech", "url": "https://yarkov.tech" }, "license": "MIT", @@ -16,7 +16,6 @@ "start": "node --env-file=.env ./dist/server/entry.mjs", "preview": "astro preview", "astro": "astro", - "directus:gen-types": "node --env-file=.env ./scripts/gen-types.js", "codegen": "graphql-codegen --require dotenv/config --config codegen.ts --watch" }, "dependencies": { @@ -25,7 +24,6 @@ "@astrojs/rss": "^4.0.13", "@astrojs/sitemap": "^3.6.0", "@astrojs/solid-js": "^5.1.3", - "@directus/sdk": "^20.1.1", "@iconify-json/mdi": "^1.2.3", "astro": "^5.15.8", "astro-icon": "^1.1.5", @@ -55,7 +53,6 @@ "@types/html-escaper": "^3.0.4", "@types/mime-types": "^2.1.4", "@types/remark-prism": "^1.3.7", - "directus-sdk-typegen": "^0.2.1", "dotenv": "^17.2.3", "sass": "^1.68.0", "typescript": "^5.9.3" diff --git a/schema.graphql b/schema.graphql index 03f36ec..ce758b1 100644 --- a/schema.graphql +++ b/schema.graphql @@ -287,7 +287,7 @@ type article_translations { tags(filter: article_translations_tag_filter, limit: Int, offset: Int, page: Int, search: String, sort: [String]): [article_translations_tag] tags_func: count_functions title: String! - views: Int + views: Int! } type article_translations_aggregated { @@ -482,7 +482,7 @@ input create_article_translations_input { status: String tags: [create_article_translations_tag_input] title: String! - views: Int + views: Int! } input create_article_translations_tag_input { diff --git a/scripts/gen-types.js b/scripts/gen-types.js deleted file mode 100644 index 2d36496..0000000 --- a/scripts/gen-types.js +++ /dev/null @@ -1,15 +0,0 @@ -import { generateDirectusTypes } from "directus-sdk-typegen"; - -async function generateTypes() { - try { - await generateDirectusTypes({ - outputPath: "./directus-schema.ts", - directusUrl: process.env.DIRECTUS_URL, - directusToken: process.env.DIRECTUS_TOKEN, - }); - } catch (error) { - console.error("Failed to generate types:", error); - } -} - -generateTypes(); diff --git a/src/components/ArticleItem/ArticleItem.tsx b/src/components/ArticleItem/ArticleItem.tsx index 9e09be3..8dcf7dd 100644 --- a/src/components/ArticleItem/ArticleItem.tsx +++ b/src/components/ArticleItem/ArticleItem.tsx @@ -2,20 +2,19 @@ import type { Component } from "solid-js"; import { createRelativeArticleUrl, createDateFormatter } from "@root/utils"; import { DEFAULT_LANGUAGE, URL_BLOG_PREFIX } from "@root/constants"; import "./ArticleItem.scss"; -import type { ArticleTranslation } from "@/directus-schema"; +import { Article_Translations } from "@/src/graphql/graphql"; export type ArticleItemProps = { - data: ArticleTranslation; + title: Article_Translations["title"]; + pub_date: Article_Translations["pub_date"]; + slug: Article_Translations["slug"]; + languages_code: Article_Translations["languages_code"]; pageLang: string; }; const ArticleItem: Component = (props) => { - const { - data: { title, pub_date: pubDate, slug, languages_code }, - pageLang, - } = props; - const articleLang = - typeof languages_code === "object" ? languages_code.code.split("-")[0] : DEFAULT_LANGUAGE; + const { title, pub_date: pubDate, slug, languages_code, pageLang } = props; + const articleLang = languages_code?.code.split("-")[0] || DEFAULT_LANGUAGE; const href = createRelativeArticleUrl({ pubDate, slug, articleLang }, URL_BLOG_PREFIX); diff --git a/src/components/ArticlePost.astro b/src/components/ArticlePost.astro index 5fcdac4..74fde3e 100644 --- a/src/components/ArticlePost.astro +++ b/src/components/ArticlePost.astro @@ -6,19 +6,28 @@ import ArticleComments from "@components/ArticleComments.astro"; import TranslatedLink from "@components/TranslatedLink.astro"; import AvailableOnLangs from "@components/AvailableOnLangs.astro"; import { useTranslation, getLanguageFromURL } from "@i18n/utils"; -import type { ArticleTranslation } from "@/directus-schema"; import { DIRECTUS_URL } from "astro:env/server"; +import { Article_TranslationsQuery } from "../graphql/graphql"; export type Props = { - article: ArticleTranslation; + article: Article_TranslationsQuery["article_translations"][0]; lang: string; }; const { article } = Astro.props as Props; const pageLang = getLanguageFromURL(Astro.url.pathname); const canonicalUrl = new URL(Astro.url.pathname, Astro.site); -const { cover_image, title, author, description, tags, pub_date, slug, views, article_id } = - article; +const { + cover_image, + title, + author, + description, + tags, + pub_date, + slug, + views, + article_id: articleTranslations, +} = article; const t = useTranslation(Astro); --- @@ -29,16 +38,13 @@ const t = useTranslation(Astro); tags && (
    - {tags.map( - (tag) => - typeof tag === "object" && ( -
  • - -
  • - ) - )} + {tags.map((tag) => ( +
  • + +
  • + ))}
) @@ -55,7 +61,7 @@ const t = useTranslation(Astro); - + { cover_image && ( @@ -67,7 +73,7 @@ const t = useTranslation(Astro); {description}

- + diff --git a/src/components/ArticlesList/ArticlesList.tsx b/src/components/ArticlesList/ArticlesList.tsx index bae0b39..9779986 100644 --- a/src/components/ArticlesList/ArticlesList.tsx +++ b/src/components/ArticlesList/ArticlesList.tsx @@ -5,7 +5,6 @@ import SearchInput from "./SearchInput"; import TagsList from "./TagsList"; import ArticleItem from "@components/ArticleItem"; import "./ArticlesList.scss"; -import type { ArticleTranslation } from "@/directus-schema"; import { ArticleQuery } from "@/src/graphql/graphql"; type UiStringsType = { "articles.empty": string; "input.search": string }; @@ -24,7 +23,7 @@ const ArticlesList: Component = (props) => { const isEmpty = () => Object.keys(articles()).length === 0; - const sortYears = (articles: ArticlesBlockType) => { + const sortByYears = (articles: ArticlesBlockType) => { return Object.keys(articles) .map(Number) .sort((a, b) => b - a); @@ -35,22 +34,26 @@ const ArticlesList: Component = (props) => { }: { params: { search: string; tags?: string[] }; }): ArticlesBlockType => { - const filter = (cb: (articles: ArticleTranslation[]) => ArticleTranslation[]) => { + const filter = ( + cb: ( + articles: ArticleQuery["article"][0]["translations"] + ) => ArticleQuery["article"][0]["translations"] + ) => { return Object.fromEntries( Object.keys(props.articles) .map((year) => [year, cb(props.articles[year])]) - .filter((articles) => articles[1].length !== 0) + .filter((articles) => articles[1]?.length !== 0) ); }; return filter((articles) => { - let filtered = articles.filter((a) => - a.title.toLocaleLowerCase().includes(search.trim().toLocaleLowerCase()) + let filtered = articles?.filter( + (a) => a && a.title.toLocaleLowerCase().includes(search.trim().toLocaleLowerCase()) ); if (tags && tags.length > 0) { - filtered = filtered.filter((a) => + filtered = filtered?.filter((a) => tags.some((t) => { - return a.tags.map((t) => t.tag_id.title).includes(t); + return a?.tags?.map((t) => t?.tag_id?.title).includes(t); }) ); } @@ -70,12 +73,22 @@ const ArticlesList: Component = (props) => {
{!isEmpty() ? ( - + {(year) => (

{year}

- {(data) => } + {(a) => + a && ( + + ) + }
)} diff --git a/src/components/AvailableOnLangs.astro b/src/components/AvailableOnLangs.astro index c38589b..c5be465 100644 --- a/src/components/AvailableOnLangs.astro +++ b/src/components/AvailableOnLangs.astro @@ -1,10 +1,10 @@ --- import { getLanguageFromURL, useTranslation } from "@root/i18n/utils"; import { createRelativeArticleUrl } from "@root/utils"; -import type { ArticleTranslation } from "@/directus-schema"; +import { Article_TranslationsQuery } from "../graphql/graphql"; export interface Props { - articles: ArticleTranslation[]; + articles: Article_TranslationsQuery["article_translations"][0]["article_id"]; } const pageLang = getLanguageFromURL(Astro.url.pathname); @@ -13,16 +13,19 @@ const { articles } = Astro.props; --- { - articles.length !== 1 && ( + articles && articles.translations && articles.translations?.length !== 1 && (
{t("article.availableOn")}:{" "} - {articles - .filter((a) => a.languages_code.code.split("-")[0] !== pageLang) - .map((a) => ( - {`${a.languages_code.name}`} - ))} + {articles.translations + .filter((a) => a && a.languages_code?.code.split("-")[0] !== pageLang) + .map( + (a) => + a && ( + {`${a.languages_code?.name}`} + ) + )}
) } diff --git a/src/components/RecentArticles.astro b/src/components/RecentArticles.astro index a4f5994..3a9073e 100644 --- a/src/components/RecentArticles.astro +++ b/src/components/RecentArticles.astro @@ -5,7 +5,7 @@ import ArticleItem from "@components/ArticleItem"; import EmptyList from "@components/EmptyList.astro"; import UIString from "@components/UIString.astro"; import TranslatedLink from "@components/TranslatedLink.astro"; -import { fetchRecentArticles } from "@/directus"; +import { getRecentArticleList } from "../queries"; export interface Props { limit?: number; @@ -13,7 +13,7 @@ export interface Props { const { limit = 1 } = Astro.props; const pageLang = getLanguageFromURL(Astro.url.pathname); -const data = await fetchRecentArticles(); +const data = await getRecentArticleList(); const articles = data.flatMap((a) => utils.removeArticleDuplicates(a.translations, pageLang)); const isEmpty = articles.length === 0; --- @@ -32,7 +32,18 @@ const isEmpty = articles.length === 0; !isEmpty ? ( articles .slice(0, limit) - .map((article) => article && ) + .map( + (a) => + a && ( + + ) + ) ) : ( ) diff --git a/src/graphql/gql.ts b/src/graphql/gql.ts index 1ac5080..c5f8fb1 100644 --- a/src/graphql/gql.ts +++ b/src/graphql/gql.ts @@ -16,10 +16,14 @@ import * as types from './graphql'; */ type Documents = { "\n\t\tquery Article {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\tid\n\t\t\t\t\ttitle\n\t\t\t\t\ttags {\n\t\t\t\t\t\ttag_id {\n\t\t\t\t\t\t\ttitle\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdescription\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t\tname\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": typeof types.ArticleDocument, + "\n\t\tquery RecentArticle {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\ttitle\n\t\t\t\t\tcover_image {\n\t\t\t\t\t\tid\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tviews\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": typeof types.RecentArticleDocument, + "\n\t\tquery Article_translations($slug: String!) {\n\t\t\tarticle_translations(filter: { slug: { _eq: $slug } }) {\n\t\t\t\tid\n\t\t\t\ttitle\n\t\t\t\ttags {\n\t\t\t\t\ttag_id {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdescription\n\t\t\t\tslug\n\t\t\t\tcontent\n\t\t\t\tauthor {\n\t\t\t\t\tfirst_name\n\t\t\t\t\tlast_name\n\t\t\t\t}\n\t\t\t\tpub_date\n\t\t\t\tviews\n\t\t\t\tlanguages_code {\n\t\t\t\t\tcode\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcover_image {\n\t\t\t\t\ttitle\n\t\t\t\t\ttype\n\t\t\t\t\tfilename_disk\n\t\t\t\t}\n\t\t\t\tarticle_id {\n\t\t\t\t\ttranslations {\n\t\t\t\t\t\tslug\n\t\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\t\tcode\n\t\t\t\t\t\t\tname\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpub_date\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": typeof types.Article_TranslationsDocument, "\n\t\tquery Tag {\n\t\t\ttag {\n\t\t\t\tid\n\t\t\t\ttitle\n\t\t\t}\n\t\t}\n\t": typeof types.TagDocument, }; const documents: Documents = { "\n\t\tquery Article {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\tid\n\t\t\t\t\ttitle\n\t\t\t\t\ttags {\n\t\t\t\t\t\ttag_id {\n\t\t\t\t\t\t\ttitle\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdescription\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t\tname\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.ArticleDocument, + "\n\t\tquery RecentArticle {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\ttitle\n\t\t\t\t\tcover_image {\n\t\t\t\t\t\tid\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tviews\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.RecentArticleDocument, + "\n\t\tquery Article_translations($slug: String!) {\n\t\t\tarticle_translations(filter: { slug: { _eq: $slug } }) {\n\t\t\t\tid\n\t\t\t\ttitle\n\t\t\t\ttags {\n\t\t\t\t\ttag_id {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdescription\n\t\t\t\tslug\n\t\t\t\tcontent\n\t\t\t\tauthor {\n\t\t\t\t\tfirst_name\n\t\t\t\t\tlast_name\n\t\t\t\t}\n\t\t\t\tpub_date\n\t\t\t\tviews\n\t\t\t\tlanguages_code {\n\t\t\t\t\tcode\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcover_image {\n\t\t\t\t\ttitle\n\t\t\t\t\ttype\n\t\t\t\t\tfilename_disk\n\t\t\t\t}\n\t\t\t\tarticle_id {\n\t\t\t\t\ttranslations {\n\t\t\t\t\t\tslug\n\t\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\t\tcode\n\t\t\t\t\t\t\tname\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpub_date\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.Article_TranslationsDocument, "\n\t\tquery Tag {\n\t\t\ttag {\n\t\t\t\tid\n\t\t\t\ttitle\n\t\t\t}\n\t\t}\n\t": types.TagDocument, }; @@ -27,6 +31,14 @@ const documents: Documents = { * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n\t\tquery Article {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\tid\n\t\t\t\t\ttitle\n\t\t\t\t\ttags {\n\t\t\t\t\t\ttag_id {\n\t\t\t\t\t\t\ttitle\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdescription\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t\tname\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): typeof import('./graphql').ArticleDocument; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n\t\tquery RecentArticle {\n\t\t\tarticle {\n\t\t\t\ttranslations(filter: { status: { _eq: \"published\" } }) {\n\t\t\t\t\ttitle\n\t\t\t\t\tcover_image {\n\t\t\t\t\t\tid\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t\tslug\n\t\t\t\t\tpub_date\n\t\t\t\t\tviews\n\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\tcode\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): typeof import('./graphql').RecentArticleDocument; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n\t\tquery Article_translations($slug: String!) {\n\t\t\tarticle_translations(filter: { slug: { _eq: $slug } }) {\n\t\t\t\tid\n\t\t\t\ttitle\n\t\t\t\ttags {\n\t\t\t\t\ttag_id {\n\t\t\t\t\t\ttitle\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdescription\n\t\t\t\tslug\n\t\t\t\tcontent\n\t\t\t\tauthor {\n\t\t\t\t\tfirst_name\n\t\t\t\t\tlast_name\n\t\t\t\t}\n\t\t\t\tpub_date\n\t\t\t\tviews\n\t\t\t\tlanguages_code {\n\t\t\t\t\tcode\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcover_image {\n\t\t\t\t\ttitle\n\t\t\t\t\ttype\n\t\t\t\t\tfilename_disk\n\t\t\t\t}\n\t\t\t\tarticle_id {\n\t\t\t\t\ttranslations {\n\t\t\t\t\t\tslug\n\t\t\t\t\t\tlanguages_code {\n\t\t\t\t\t\t\tcode\n\t\t\t\t\t\t\tname\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpub_date\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): typeof import('./graphql').Article_TranslationsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/src/graphql/graphql.ts b/src/graphql/graphql.ts index 6c42178..25b4ffa 100644 --- a/src/graphql/graphql.ts +++ b/src/graphql/graphql.ts @@ -1411,7 +1411,7 @@ export type Article_Translations = { tags?: Maybe>>; tags_func?: Maybe; title: Scalars['String']['output']; - views?: Maybe; + views: Scalars['Int']['output']; }; @@ -1686,7 +1686,7 @@ export type Create_Article_Translations_Input = { status?: InputMaybe; tags?: InputMaybe>>; title: Scalars['String']['input']; - views?: InputMaybe; + views: Scalars['Int']['input']; }; export type Create_Article_Translations_Tag_Input = { @@ -4302,6 +4302,18 @@ export type ArticleQueryVariables = Exact<{ [key: string]: never; }>; export type ArticleQuery = { __typename?: 'Query', article: Array<{ __typename?: 'article', translations?: Array<{ __typename?: 'article_translations', id: string, title: string, description: string, slug: string, pub_date: any, tags?: Array<{ __typename?: 'article_translations_tag', tag_id?: { __typename?: 'tag', title: string } | null } | null> | null, languages_code?: { __typename?: 'languages', code: string, name?: string | null } | null } | null> | null }> }; +export type RecentArticleQueryVariables = Exact<{ [key: string]: never; }>; + + +export type RecentArticleQuery = { __typename?: 'Query', article: Array<{ __typename?: 'article', translations?: Array<{ __typename?: 'article_translations', title: string, slug: string, pub_date: any, views: number, cover_image?: { __typename?: 'directus_files', id: string, title?: string | null } | null, languages_code?: { __typename?: 'languages', code: string } | null } | null> | null }> }; + +export type Article_TranslationsQueryVariables = Exact<{ + slug: Scalars['String']['input']; +}>; + + +export type Article_TranslationsQuery = { __typename?: 'Query', article_translations: Array<{ __typename?: 'article_translations', id: string, title: string, description: string, slug: string, content: string, pub_date: any, views: number, tags?: Array<{ __typename?: 'article_translations_tag', tag_id?: { __typename?: 'tag', title: string } | null } | null> | null, author?: { __typename?: 'directus_users', first_name?: string | null, last_name?: string | null } | null, languages_code?: { __typename?: 'languages', code: string, name?: string | null } | null, cover_image?: { __typename?: 'directus_files', title?: string | null, type?: string | null, filename_disk?: string | null } | null, article_id?: { __typename?: 'article', translations?: Array<{ __typename?: 'article_translations', slug: string, pub_date: any, languages_code?: { __typename?: 'languages', code: string, name?: string | null } | null } | null> | null } | null }> }; + export type TagQueryVariables = Exact<{ [key: string]: never; }>; @@ -4348,6 +4360,66 @@ export const ArticleDocument = new TypedDocumentString(` } } `) as unknown as TypedDocumentString; +export const RecentArticleDocument = new TypedDocumentString(` + query RecentArticle { + article { + translations(filter: {status: {_eq: "published"}}) { + title + cover_image { + id + title + } + slug + pub_date + views + languages_code { + code + } + } + } +} + `) as unknown as TypedDocumentString; +export const Article_TranslationsDocument = new TypedDocumentString(` + query Article_translations($slug: String!) { + article_translations(filter: {slug: {_eq: $slug}}) { + id + title + tags { + tag_id { + title + } + } + description + slug + content + author { + first_name + last_name + } + pub_date + views + languages_code { + code + name + } + cover_image { + title + type + filename_disk + } + article_id { + translations { + slug + languages_code { + code + name + } + pub_date + } + } + } +} + `) as unknown as TypedDocumentString; export const TagDocument = new TypedDocumentString(` query Tag { tag { diff --git a/src/layouts/article.astro b/src/layouts/article.astro index 5213b97..dd2ce11 100644 --- a/src/layouts/article.astro +++ b/src/layouts/article.astro @@ -7,13 +7,12 @@ import ArticleContent from "@components/ArticleContent.astro"; import ArticlePost from "@components/ArticlePost.astro"; import OpenGraph from "@components/OpenGraph.astro"; // import TableOfContents from "@root/components/TableOfContents.astro"; -import type { ArticleTranslation } from "@/directus-schema"; import { markdownToHTML } from "@utils/markdown"; +import { Article_TranslationsQuery } from "../graphql/graphql"; export interface Props { - lang?: string | undefined; - article: ArticleTranslation; - headings: MarkdownHeading[]; + lang?: string; + article: Article_TranslationsQuery["article_translations"][0]; } const canonicalUrl = new URL(Astro.url.pathname, Astro.site); @@ -28,17 +27,22 @@ const htmlContent = await markdownToHTML(content); title={title} siteName={SITE_METADATA.name} description={description} - type='article' + type="article" url={canonicalUrl.href} image={cover_image - ? { path: cover_image.filename_disk, width: "700", height: "400", type: cover_image.type } + ? { + path: `${cover_image.filename_disk}`, + width: "700", + height: "400", + type: `${cover_image.type}`, + } : undefined} /> - + -
+
diff --git a/src/pages/[blog]/[...url].astro b/src/pages/[blog]/[...url].astro index 6aab0af..9cc246f 100644 --- a/src/pages/[blog]/[...url].astro +++ b/src/pages/[blog]/[...url].astro @@ -1,17 +1,17 @@ --- import ArticleLayout from "@root/layouts/article.astro"; -import { fetchArticleTranslationsBySlug, incArticleTranslationViews } from "@/directus"; +import { getArticleTranslationsBySlug } from "@/src/queries"; const { url } = Astro.params as { blog: string; url: string }; const slug = url.split("/").at(-1); if (!slug) return Astro.redirect("/404"); -const article = await fetchArticleTranslationsBySlug(slug); +const article = await getArticleTranslationsBySlug(slug); if (!article) return Astro.redirect("/404"); -if (import.meta.env.PROD) await incArticleTranslationViews(article); +// if (import.meta.env.PROD) await incArticleTranslationViews(article); --- - + diff --git a/src/queries/article.ts b/src/queries/article.ts index 9f4107e..eeab121 100644 --- a/src/queries/article.ts +++ b/src/queries/article.ts @@ -31,3 +31,91 @@ export async function getArticleList() { return result.data.article; } + +export async function getRecentArticleList() { + const RecentArticleQuery = graphql(` + query RecentArticle { + article { + translations(filter: { status: { _eq: "published" } }) { + title + cover_image { + id + title + } + slug + pub_date + views + languages_code { + code + } + } + } + } + `); + + const result = await execute(RecentArticleQuery); + + if (!result.data) return []; + + return result.data.article; +} + +export async function getArticleTranslationsBySlug(slug: string) { + const ArticleTranslationQuery = graphql(` + query Article_translations($slug: String!) { + article_translations(filter: { slug: { _eq: $slug } }) { + id + title + tags { + tag_id { + title + } + } + description + slug + content + author { + first_name + last_name + } + pub_date + views + languages_code { + code + name + } + cover_image { + title + type + filename_disk + } + article_id { + translations { + slug + languages_code { + code + name + } + pub_date + } + } + } + } + `); + + const result = await execute(ArticleTranslationQuery, { slug }); + + if (!result.data || result.data.article_translations.length === 0) return null; + + return { ...result.data.article_translations[0] }; +} + +// export async function incArticleTranslationViews() { +// const IncArticleTranslationViewsQuery = graphql(` +// mutation Update_article_translations_item($id: ID!) { +// update_article_translations_item(id: $id, data: { views: ${article.views + 1} }) { +// views +// } +// } +// `) +// } diff --git a/src/utils/article.ts b/src/utils/article.ts index e8c101a..c3be000 100644 --- a/src/utils/article.ts +++ b/src/utils/article.ts @@ -1,20 +1,21 @@ import type { MarkdownHeading } from "astro"; import { DEFAULT_LANGUAGE } from "@root/constants"; -import type { ArticleTranslation } from "@/directus-schema"; -import { ArticleQuery } from "../graphql/graphql"; +import { ArticleQuery, RecentArticleQuery } from "../graphql/graphql"; /** * If there is a translation of an article in the current language of the page, * the remaining articles with other translations should be removed. */ export function removeArticleDuplicates( - articles: ArticleQuery["article"][0]["translations"], + articles: + | ArticleQuery["article"][0]["translations"] + | RecentArticleQuery["article"][0]["translations"], pageLang: LanguageKeys ) { if (!articles) return []; if (articles && articles.length >= 2) { const pageLangArticles = articles.filter( - (a) => a?.languages_code?.code.split("-")[0] === pageLang + (a) => a && a.languages_code?.code.split("-")[0] === pageLang ); if (pageLangArticles.length !== 0) return pageLangArticles; return articles;