From 5dcb790ff1c74b645faddc038e763acc0a68d4ad Mon Sep 17 00:00:00 2001
From: sergeyyarkov
Date: Mon, 24 Nov 2025 16:33:27 +0300
Subject: [PATCH] upd
---
directus-schema.ts | 658 -------------------
directus.ts | 146 ----
package-lock.json | 190 +++---
package.json | 5 +-
schema.graphql | 4 +-
scripts/gen-types.js | 15 -
src/components/ArticleItem/ArticleItem.tsx | 15 +-
src/components/ArticlePost.astro | 38 +-
src/components/ArticlesList/ArticlesList.tsx | 33 +-
src/components/AvailableOnLangs.astro | 23 +-
src/components/RecentArticles.astro | 17 +-
src/graphql/gql.ts | 12 +
src/graphql/graphql.ts | 76 ++-
src/layouts/article.astro | 20 +-
src/pages/[blog]/[...url].astro | 8 +-
src/queries/article.ts | 88 +++
src/utils/article.ts | 9 +-
17 files changed, 356 insertions(+), 1001 deletions(-)
delete mode 100644 directus-schema.ts
delete mode 100644 directus.ts
delete mode 100644 scripts/gen-types.js
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 && (
)
@@ -55,7 +61,7 @@ const t = useTranslation(Astro);
- {`${author.first_name} ${author.last_name}`}
+ {`${author?.first_name} ${author?.last_name}`}
{
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;