8 Commits

23 changed files with 834 additions and 844 deletions

49
GIZLILIK_POLITIKASI.md Normal file
View File

@@ -0,0 +1,49 @@
# 🛡️ hMarket - Gizlilik Politikası
**Son Güncelleme:** 22 Şubat 2026
Bu gizlilik politikası, **hMarket** (https://hmarket.mustafaozkaya.tr/) mobil uygulaması ve web platformu tarafından toplanan bilgilerin nasıl kullanıldığını, saklandığını ve korunduğunu açıklamaktadır. hMarket, kullanıcılarına akıllı alışveriş listeleri oluşturma, yönetme ve paylaşma hizmeti sunan bir PWA (Progressive Web App) uygulamasıdır.
---
### 1. Toplanan Veriler
hMarket'i kullandığınızda aşağıdaki kategorilerde veriler toplanabilir:
* **Hesap Bilgileri:** Kayıt sırasında sağladığınız ad, soyad ve e-posta adresi.
* **Sosyal Giriş Bilgileri:** Google ile giriş yaptığınızda, Google profilinizden sağlanan isim, e-posta ve profil fotoğrafı.
* **İçerik Verileri:** Oluşturduğunuz alışveriş listeleri, eklediğiniz ürünler, miktarlar ve paylaştığınız kişilerin bilgileri.
* **Teknik Veriler:** IP adresi, cihaz türü, tarayıcı bilgileri ve uygulama içi kullanım istatistikleri.
* **Bildirim Verileri:** Push bildirimleri gönderebilmek amacıyla Firebase üzerinden alınan cihaz jetonları (tokens).
### 2. Verilerin Kullanım Amacı
Toplanan veriler aşağıdaki süreçler için kullanılır:
* Alışveriş listelerinin cihazlar arasında senkronize edilmesi.
* Listelerin diğer kullanıcılarla paylaşılarak ortak çalışma imkanı sunulması.
* Listelerde yapılan değişiklikler hakkında gerçek zamanlı bildirim gönderilmesi.
* Kullanıcı deneyiminin iyileştirilmesi ve teknik hataların giderilmesi.
### 3. Verilerin Paylaşımı ve Saklanması
Kişisel verileriniz, yasal zorunluluklar veya hizmetin teknik gereklilikleri (Örn: Bildirimler için Firebase, Giriş için Google) dışında **üçüncü şahıslarla paylaşılmaz.** Verileriniz güvenli veritabanlarında şifrelenmiş olarak saklanır.
### 4. Çerezler ve Yerel Depolama
hMarket, oturumunuzu açık tutmak ve tercihlerinizi hatırlamak için tarayıcınızın **Local Storage** ve **Cookies** (çerezler) özelliklerini kullanır.
### 5. Kullanıcı Hakları (KVKK / GDPR)
Kullanıcılar olarak her zaman şu haklara sahipsiniz:
* Hangi verilerinizin tutulduğunu sorgulama.
* Yanlış verilerin düzeltilmesini isteme.
* Hesabınızı ve tüm listelerinizi kalıcı olarak silme.
* Pazarlama amaçlı veri kullanımına itiraz etme.
### 6. Hesap ve Veri Silme
Kullanıcılar, uygulama içindeki profil ayarlarından hesaplarını ve hesaplarına bağlı tüm verileri istedikleri an silebilirler. Silinen veriler geri getirilemez şekilde sistemden kaldırılır.
### 7. İletişim
Gizlilik politikası hakkındaki sorularınız ve veri talepleriniz için:
* **Geliştirici:** Mustafa ÖZKAYA
* **Web:** https://www.mustafaozkaya.tr/
* **E-posta:** [E-posta adresinizi buraya ekleyin]
---
*Bu belge hMarket uygulamasının modern gizlilik standartlarına uyumu için hOLOlu tarafından hazırlanmıştır.*

33
KULLANIM_SARTLARI.md Normal file
View File

@@ -0,0 +1,33 @@
# 📜 hMarket - Kullanım Şartları
**Son Güncelleme:** 22 Şubat 2026
hMarket uygulamasını kullanarak aşağıdaki şartları kabul etmiş sayılırsınız. Lütfen bu metni dikkatlice okuyunuz.
---
### 1. Hizmet Tanımı
hMarket, Mustafa ÖZKAYA tarafından geliştirilen, kullanıcıların kişisel veya paylaşımlı alışveriş listeleri oluşturmasına olanak tanıyan bir yazılım hizmetidir.
### 2. Kullanım Koşulları
* Uygulamayı kullanmak için geçerli bir e-posta adresi veya Google hesabı ile kayıt olmanız gerekebilir.
* Hesap bilgilerinizin güvenliğinden tamamen siz sorumlusunuz.
* Uygulama, kişisel kullanım için tasarlanmıştır; sistemin işleyişini bozacak saldırı veya tersine mühendislik çabaları yasaktır.
### 3. Fikri Mülkiyet Hakları
hMarket yazılımı, tasarımı, logosu ve tüm kod içeriği Mustafa ÖZKAYA'ya aittir. İzinsiz kopyalanamaz veya dağıtılamaz.
### 4. Sorumluluk Reddi
* hMarket, "olduğu gibi" sunulur. Teknik arızalar, veri kayıpları veya sistem kesintilerinden kaynaklanabilecek dolaylı zararlardan geliştirici sorumlu tutulamaz.
* Kullanıcıların listelerine eklediği içeriklerin doğruluğu ve yasal sorumluluğu kullanıcıya aittir.
### 5. Değişiklikler
Geliştirici, hizmet şartlarını önceden haber vermeksizin güncelleme hakkını saklı tutar. Güncel şartlar uygulama içinden veya web sitesinden takip edilebilir.
### 6. İletişim
Hizmet şartları hakkında sorularınız için:
* **Geliştirici:** Mustafa ÖZKAYA
* **E-posta:** [E-posta adresinizi buraya ekleyin]
---
*hMarket hizmet kalitesini ve kullanıcı güvenliğini ön planda tutar.*

View File

@@ -1907,28 +1907,58 @@
}
},
"node_modules/body-parser": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
"integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"bytes": "~3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.13.0",
"raw-body": "2.5.2",
"destroy": "~1.2.0",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
"qs": "~6.14.0",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/body-parser/node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
@@ -2781,38 +2811,39 @@
}
},
"node_modules/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
"integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"body-parser": "~1.20.3",
"content-disposition": "~0.5.4",
"content-type": "~1.0.4",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"cookie": "~0.7.1",
"cookie-signature": "~1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"finalhandler": "~1.3.1",
"fresh": "~0.5.2",
"http-errors": "~2.0.0",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"on-finished": "~2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.12",
"path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"qs": "~6.14.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.19.0",
"serve-static": "1.16.2",
"send": "~0.19.0",
"serve-static": "~1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"statuses": "~2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
@@ -2871,12 +2902,13 @@
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
},
"node_modules/express-validator": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.2.1.tgz",
"integrity": "sha512-CjNE6aakfpuwGaHQZ3m8ltCG2Qvivd7RHtVMS/6nVxOM7xVGqr4bhflsm4+N5FP5zI7Zxp+Hae+9RE+o8e3ZOQ==",
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.3.1.tgz",
"integrity": "sha512-IGenaSf+DnWc69lKuqlRE9/i/2t5/16VpH5bXoqdxWz1aCpRvEdrBuu1y95i/iL5QP8ZYVATiwLFhwk3EDl5vg==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21",
"validator": "~13.12.0"
"validator": "~13.15.23"
},
"engines": {
"node": ">= 8.0.0"
@@ -2915,18 +2947,19 @@
"dev": true
},
"node_modules/fast-xml-parser": {
"version": "4.5.3",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
"integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz",
"integrity": "sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"optional": true,
"dependencies": {
"strnum": "^1.1.1"
"strnum": "^1.0.5"
},
"bin": {
"fxparser": "src/cli/cli.js"
@@ -3075,7 +3108,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -3535,6 +3567,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -4387,10 +4420,11 @@
"dev": true
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -4470,11 +4504,12 @@
}
},
"node_modules/jsonwebtoken/node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
"integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"jwa": "^1.4.2",
"safe-buffer": "^5.0.1"
}
},
@@ -4543,12 +4578,13 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
"license": "MIT",
"optional": true,
"dependencies": {
"jwa": "^2.0.0",
"jwa": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
@@ -4594,9 +4630,10 @@
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT"
},
"node_modules/lodash.camelcase": {
"version": "4.3.0",
@@ -4820,10 +4857,11 @@
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -4953,9 +4991,10 @@
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz",
"integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==",
"license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
"node": ">= 6.13.0"
}
@@ -5501,11 +5540,12 @@
]
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"version": "6.14.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
@@ -5531,19 +5571,49 @@
}
},
"node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
"integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/raw-body/node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/raw-body/node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -5680,7 +5750,8 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/semver": {
"version": "6.3.1",
@@ -6559,9 +6630,10 @@
}
},
"node_modules/validator": {
"version": "13.12.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
"integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
"version": "13.15.26",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
"integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}

BIN
backend/prisma/dev.db Normal file

Binary file not shown.

View File

@@ -1,5 +1,5 @@
// HMarket Veritabanı Şeması
// MariaDB için Prisma ORM konfigürasyonu
// MySQL için Prisma ORM konfigürasyonu
generator client {
provider = "prisma-client-js"
@@ -128,7 +128,7 @@ model Product {
id String @id @default(cuid())
name String
description String?
barcode String? @unique
barcode String? // barkod opsiyonel
brand String?
unit String? // Ürün varsayılan birimi
categoryId String?
@@ -153,7 +153,7 @@ model ListItem {
customName String? // Ürün yoksa manuel isim
quantity Float @default(1)
unit String @default("adet") // "kg", "lt", "adet", vb.
price Decimal? @db.Decimal(10, 2)
price Decimal? // SQLite: Decimal stored as String
note String?
isPurchased Boolean @default(false)
purchasedAt DateTime?
@@ -174,7 +174,7 @@ model ListItem {
model PriceHistory {
id String @id @default(cuid())
productId String
price Decimal @db.Decimal(10, 2)
price Decimal // SQLite: Decimal stored as String
store String? // Mağaza adı
location String? // Konum bilgisi
source String @default("user") // "user", "api", "scraping"
@@ -193,7 +193,7 @@ model Notification {
title String
message String
type String // "list_shared", "item_added", "item_purchased", "price_alert"
data Json? // Ek veri (JSON format)
data String? // Ek veri (JSON format - SQLite String olarak saklanır)
isRead Boolean @default(false)
createdAt DateTime @default(now())
@@ -209,7 +209,7 @@ model Activity {
listId String
userId String
action String // "item_added", "item_removed", "item_updated", "item_purchased"
details Json? // Aktivite detayları
details String? // Aktivite detayları (JSON - SQLite String olarak saklanır)
createdAt DateTime @default(now())
// İlişkiler

View File

@@ -1,389 +1,139 @@
const { PrismaClient } = require('@prisma/client');
const bcrypt = require('bcryptjs');
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient();
const prisma = new PrismaClient()
async function main() {
console.log('🌱 Veritabanı seed işlemi başlatılıyor...');
console.log('Örnek veriler ekleniyor...')
// Admin kullanıcısı oluştur
const hashedPassword = await bcrypt.hash('admin123', 12);
// Kullanıcılar
const user1 = await prisma.user.create({
data: {
email: 'mustafa@example.com',
username: 'mustafa',
firstName: 'Mustafa',
lastName: 'ÖZKAYA',
password: '$2a$10$dummy',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=mustafa',
}
})
const adminUser = await prisma.user.upsert({
where: { email: 'admin@hmarket.com' },
update: {},
create: {
email: 'admin@hmarket.com',
username: 'admin',
firstName: 'Admin',
lastName: 'User',
password: hashedPassword,
isAdmin: true,
},
});
console.log('✅ Admin kullanıcısı oluşturuldu:', adminUser.email);
// Test kullanıcıları oluştur
const testUsers = [
{
email: 'ahmet@test.com',
const user2 = await prisma.user.create({
data: {
email: 'ahmet@example.com',
username: 'ahmet',
firstName: 'Ahmet',
lastName: 'Yılmaz',
password: await bcrypt.hash('test123', 12),
},
{
email: 'ayse@test.com',
password: '$2a$10$dummy',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=ahmet',
}
})
const user3 = await prisma.user.create({
data: {
email: 'ayse@example.com',
username: 'ayse',
firstName: 'Ayşe',
lastName: 'Kaya',
password: await bcrypt.hash('test123', 12),
},
{
email: 'mehmet@test.com',
username: 'mehmet',
firstName: 'Mehmet',
lastName: 'Demir',
password: await bcrypt.hash('test123', 12),
},
];
for (const userData of testUsers) {
const user = await prisma.user.upsert({
where: { email: userData.email },
update: {},
create: userData,
});
console.log('✅ Test kullanıcısı oluşturuldu:', user.email);
password: '$2a$10$dummy',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=ayse',
}
})
// Kategoriler oluştur
const categories = [
{ name: 'Meyve & Sebze', description: 'Taze meyve ve sebzeler', icon: '🥕', color: '#4CAF50' },
{ name: 'Et & Tavuk', description: 'Kırmızı et, beyaz et ve şarküteri ürünleri', icon: '🥩', color: '#F44336' },
{ name: 'Süt Ürünleri', description: 'Süt, peynir, yoğurt ve diğer süt ürünleri', icon: '🥛', color: '#2196F3' },
{ name: 'Fırın & Pastane', description: 'Ekmek, pasta ve unlu mamuller', icon: '🍞', color: '#FF9800' },
{ name: 'Atıştırmalık', description: 'Çikolata, bisküvi ve atıştırmalık ürünler', icon: '🍿', color: '#9C27B0' },
{ name: 'İçecek', description: 'Alkolsüz içecekler ve sıcak içecekler', icon: '🥤', color: '#00BCD4' },
{ name: 'Temizlik', description: 'Ev temizlik ürünleri ve deterjanlar', icon: '🧽', color: '#607D8B' },
{ name: 'Kişisel Bakım', description: 'Kişisel hijyen ve bakım ürünleri', icon: '🧴', color: '#E91E63' },
{ name: 'Bebek', description: 'Bebek bakım ürünleri ve mama', icon: '🍼', color: '#FFEB3B' },
{ name: 'Dondurulmuş', description: 'Dondurulmuş gıda ürünleri', icon: '🧊', color: '#3F51B5' },
];
console.log('✅ Kullanıcılar oluşturuldu')
for (const categoryData of categories) {
const category = await prisma.category.upsert({
where: { name: categoryData.name },
update: {},
create: categoryData,
});
console.log('✅ Kategori oluşturuldu:', category.name);
}
// Kategoriler
const cat1 = await prisma.category.create({ data: { name: 'Sebze & Meyve', icon: '🥬', color: '#4CAF50' } })
const cat2 = await prisma.category.create({ data: { name: 'Et & Tavuk', icon: '🥩', color: '#F44336' } })
const cat3 = await prisma.category.create({ data: { name: 'Süt & Süt Ürünleri', icon: '🥛', color: '#2196F3' } })
const cat4 = await prisma.category.create({ data: { name: 'Ekmek & Unlu Mamüller', icon: '🍞', color: '#FF9800' } })
const cat5 = await prisma.category.create({ data: { name: 'İçecekler', icon: '🥤', color: '#9C27B0' } })
const cat6 = await prisma.category.create({ data: { name: 'Temizlik', icon: '🧹', color: '#607D8B' } })
const cat7 = await prisma.category.create({ data: { name: 'Atıştırmalık', icon: '🍪', color: '#795548' } })
const cat8 = await prisma.category.create({ data: { name: 'Dondurma', icon: '🍦', color: '#E91E63' } })
// Örnek ürünler oluştur
const products = [
// Meyve & Sebze
{ name: 'Elma', categoryName: 'Meyve & Sebze', barcode: '1234567890123', averagePrice: 12.50 },
{ name: 'Muz', categoryName: 'Meyve & Sebze', barcode: '1234567890124', averagePrice: 18.00 },
{ name: 'Domates', categoryName: 'Meyve & Sebze', barcode: '1234567890125', averagePrice: 8.75 },
{ name: 'Salatalık', categoryName: 'Meyve & Sebze', barcode: '1234567890126', averagePrice: 6.50 },
{ name: 'Soğan', categoryName: 'Meyve & Sebze', barcode: '1234567890127', averagePrice: 4.25 },
{ name: 'Patates', categoryName: 'Meyve & Sebze', barcode: '1234567890137', averagePrice: 5.75 },
{ name: 'Havuç', categoryName: 'Meyve & Sebze', barcode: '1234567890138', averagePrice: 7.50 },
{ name: 'Biber', categoryName: 'Meyve & Sebze', barcode: '1234567890139', averagePrice: 15.00 },
{ name: 'Portakal', categoryName: 'Meyve & Sebze', barcode: '1234567890140', averagePrice: 10.00 },
{ name: 'Limon', categoryName: 'Meyve & Sebze', barcode: '1234567890141', averagePrice: 8.00 },
console.log('✅ Kategoriler oluşturuldu')
// Süt Ürünleri
{ name: 'Süt 1L', categoryName: 'Süt Ürünleri', barcode: '1234567890128', averagePrice: 8.75 },
{ name: 'Yoğurt 500g', categoryName: 'Süt Ürünleri', barcode: '1234567890129', averagePrice: 12.50 },
{ name: 'Beyaz Peynir', categoryName: 'Süt Ürünleri', barcode: '1234567890130', averagePrice: 45.00 },
{ name: 'Kaşar Peyniri', categoryName: 'Süt Ürünleri', barcode: '1234567890131', averagePrice: 65.00 },
{ name: 'Tereyağı', categoryName: 'Süt Ürünleri', barcode: '1234567890142', averagePrice: 35.00 },
{ name: 'Yumurta 30\'lu', categoryName: 'Süt Ürünleri', barcode: '1234567890143', averagePrice: 85.00 },
{ name: 'Krema', categoryName: 'Süt Ürünleri', barcode: '1234567890144', averagePrice: 15.50 },
// Ürünler
const products = await Promise.all([
prisma.product.create({ data: { name: 'Domates', categoryId: cat1.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Soğan', categoryId: cat1.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Salatalık', categoryId: cat1.id, unit: 'adet' } }),
prisma.product.create({ data: { name: 'Tavuk Göğsü', categoryId: cat2.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Kıyma', categoryId: cat2.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Kırmızı Et', categoryId: cat2.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Süt', categoryId: cat3.id, unit: 'L' } }),
prisma.product.create({ data: { name: 'Yoğurt', categoryId: cat3.id, unit: 'adet' } }),
prisma.product.create({ data: { name: 'Ekmek', categoryId: cat4.id, unit: 'adet' } }),
prisma.product.create({ data: { name: 'Cola', categoryId: cat5.id, unit: 'adet' } }),
prisma.product.create({ data: { name: 'Bulaşık Deterjanı', categoryId: cat6.id, unit: 'adet' } }),
prisma.product.create({ data: { name: 'Baklava', categoryId: cat7.id, unit: 'kg' } }),
prisma.product.create({ data: { name: 'Dondurma', categoryId: cat8.id, unit: 'L' } }),
])
// Fırın & Pastane
{ name: 'Ekmek', categoryName: 'Fırın & Pastane', barcode: '1234567890132', averagePrice: 4.50 },
{ name: 'Simit', categoryName: 'Fırın & Pastane', barcode: '1234567890133', averagePrice: 2.50 },
{ name: 'Pide', categoryName: 'Fırın & Pastane', barcode: '1234567890145', averagePrice: 8.00 },
{ name: 'Çörek', categoryName: 'Fırın & Pastane', barcode: '1234567890146', averagePrice: 6.50 },
{ name: 'Kek', categoryName: 'Fırın & Pastane', barcode: '1234567890147', averagePrice: 25.00 },
console.log('✅ Ürünler oluşturuldu')
// İçecek
{ name: 'Su 1.5L', categoryName: 'İçecek', barcode: '1234567890134', averagePrice: 2.50 },
{ name: 'Çay', categoryName: 'İçecek', barcode: '1234567890135', averagePrice: 35.00 },
{ name: 'Kahve', categoryName: 'İçecek', barcode: '1234567890136', averagePrice: 85.00 },
{ name: 'Meyve Suyu', categoryName: 'İçecek', barcode: '1234567890148', averagePrice: 12.50 },
{ name: 'Kola', categoryName: 'İçecek', barcode: '1234567890149', averagePrice: 8.75 },
{ name: 'Ayran', categoryName: 'İçecek', barcode: '1234567890150', averagePrice: 4.50 },
// Et & Tavuk
{ name: 'Tavuk But', categoryName: 'Et & Tavuk', barcode: '1234567890151', averagePrice: 45.00 },
{ name: 'Dana Kıyma', categoryName: 'Et & Tavuk', barcode: '1234567890152', averagePrice: 120.00 },
{ name: 'Köfte', categoryName: 'Et & Tavuk', barcode: '1234567890153', averagePrice: 85.00 },
{ name: 'Sosis', categoryName: 'Et & Tavuk', barcode: '1234567890154', averagePrice: 25.00 },
// Temizlik
{ name: 'Deterjan', categoryName: 'Temizlik', barcode: '1234567890155', averagePrice: 45.00 },
{ name: 'Sabun', categoryName: 'Temizlik', barcode: '1234567890156', averagePrice: 8.50 },
{ name: 'Şampuan', categoryName: 'Temizlik', barcode: '1234567890157', averagePrice: 35.00 },
{ name: 'Diş Macunu', categoryName: 'Kişisel Bakım', barcode: '1234567890158', averagePrice: 18.50 },
// Atıştırmalık
{ name: 'Çikolata', categoryName: 'Atıştırmalık', barcode: '1234567890159', averagePrice: 12.50 },
{ name: 'Bisküvi', categoryName: 'Atıştırmalık', barcode: '1234567890160', averagePrice: 8.75 },
{ name: 'Cips', categoryName: 'Atıştırmalık', barcode: '1234567890161', averagePrice: 6.50 },
];
for (const productData of products) {
const category = await prisma.category.findUnique({
where: { name: productData.categoryName }
});
if (category) {
const product = await prisma.product.upsert({
where: { barcode: productData.barcode },
update: {},
create: {
name: productData.name,
barcode: productData.barcode,
categoryId: category.id,
},
});
console.log('✅ Ürün oluşturuldu:', product.name);
}
}
// Örnek alışveriş listeleri oluştur
const ahmetUser = await prisma.user.findUnique({
where: { email: 'ahmet@test.com' }
});
const ayseUser = await prisma.user.findUnique({
where: { email: 'ayse@test.com' }
});
const mehmetUser = await prisma.user.findUnique({
where: { email: 'mehmet@test.com' }
});
// Ahmet için alışveriş listeleri
if (ahmetUser) {
const shoppingLists = [
{
name: 'Haftalık Alışveriş',
description: 'Bu haftanın market alışverişi',
// Market Listeleri
const list1 = await prisma.shoppingList.create({
data: {
name: 'Haftalık Market',
description: 'Bu hafta alınacaklar',
color: '#4CAF50',
items: [
{ productName: 'Elma', quantity: 2, unit: 'kg', price: 15.50 },
{ productName: 'Süt 1L', quantity: 1, unit: 'adet', price: 8.75 },
{ customName: 'Deterjan', quantity: 1, unit: 'adet', price: 25.00, note: 'Çamaşır deterjanı' },
{ productName: 'Ekmek', quantity: 2, unit: 'adet', price: 9.00 },
{ productName: 'Yumurta 30\'lu', quantity: 1, unit: 'adet', price: 85.00 },
]
},
{
name: 'Kahvaltı Malzemeleri',
description: 'Kahvaltı için gerekli ürünler',
color: '#FF9800',
items: [
{ productName: 'Ekmek', quantity: 2, unit: 'adet', price: 9.00 },
{ productName: 'Beyaz Peynir', quantity: 1, unit: 'kg', price: 45.00 },
{ productName: 'Tereyağı', quantity: 1, unit: 'adet', price: 35.00 },
{ productName: 'Domates', quantity: 1, unit: 'kg', price: 8.75 },
{ productName: 'Salatalık', quantity: 2, unit: 'adet', price: 13.00 },
{ productName: 'Çay', quantity: 1, unit: 'adet', price: 35.00 },
]
ownerId: user1.id,
}
];
})
for (const listData of shoppingLists) {
const shoppingList = await prisma.shoppingList.create({
// Listeye üye ekle
await prisma.listMember.create({
data: {
name: listData.name,
description: listData.description,
color: listData.color,
ownerId: ahmetUser.id,
},
});
for (const itemData of listData.items) {
let productId = null;
if (itemData.productName) {
const product = await prisma.product.findFirst({
where: { name: itemData.productName }
});
if (product) {
productId = product.id;
}
userId: user2.id,
listId: list1.id,
role: 'admin'
}
})
await prisma.listItem.create({
// Liste Öğeleri (productId kullan)
await prisma.listItem.create({ data: { productId: products[0].id, quantity: 2, unit: 'kg', listId: list1.id } }) // Domates
await prisma.listItem.create({ data: { productId: products[1].id, quantity: 1, unit: 'kg', listId: list1.id } }) // Soğan
await prisma.listItem.create({ data: { productId: products[2].id, quantity: 3, unit: 'adet', listId: list1.id, isPurchased: true } }) // Salatalık
await prisma.listItem.create({ data: { productId: products[3].id, quantity: 1, unit: 'kg', listId: list1.id } }) // Tavuk
await prisma.listItem.create({ data: { productId: products[4].id, quantity: 0.5, unit: 'kg', listId: list1.id } }) // Kıyma
await prisma.listItem.create({ data: { productId: products[6].id, quantity: 2, unit: 'L', listId: list1.id, isPurchased: true } }) // Süt
await prisma.listItem.create({ data: { productId: products[7].id, quantity: 4, unit: 'adet', listId: list1.id } }) // Yoğurt
await prisma.listItem.create({ data: { productId: products[8].id, quantity: 2, unit: 'adet', listId: list1.id } }) // Ekmek
await prisma.listItem.create({ data: { productId: products[9].id, quantity: 6, unit: 'adet', listId: list1.id } }) // Cola
await prisma.listItem.create({ data: { productId: products[10].id, quantity: 1, unit: 'adet', listId: list1.id, isPurchased: true } }) // Deterjan
console.log('✅ İlk liste oluşturuldu')
// İkinci liste
const list2 = await prisma.shoppingList.create({
data: {
listId: shoppingList.id,
productId: productId,
customName: itemData.customName,
quantity: itemData.quantity,
unit: itemData.unit,
price: itemData.price,
note: itemData.note,
},
});
}
console.log('✅ Alışveriş listesi oluşturuldu:', shoppingList.name);
}
}
// Ayşe için alışveriş listeleri
if (ayseUser) {
const ayseShoppingLists = [
{
name: 'Parti Alışverişi',
description: 'Doğum günü partisi için',
name: 'Bayram Alışverişi',
description: 'Bayram için gerekli malzemeler',
color: '#E91E63',
items: [
{ productName: 'Kek', quantity: 1, unit: 'adet', price: 25.00 },
{ productName: 'Çikolata', quantity: 5, unit: 'adet', price: 62.50 },
{ productName: 'Bisküvi', quantity: 3, unit: 'paket', price: 26.25 },
{ productName: 'Kola', quantity: 6, unit: 'adet', price: 52.50 },
{ productName: 'Meyve Suyu', quantity: 4, unit: 'adet', price: 50.00 },
{ customName: 'Parti Süsleri', quantity: 1, unit: 'set', price: 45.00 },
]
},
{
name: 'Temizlik Malzemeleri',
description: 'Ev temizliği için gerekli ürünler',
color: '#607D8B',
items: [
{ productName: 'Deterjan', quantity: 2, unit: 'adet', price: 90.00 },
{ productName: 'Sabun', quantity: 3, unit: 'adet', price: 25.50 },
{ productName: 'Şampuan', quantity: 1, unit: 'adet', price: 35.00 },
{ customName: 'Cam Temizleyici', quantity: 1, unit: 'adet', price: 18.50 },
{ customName: 'Yer Bezi', quantity: 2, unit: 'adet', price: 15.00 },
]
ownerId: user1.id,
}
];
})
for (const listData of ayseShoppingLists) {
const shoppingList = await prisma.shoppingList.create({
data: {
name: listData.name,
description: listData.description,
color: listData.color,
ownerId: ayseUser.id,
},
});
await prisma.listItem.create({ data: { productId: products[5].id, quantity: 2, unit: 'kg', listId: list2.id } }) // Kırmızı Et
await prisma.listItem.create({ data: { productId: products[11].id, quantity: 1, unit: 'kg', listId: list2.id } }) // Baklava
await prisma.listItem.create({ data: { productId: products[12].id, quantity: 2, unit: 'L', listId: list2.id } }) // Dondurma
for (const itemData of listData.items) {
let productId = null;
console.log('✅ İkinci liste oluşturuldu')
if (itemData.productName) {
const product = await prisma.product.findFirst({
where: { name: itemData.productName }
});
if (product) {
productId = product.id;
}
}
await prisma.listItem.create({
data: {
listId: shoppingList.id,
productId: productId,
customName: itemData.customName,
quantity: itemData.quantity,
unit: itemData.unit,
price: itemData.price,
},
});
}
console.log('✅ Alışveriş listesi oluşturuldu:', shoppingList.name);
}
}
// Mehmet için alışveriş listesi
if (mehmetUser) {
const mehmetShoppingList = {
name: 'Et ve Protein',
description: 'Protein ihtiyacı için et ürünleri',
color: '#F44336',
items: [
{ productName: 'Tavuk But', quantity: 2, unit: 'kg', price: 90.00 },
{ productName: 'Dana Kıyma', quantity: 1, unit: 'kg', price: 120.00 },
{ productName: 'Köfte', quantity: 1, unit: 'kg', price: 85.00 },
{ productName: 'Sosis', quantity: 2, unit: 'paket', price: 50.00 },
{ productName: 'Yumurta 30\'lu', quantity: 1, unit: 'adet', price: 85.00 },
]
};
const shoppingList = await prisma.shoppingList.create({
data: {
name: mehmetShoppingList.name,
description: mehmetShoppingList.description,
color: mehmetShoppingList.color,
ownerId: mehmetUser.id,
},
});
for (const itemData of mehmetShoppingList.items) {
let productId = null;
if (itemData.productName) {
const product = await prisma.product.findFirst({
where: { name: itemData.productName }
});
if (product) {
productId = product.id;
}
}
await prisma.listItem.create({
data: {
listId: shoppingList.id,
productId: productId,
quantity: itemData.quantity,
unit: itemData.unit,
price: itemData.price,
},
});
}
console.log('✅ Alışveriş listesi oluşturuldu:', shoppingList.name);
}
console.log('✅ Tüm örnek alışveriş listeleri oluşturuldu');
// Sistem ayarları
const settings = [
{ key: 'app_name', value: 'HMarket', type: 'string' },
{ key: 'app_version', value: '1.0.0', type: 'string' },
{ key: 'max_list_members', value: '10', type: 'number' },
{ key: 'enable_notifications', value: 'true', type: 'boolean' },
{ key: 'default_currency', value: 'TL', type: 'string' },
];
for (const settingData of settings) {
await prisma.setting.upsert({
where: { key: settingData.key },
update: { value: settingData.value },
create: settingData,
});
console.log('✅ Ayar oluşturuldu:', settingData.key);
}
console.log('🎉 Seed işlemi tamamlandı!');
console.log('\n🎉 Örnek veriler başarıyla eklendi!')
console.log(` - 3 kullanıcı`)
console.log(` - 8 kategori`)
console.log(` - ${await prisma.product.count()} ürün`)
console.log(` - 2 liste`)
console.log(` - 13 liste öğesi`)
}
main()
.catch((e) => {
console.error('❌ Seed işlemi sırasında hata:', e);
process.exit(1);
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect();
});
await prisma.$disconnect()
})

View File

@@ -1,5 +1,4 @@
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
@@ -32,12 +31,15 @@ passport.deserializeUser(async (id, done) => {
}
});
// Google OAuth Strategy
passport.use(new GoogleStrategy({
// Google OAuth Strategy - Sadece credentials varsa yükle
if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_CALLBACK_URL || "/api/auth/google/callback"
}, async (accessToken, refreshToken, profile, done) => {
}, async (accessToken, refreshToken, profile, done) => {
try {
// Önce Google ID ile kullanıcı ara
let user = await prisma.user.findUnique({
@@ -93,6 +95,7 @@ passport.use(new GoogleStrategy({
console.error('Google OAuth Error:', error);
return done(error, null);
}
}));
}));
}
module.exports = passport;

View File

@@ -1,5 +1,4 @@
const express = require('express');
const { PrismaClient } = require('@prisma/client');
const { authenticateToken, checkListMembership, requireListEditPermission } = require('../middleware/auth');
const { asyncHandler } = require('../middleware/errorHandler');
const {
@@ -15,7 +14,6 @@ const { successResponse, errorResponse, calculatePagination, createPaginationMet
const notificationService = require('../services/notificationService');
const router = express.Router();
const prisma = new PrismaClient();
/**
* Liste öğelerini getir
@@ -68,8 +66,8 @@ router.get('/:listId',
// Toplam sayı ve öğeleri getir
const [total, items] = await Promise.all([
prisma.listItem.count({ where }),
prisma.listItem.findMany({
req.prisma.listItem.count({ where }),
req.prisma.listItem.findMany({
where,
skip,
take,
@@ -116,7 +114,7 @@ router.get('/:listId/:itemId',
const { listId, itemId } = req.params;
const item = await prisma.listItem.findFirst({
const item = await req.prisma.listItem.findFirst({
where: {
id: itemId,
listId
@@ -179,7 +177,7 @@ router.post('/:listId',
// Eğer productId verilmişse, ürünün var olduğunu kontrol et
let product = null;
if (productId) {
product = await prisma.product.findUnique({
product = await req.prisma.product.findUnique({
where: { id: productId }
});
@@ -189,7 +187,7 @@ router.post('/:listId',
}
// Aynı öğenin listede zaten var olup olmadığını kontrol et
const existingItem = await prisma.listItem.findFirst({
const existingItem = await req.prisma.listItem.findFirst({
where: {
listId,
OR: [
@@ -204,7 +202,7 @@ router.post('/:listId',
}
// Yeni öğe oluştur
const newItem = await prisma.listItem.create({
const newItem = await req.prisma.listItem.create({
data: {
customName: productId ? product.name : name,
quantity,
@@ -226,26 +224,26 @@ router.post('/:listId',
// Ürün kullanım sayısını artır (Product modelinde usageCount alanı yok, bu özellik kaldırıldı)
// Liste güncelleme tarihini güncelle
await prisma.shoppingList.update({
await req.prisma.shoppingList.update({
where: { id: listId },
data: { updatedAt: new Date() }
});
// Aktivite kaydı oluştur
await prisma.activity.create({
data: {
action: 'item_added',
details: {
itemId: newItem.id,
itemName: newItem.customName || newItem.product?.name || 'Öğe',
userName: `${req.user.firstName} ${req.user.lastName}`
},
userId,
listId
}
});
// Aktivite kaydı oluştur (geçici olarak devre dışı)
// await req.prisma.activity.create({
// data: {
// action: 'item_added',
// details: {
// itemId: newItem.id,
// itemName: newItem.customName || newItem.product?.name || 'Öğe',
// userName: `${req.user.firstName} ${req.user.lastName}`
// },
// userId,
// listId
// }
// });
// Liste üyelerine bildirim gönder (geçici olarak devre dışı - notifyListMembers fonksiyonu mevcut değil)
// Liste üyelerine bildirim gönder (geçici olarak devre dışı)
// await notificationService.notifyListMembers(
// listId,
// userId,
@@ -254,14 +252,14 @@ router.post('/:listId',
// { itemId: newItem.id, itemName: newItem.customName || newItem.product?.name }
// );
// Socket.IO ile gerçek zamanlı güncelleme
const io = req.app.get('io');
if (io) {
io.to(`list_${listId}`).emit('itemAdded', {
item: newItem,
addedBy: req.user
});
}
// Socket.IO ile gerçek zamanlı güncelleme (geçici olarak devre dışı)
// const io = req.app.get('io');
// if (io) {
// io.to(`list_${listId}`).emit('itemAdded', {
// item: newItem,
// addedBy: req.user
// });
// }
// Priority değerini string'e çevir
const newItemWithStringPriority = {
@@ -321,7 +319,7 @@ router.put('/:listId/:itemId',
// Öğenin var olduğunu kontrol et
console.log('🔍 Öğe aranıyor:', { itemId, listId });
const existingItem = await prisma.listItem.findFirst({
const existingItem = await req.prisma.listItem.findFirst({
where: {
id: itemId,
listId
@@ -364,7 +362,7 @@ router.put('/:listId/:itemId',
}
// Öğeyi güncelle
const updatedItem = await prisma.listItem.update({
const updatedItem = await req.prisma.listItem.update({
where: { id: itemId },
data: updateData,
include: {
@@ -378,7 +376,7 @@ router.put('/:listId/:itemId',
// Fiyat geçmişi ekle (eğer fiyat girilmişse ve ürün varsa)
if (price && existingItem.productId && isPurchased) {
await prisma.priceHistory.create({
await req.prisma.priceHistory.create({
data: {
price: price,
productId: existingItem.productId,
@@ -389,7 +387,7 @@ router.put('/:listId/:itemId',
}
// Liste güncelleme tarihini güncelle
await prisma.shoppingList.update({
await req.prisma.shoppingList.update({
where: { id: listId },
data: { updatedAt: new Date() }
});
@@ -402,7 +400,7 @@ router.put('/:listId/:itemId',
: `${req.user.firstName} ${req.user.lastName} "${updatedItem.name}" öğesinin satın alma durumunu iptal etti`;
}
await prisma.activity.create({
await req.prisma.activity.create({
data: {
action: isPurchased !== undefined ? (isPurchased ? 'ITEM_PURCHASED' : 'ITEM_UNPURCHASED') : 'ITEM_UPDATED',
details: {
@@ -467,7 +465,7 @@ router.delete('/:listId/:itemId',
const userId = req.user.id;
// Öğenin var olduğunu kontrol et
const existingItem = await prisma.listItem.findFirst({
const existingItem = await req.prisma.listItem.findFirst({
where: {
id: itemId,
listId
@@ -479,19 +477,19 @@ router.delete('/:listId/:itemId',
}
// Öğeyi sil
await prisma.listItem.delete({
await req.prisma.listItem.delete({
where: { id: itemId }
});
// Liste güncelleme tarihini güncelle
await prisma.shoppingList.update({
await req.prisma.shoppingList.update({
where: { id: listId },
data: { updatedAt: new Date() }
});
// Aktivite kaydı oluştur (Prisma şemasına uygun)
const itemName = existingItem.customName || existingItem.product?.name || 'Öğe';
await prisma.activity.create({
await req.prisma.activity.create({
data: {
action: 'ITEM_REMOVED',
details: {
@@ -551,7 +549,7 @@ router.patch('/:listId/bulk',
}
// Öğelerin var olduğunu kontrol et
const existingItems = await prisma.listItem.findMany({
const existingItems = await req.prisma.listItem.findMany({
where: {
id: { in: items },
listId
@@ -593,14 +591,14 @@ router.patch('/:listId/bulk',
// Toplu güncelleme veya silme
if (action === 'delete') {
await prisma.listItem.deleteMany({
await req.prisma.listItem.deleteMany({
where: {
id: { in: items },
listId
}
});
} else {
await prisma.listItem.updateMany({
await req.prisma.listItem.updateMany({
where: {
id: { in: items },
listId
@@ -610,13 +608,13 @@ router.patch('/:listId/bulk',
}
// Liste güncelleme tarihini güncelle
await prisma.shoppingList.update({
await req.prisma.shoppingList.update({
where: { id: listId },
data: { updatedAt: new Date() }
});
// Aktivite kaydı oluştur
await prisma.activity.create({
await req.prisma.activity.create({
data: {
type: activityType,
description: activityDescription,

View File

@@ -198,23 +198,25 @@ router.post('/', authenticateToken, [
}
});
// Aktivite kaydı oluştur
await req.prisma.activity.create({
data: {
listId: list.id,
userId: req.user.id,
action: 'list_created',
details: {
listName: list.name
}
}
});
// Aktivite kaydı oluştur (geçici olarak devre dışı)
// await req.prisma.activity.create({
// data: {
// listId: list.id,
// userId: req.user.id,
// action: 'list_created',
// details: {
// listName: list.name
// }
// }
// });
// Socket.IO ile gerçek zamanlı bildirim gönder
req.io.emit('list_created', {
list: { ...list, userRole: 'owner' },
user: req.user
});
// Socket.IO ile gerçek zamanlı bildirim gönder (geçici olarak devre dışı)
// if (req.io) {
// req.io.emit('list_created', {
// list: { ...list, userRole: 'owner' },
// user: req.user
// });
// }
res.status(201).json({
success: true,
@@ -483,6 +485,7 @@ router.post('/:listId/members', [
// Validation hatalarını kontrol et
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log("Liste paylasim hatasi detaylari:", errors.array());
return res.status(400).json({
success: false,
message: 'Girilen bilgilerde hatalar var',

View File

@@ -148,7 +148,7 @@ process.on('SIGINT', async () => {
});
// Sunucuyu başlat
const PORT = process.env.PORT || 5000;
const PORT = process.env.PORT || 7001;
server.listen(PORT, () => {
console.log(`🚀 Server ${PORT} portunda çalışıyor - port 7001`);

View File

@@ -9,6 +9,16 @@ class NotificationService {
initializeFirebase() {
try {
// Firebase credentials kontrolü
const hasCredentials = process.env.FIREBASE_PROJECT_ID &&
process.env.FIREBASE_PRIVATE_KEY &&
process.env.FIREBASE_CLIENT_EMAIL;
if (!hasCredentials) {
console.log('⚠️ Firebase credentials not configured. Push notifications disabled.');
return;
}
if (!admin.apps.length) {
const serviceAccount = {
type: process.env.FIREBASE_TYPE,
@@ -27,10 +37,11 @@ class NotificationService {
credential: admin.credential.cert(serviceAccount)
});
console.log('Firebase Admin SDK initialized successfully');
console.log('Firebase Admin SDK initialized successfully');
}
} catch (error) {
console.error('Firebase initialization error:', error);
console.error('Firebase initialization error:', error.message);
console.warn('Push notifications will be disabled.');
}
}

View File

@@ -16,13 +16,20 @@ function getDatabaseName(databaseUrl) {
async function setupUtf8mb4(prisma) {
const databaseUrl = process.env.DATABASE_URL || '';
// SQLite için bu fonksiyonu atla
if (databaseUrl.includes('sqlite') || databaseUrl.includes('.db')) {
console.log(' SQLite kullanılıyor. UTF8MB4 kurulumu atlandı.');
return;
}
const dbName = getDatabaseName(databaseUrl);
if (!dbName) {
console.warn('⚠️ DATABASE_URL bulunamadı veya veritabanı adı çözümlenemedi. UTF8MB4 kurulumu atlandı.');
return;
}
// Try altering database charset/collation
// Only run for MySQL/MariaDB
try {
await prisma.$executeRawUnsafe(`ALTER DATABASE \`${dbName}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`);
console.log('✅ Veritabanı varsayılan karakter seti/collation utf8mb4 olarak ayarlandı.');
@@ -30,7 +37,6 @@ async function setupUtf8mb4(prisma) {
console.warn('⚠️ Veritabanı charset ayarlanırken hata oluştu:', err?.message || err);
}
// Try converting categories table
try {
await prisma.$executeRawUnsafe('ALTER TABLE `categories` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci');
console.log('✅ `categories` tablosu utf8mb4 olarak dönüştürüldü.');

View File

@@ -2433,9 +2433,10 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -4618,9 +4619,10 @@
}
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -4707,9 +4709,10 @@
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -4738,9 +4741,10 @@
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -5145,19 +5149,21 @@
}
},
"node_modules/axios": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"follow-redirects": "^1.15.11",
"form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -5421,11 +5427,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.18",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.18.tgz",
"integrity": "sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==",
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
"integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
"baseline-browser-mapping": "dist/cli.cjs"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/batch": {
@@ -5473,22 +5483,23 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"node_modules/body-parser": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
"integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"bytes": "~3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.13.0",
"raw-body": "2.5.2",
"destroy": "~1.2.0",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
"qs": "~6.14.0",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8",
@@ -5503,6 +5514,26 @@
"ms": "2.0.0"
}
},
"node_modules/body-parser/node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -5519,6 +5550,15 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/body-parser/node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/bonjour-service": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
@@ -5559,9 +5599,9 @@
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
},
"node_modules/browserslist": {
"version": "4.26.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz",
"integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==",
"version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
"funding": [
{
"type": "opencollective",
@@ -5576,12 +5616,13 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
"electron-to-chromium": "^1.5.227",
"node-releases": "^2.0.21",
"update-browserslist-db": "^1.1.3"
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
"electron-to-chromium": "^1.5.263",
"node-releases": "^2.0.27",
"update-browserslist-db": "^1.2.0"
},
"bin": {
"browserslist": "cli.js"
@@ -5714,9 +5755,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001751",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz",
"integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==",
"version": "1.0.30001775",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz",
"integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==",
"funding": [
{
"type": "opencollective",
@@ -5730,7 +5771,8 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
],
"license": "CC-BY-4.0"
},
"node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",
@@ -6988,9 +7030,10 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.237",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz",
"integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg=="
"version": "1.5.302",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz",
"integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==",
"license": "ISC"
},
"node_modules/emittery": {
"version": "0.8.1",
@@ -7081,12 +7124,13 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.18.3",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
"integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
"tapable": "^2.3.0"
},
"engines": {
"node": ">=10.13.0"
@@ -7231,9 +7275,10 @@
}
},
"node_modules/es-module-lexer": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
"integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
"license": "MIT"
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
@@ -7780,9 +7825,10 @@
}
},
"node_modules/eslint/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -7969,38 +8015,39 @@
}
},
"node_modules/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
"integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"body-parser": "~1.20.3",
"content-disposition": "~0.5.4",
"content-type": "~1.0.4",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"cookie": "~0.7.1",
"cookie-signature": "~1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"finalhandler": "~1.3.1",
"fresh": "~0.5.2",
"http-errors": "~2.0.0",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"on-finished": "~2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.12",
"path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"qs": "~6.14.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.19.0",
"serve-static": "1.16.2",
"send": "~0.19.0",
"serve-static": "~1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"statuses": "~2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
@@ -8173,9 +8220,10 @@
}
},
"node_modules/filelist/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -8681,7 +8729,8 @@
"node_modules/glob-to-regexp": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"license": "BSD-2-Clause"
},
"node_modules/global-modules": {
"version": "2.0.0",
@@ -10792,9 +10841,10 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"license": "MIT",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -10907,19 +10957,20 @@
}
},
"node_modules/jsonpath": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz",
"integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz",
"integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==",
"license": "MIT",
"dependencies": {
"esprima": "1.2.2",
"static-eval": "2.0.2",
"underscore": "1.12.1"
"esprima": "1.2.5",
"static-eval": "2.1.1",
"underscore": "1.13.6"
}
},
"node_modules/jsonpath/node_modules/esprima": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
"integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz",
"integrity": "sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
@@ -11077,9 +11128,10 @@
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT"
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
@@ -11323,9 +11375,10 @@
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11437,9 +11490,10 @@
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz",
"integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==",
"license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
"node": ">= 6.13.0"
}
@@ -11450,9 +11504,10 @@
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="
},
"node_modules/node-releases": {
"version": "2.0.25",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz",
"integrity": "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA=="
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
"license": "MIT"
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -13348,11 +13403,12 @@
}
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"version": "6.14.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
@@ -13410,23 +13466,45 @@
}
},
"node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
"integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/raw-body/node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/raw-body/node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -13434,6 +13512,15 @@
"node": ">=0.10.0"
}
},
"node_modules/raw-body/node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/react": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
@@ -13618,9 +13705,10 @@
}
},
"node_modules/react-router": {
"version": "7.9.4",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.4.tgz",
"integrity": "sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==",
"version": "7.13.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz",
"integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0"
@@ -13639,11 +13727,12 @@
}
},
"node_modules/react-router-dom": {
"version": "7.9.4",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.4.tgz",
"integrity": "sha512-f30P6bIkmYvnHHa5Gcu65deIXoA2+r3Eb6PJIAddvsT9aGlchMatJ51GgpU470aSqRRbFX22T70yQNUGuW3DfA==",
"version": "7.13.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz",
"integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==",
"license": "MIT",
"dependencies": {
"react-router": "7.9.4"
"react-router": "7.13.1"
},
"engines": {
"node": ">=20.0.0"
@@ -13654,11 +13743,16 @@
}
},
"node_modules/react-router/node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/react-scripts": {
@@ -14087,9 +14181,10 @@
}
},
"node_modules/rollup": {
"version": "2.79.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
"version": "2.80.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
"integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
"license": "MIT",
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -14313,9 +14408,10 @@
}
},
"node_modules/schema-utils/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -14508,9 +14604,10 @@
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
"license": "MIT"
},
"node_modules/set-function-length": {
"version": "1.2.2",
@@ -14872,96 +14969,12 @@
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
},
"node_modules/static-eval": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
"integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz",
"integrity": "sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==",
"license": "MIT",
"dependencies": {
"escodegen": "^1.8.1"
}
},
"node_modules/static-eval/node_modules/escodegen": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=4.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/static-eval/node_modules/estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/static-eval/node_modules/levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
"dependencies": {
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/static-eval/node_modules/optionator": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
"integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
"dependencies": {
"deep-is": "~0.1.3",
"fast-levenshtein": "~2.0.6",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
"word-wrap": "~1.2.3"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/static-eval/node_modules/prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/static-eval/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/static-eval/node_modules/type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
"dependencies": {
"prelude-ls": "~1.1.2"
},
"engines": {
"node": ">= 0.8.0"
"escodegen": "^2.1.0"
}
},
"node_modules/statuses": {
@@ -15302,9 +15315,11 @@
}
},
"node_modules/sucrase/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -15321,11 +15336,12 @@
}
},
"node_modules/sucrase/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"version": "9.0.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
"brace-expansion": "^2.0.2"
},
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -15610,19 +15626,6 @@
}
}
},
"node_modules/tailwindcss/node_modules/yaml": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
}
},
"node_modules/tapable": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
@@ -15704,9 +15707,10 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.14",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz",
"integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==",
"version": "5.3.16",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
@@ -16069,9 +16073,10 @@
}
},
"node_modules/underscore": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
"integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
"license": "MIT"
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.1",
@@ -16151,9 +16156,9 @@
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
"funding": [
{
"type": "opencollective",
@@ -16168,6 +16173,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
@@ -16299,9 +16305,10 @@
}
},
"node_modules/watchpack": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
"integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==",
"license": "MIT",
"dependencies": {
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2"
@@ -16332,9 +16339,10 @@
}
},
"node_modules/webpack": {
"version": "5.102.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz",
"integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==",
"version": "5.105.3",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.3.tgz",
"integrity": "sha512-LLBBA4oLmT7sZdHiYE/PeVuifOxYyE2uL/V+9VQP7YSYdJU7bSf7H8bZRRxW8kEPMkmVjnrXmoR3oejIdX0xbg==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -16342,25 +16350,25 @@
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.15.0",
"acorn": "^8.16.0",
"acorn-import-phases": "^1.0.3",
"browserslist": "^4.26.3",
"browserslist": "^4.28.1",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.3",
"es-module-lexer": "^1.2.1",
"enhanced-resolve": "^5.19.0",
"es-module-lexer": "^2.0.0",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"loader-runner": "^4.3.1",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^4.3.3",
"tapable": "^2.3.0",
"terser-webpack-plugin": "^5.3.11",
"watchpack": "^2.4.4",
"webpack-sources": "^3.3.3"
"terser-webpack-plugin": "^5.3.16",
"watchpack": "^2.5.1",
"webpack-sources": "^3.3.4"
},
"bin": {
"webpack": "bin/webpack.js"
@@ -16514,9 +16522,10 @@
}
},
"node_modules/webpack-sources": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz",
"integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
}
@@ -16788,9 +16797,10 @@
}
},
"node_modules/workbox-build/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",

View File

@@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="hMarket - Akıllı Alışveriş Listesi ve Fiyat Takibi"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
@@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>hMarket - Akıllı Alışveriş Listesi</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "hMarket",
"name": "hMarket - Akıllı Alışveriş Listesi",
"icons": [
{
"src": "favicon.ico",

View File

@@ -88,7 +88,7 @@ const Navbar: React.FC = () => {
<Box sx={{ p: 2, display: 'flex', alignItems: 'center' }}>
<ShoppingCart sx={{ mr: 1, color: 'primary.main' }} />
<Typography variant="h6" color="primary.main" fontWeight="bold">
HMarket
hMarket
</Typography>
</Box>
<Divider />
@@ -139,7 +139,7 @@ const Navbar: React.FC = () => {
<Box sx={{ display: 'flex', alignItems: 'center', flexGrow: 1 }}>
<ShoppingCart sx={{ mr: 1 }} />
<Typography variant="h6" component="div" fontWeight="bold">
HMarket
hMarket
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 1 }}>
@@ -188,7 +188,7 @@ const Navbar: React.FC = () => {
sx={{ cursor: 'pointer' }}
onClick={() => navigate('/dashboard')}
>
HMarket
hMarket
</Typography>
</Box>

View File

@@ -106,7 +106,7 @@ const LoginPage: React.FC = () => {
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<ShoppingCart sx={{ fontSize: 40, color: 'primary.main', mr: 1 }} />
<Typography component="h1" variant="h4" color="primary.main" fontWeight="bold">
HMarket
hMarket
</Typography>
</Box>
@@ -244,13 +244,34 @@ const LoginPage: React.FC = () => {
</Link>
</Typography>
</Box>
<Box sx={{ textAlign: 'center', mt: 3, pt: 2, borderTop: '1px solid rgba(0,0,0,0.05)', display: 'flex', justifyContent: 'center', gap: 2 }}>
<Link
href="https://www.mustafaozkaya.tr/hmarket-kullanim-sartlari/"
target="_blank"
rel="noopener"
variant="caption"
sx={{ textDecoration: 'none', color: 'text.secondary' }}
>
Kullanım Şartları
</Link>
<Link
href="https://www.mustafaozkaya.tr/hmarket-gizlilik-politikasi/"
target="_blank"
rel="noopener"
variant="caption"
sx={{ textDecoration: 'none', color: 'text.secondary' }}
>
Gizlilik Politikası
</Link>
</Box>
</Box>
</Paper>
{/* Features */}
<Box sx={{ mt: 4, textAlign: 'center' }}>
<Typography variant="h6" gutterBottom>
Neden HMarket?
Neden hMarket?
</Typography>
<Box sx={{ display: 'flex', justifyContent: 'center', gap: 4, mt: 2 }}>
<Box>

View File

@@ -135,7 +135,7 @@ const RegisterPage: React.FC = () => {
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<ShoppingCart sx={{ fontSize: 40, color: 'primary.main', mr: 1 }} />
<Typography component="h1" variant="h4" color="primary.main" fontWeight="bold">
HMarket
hMarket
</Typography>
</Box>
@@ -352,14 +352,25 @@ const RegisterPage: React.FC = () => {
{/* Terms */}
<Box sx={{ mt: 2, textAlign: 'center' }}>
<Typography variant="body2" color="text.secondary">
By creating an account, you agree to our{' '}
<Link href="#" sx={{ textDecoration: 'none' }}>
Terms of Service
</Link>{' '}
and{' '}
<Link href="#" sx={{ textDecoration: 'none' }}>
Privacy Policy
Hesap oluşturarak,{' '}
<Link
href="https://www.mustafaozkaya.tr/hmarket-kullanim-sartlari/"
target="_blank"
rel="noopener"
sx={{ textDecoration: 'none' }}
>
Kullanım Şartları
</Link>
{' '}ve{' '}
<Link
href="https://www.mustafaozkaya.tr/hmarket-gizlilik-politikasi/"
target="_blank"
rel="noopener"
sx={{ textDecoration: 'none' }}
>
Gizlilik Politikası
</Link>
'nı kabul etmiş olursunuz.
</Typography>
</Box>
</Box>

View File

@@ -14,6 +14,7 @@ import {
Avatar,
LinearProgress,
IconButton,
Link,
} from '@mui/material';
import {
Add,
@@ -324,6 +325,33 @@ const DashboardPage: React.FC = () => {
</Card>
</Box>
</Box>
{/* Footer */}
<Box sx={{ mt: 8, pt: 4, borderTop: '1px solid rgba(0,0,0,0.05)', textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 1 }}>
<Box sx={{ display: 'flex', gap: 2 }}>
<Link
href="https://www.mustafaozkaya.tr/hmarket-kullanim-sartlari/"
target="_blank"
rel="noopener"
variant="body2"
sx={{ textDecoration: 'none', color: 'text.secondary' }}
>
Kullanım Şartları
</Link>
<Link
href="https://www.mustafaozkaya.tr/hmarket-gizlilik-politikasi/"
target="_blank"
rel="noopener"
variant="body2"
sx={{ textDecoration: 'none', color: 'text.secondary' }}
>
Gizlilik Politikası
</Link>
</Box>
<Typography variant="caption" display="block" sx={{ mt: 1, color: 'text.disabled' }}>
© 2026 hMarket - Mustafa ÖZKAYA
</Typography>
</Box>
</Container>
);
};

View File

@@ -1 +0,0 @@
{"email":"admin@hmarket.com","password":"admin123"}

View File

@@ -1,4 +0,0 @@
{
"login": "ahmet@test.com",
"password": "test123"
}