1
0

working nhost client

هذا الالتزام موجود في:
Your Name
2025-10-08 09:29:32 +00:00
الأصل b23bc554c5
التزام a837154231
10 ملفات معدلة مع 1189 إضافات و663 حذوفات

46
.dockerignore Normal file
عرض الملف

@@ -0,0 +1,46 @@
# التبعيات
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# ملفات البيئة
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# ملفات السجلات
logs
*.log
# ملفات التخزين المؤقت
.cache
.parcel-cache
.nuxt
.next
dist
build
# نظام التحكم بالنسخ
.git
.gitignore
README.md
# ملفات النظام
.DS_Store
Thumbs.db
# ملفات IDE
.vscode
.idea
*.swp
*.swo
# ملفات الاختبار
coverage
.nyc_output
node_modules

17
.ghaymah.json Normal file
عرض الملف

@@ -0,0 +1,17 @@
{
"id": "d7d9b033-eb33-4dcd-93f7-aa6f03ed706b",
"name": "dashboard",
"projectId": "2f99d8bc-53ba-44fc-ac40-2ff3dc380c87",
"ports": [
{
"expose": true,
"number": 5173
}
],
"publicAccess": {
"enabled": true,
"domain": "auto"
},
"resourceTier": "t5",
"dockerFileName": "Dockerfile"
}

15
Dockerfile Normal file
عرض الملف

@@ -0,0 +1,15 @@
FROM node:20-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
ENV PORT=8080
EXPOSE 8080
CMD [ "npm", "run", "dev"]

عرض الملف

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Onekeyword</title>
</head>
<body>
<div id="root"></div>

423
package-lock.json مولّد
عرض الملف

@@ -8,6 +8,10 @@
"name": "my-app",
"version": "0.0.0",
"dependencies": {
"@apollo/client": "^4.0.7",
"@nhost/react": "^3.11.2",
"graphql": "^16.11.0",
"graphql-ws": "^6.0.6",
"lucide-react": "^0.544.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
@@ -44,6 +48,47 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@apollo/client": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-4.0.7.tgz",
"integrity": "sha512-hZp/mKtAqM+g6buUnu6Wqtyc33QebvfdY0SE46xWea4lU1CxwI57VORy2N2vA9CoCRgYM4ELNXzr6nNErAdhfg==",
"workspaces": [
"dist",
"codegen",
"scripts/codemods/ac3-to-ac4"
],
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"@wry/caches": "^1.0.0",
"@wry/equality": "^0.5.6",
"@wry/trie": "^0.5.0",
"graphql-tag": "^2.12.6",
"optimism": "^0.18.0",
"tslib": "^2.3.0"
},
"peerDependencies": {
"graphql": "^16.0.0",
"graphql-ws": "^5.5.5 || ^6.0.3",
"react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc",
"react-dom": "^17.0.0 || ^18.0.0 || >=19.0.0-rc",
"rxjs": "^7.3.0",
"subscriptions-transport-ws": "^0.9.0 || ^0.11.0"
},
"peerDependenciesMeta": {
"graphql-ws": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
},
"subscriptions-transport-ws": {
"optional": true
}
}
},
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -922,6 +967,14 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@graphql-typed-document-node/core": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz",
"integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==",
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1042,6 +1095,126 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@nhost/graphql-js": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@nhost/graphql-js/-/graphql-js-0.3.0.tgz",
"integrity": "sha512-CVYq6wx0VbaYdpUBmfNO/6mZatHB5+YBCqFjWyxhpN1nzHCHEO6rgdL7j0qk31OFE6XAX0z7AQZSXg1Pn63GUw==",
"deprecated": "⚠ DEPRECATED: This package is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK is auto-generated from OpenAPI specs, provides better consistency, and works isomorphically across all JavaScript environments. This package will receive security patches and bug fixes until March 31st but no new features. Migrate to @nhost/nhost-js for future compatibility. Learn more: https://nhost.io/blog/introducing-new-javascript-sdk",
"dependencies": {
"@graphql-typed-document-node/core": "^3.2.0",
"base-64": "^1.0.0",
"isomorphic-unfetch": "^3.1.0",
"jwt-decode": "^4.0.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@nhost/hasura-auth-js": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/@nhost/hasura-auth-js/-/hasura-auth-js-2.12.0.tgz",
"integrity": "sha512-yOugrb9VCJr7Br/aSmv3iSN0rHvSBmynWppD1jiWuGqGVE0Fe/nwmYzJka1+5xDEdjtJvqaLnINEd84FI+pXSQ==",
"deprecated": "⚠ DEPRECATED: This package is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK is auto-generated from OpenAPI specs, provides better consistency, and works isomorphically across all JavaScript environments. This package will receive security patches and bug fixes until March 31st but no new features. Migrate to @nhost/nhost-js for future compatibility. Learn more: https://nhost.io/blog/introducing-new-javascript-sdk",
"dependencies": {
"@simplewebauthn/browser": "^9.0.1",
"fetch-ponyfill": "^7.1.0",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"xstate": "^4.38.3"
}
},
"node_modules/@nhost/hasura-storage-js": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@nhost/hasura-storage-js/-/hasura-storage-js-2.9.0.tgz",
"integrity": "sha512-FCeQpiqxH9JAAMwsS5kEv0OwyN8WhSD65XYM3P8CAeOqbun8yreQno7/wovFsGPVZqMgFDJ0VG9RhR1MFsPqdA==",
"deprecated": "⚠ DEPRECATED: This package is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK is auto-generated from OpenAPI specs, provides better consistency, and works isomorphically across all JavaScript environments. This package will receive security patches and bug fixes until March 31st but no new features. Migrate to @nhost/nhost-js for future compatibility. Learn more: https://nhost.io/blog/introducing-new-javascript-sdk",
"dependencies": {
"graphql": "16.8.1",
"xstate": "^4.38.3"
}
},
"node_modules/@nhost/hasura-storage-js/node_modules/graphql": {
"version": "16.8.1",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/@nhost/nhost-js": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@nhost/nhost-js/-/nhost-js-3.3.1.tgz",
"integrity": "sha512-AzOUalIQr0BS2psgEqxI+AMbNjSKB5RUOGzZX82U7YVcbJ9YvYf6a25EmtnJpItmN7H/h22Vxu8AbXqdtsGVkQ==",
"deprecated": "⚠ DEPRECATED: This version is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK is auto-generated from OpenAPI specs, provides better consistency, and works isomorphically across all JavaScript environments. This package will receive security patches and bug fixes until March 31st but no new features. Migrate to @nhost/nhost-js for future compatibility. Learn more: https://nhost.io/blog/introducing-new-javascript-sdk",
"dependencies": {
"@nhost/graphql-js": "0.3.0",
"@nhost/hasura-auth-js": "2.12.0",
"@nhost/hasura-storage-js": "2.9.0",
"isomorphic-unfetch": "^3.1.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@nhost/react": {
"version": "3.11.2",
"resolved": "https://registry.npmjs.org/@nhost/react/-/react-3.11.2.tgz",
"integrity": "sha512-OQLDFltmFo7l11VHoR6b17fNNG5qxGF3UU21md0dglo3exZ2XT3lFqI/6rITIAy5kiXK66ciBAN060Zmy0E4dA==",
"deprecated": "⚠ DEPRECATED: This package is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK is auto-generated from OpenAPI specs, provides better consistency, and works isomorphically across all JavaScript environments. This package will receive security patches and bug fixes until March 31st but no new features. Migrate to @nhost/nhost-js for future compatibility. Learn more: https://nhost.io/blog/introducing-new-javascript-sdk",
"dependencies": {
"@nhost/nhost-js": "3.3.1",
"@xstate/react": "^3.2.2",
"jwt-decode": "^4.0.0",
"react-dom": "^18.2.0",
"xstate": "^4.38.3"
},
"peerDependencies": {
"react": "^17.0.0 || ^18.1.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.1.0 || ^19.0.0"
}
},
"node_modules/@nhost/react/node_modules/@xstate/react": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@xstate/react/-/react-3.2.2.tgz",
"integrity": "sha512-feghXWLedyq8JeL13yda3XnHPZKwYDN5HPBLykpLeuNpr9178tQd2/3d0NrH6gSd0sG5mLuLeuD+ck830fgzLQ==",
"dependencies": {
"use-isomorphic-layout-effect": "^1.1.2",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@xstate/fsm": "^2.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"xstate": "^4.37.2"
},
"peerDependenciesMeta": {
"@xstate/fsm": {
"optional": true
},
"xstate": {
"optional": true
}
}
},
"node_modules/@nhost/react/node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.3.1"
}
},
"node_modules/@nhost/react/node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1432,6 +1605,20 @@
"win32"
]
},
"node_modules/@simplewebauthn/browser": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-9.0.1.tgz",
"integrity": "sha512-wD2WpbkaEP4170s13/HUxPcAV5y4ZXaKo1TfNklS5zDefPinIgXOpgz1kpEvobAsaLPa2KeH7AKKX/od1mrBJw==",
"dependencies": {
"@simplewebauthn/types": "^9.0.1"
}
},
"node_modules/@simplewebauthn/types": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@simplewebauthn/types/-/types-9.0.1.tgz",
"integrity": "sha512-tGSRP1QvsAvsJmnOlRQyw/mvK9gnPtjEc5fg2+m8n+QUa+D7rvrKkOYyfpy42GTs90X3RDOnqJgfHt+qO67/+w==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."
},
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
@@ -1884,6 +2071,50 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
"node_modules/@wry/caches": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
"integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@wry/context": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz",
"integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@wry/equality": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz",
"integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@wry/trie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz",
"integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -2033,6 +2264,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.6",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz",
@@ -2814,6 +3050,14 @@
"reusify": "^1.0.4"
}
},
"node_modules/fetch-ponyfill": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-7.1.0.tgz",
"integrity": "sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==",
"dependencies": {
"node-fetch": "~2.6.1"
}
},
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -3024,6 +3268,57 @@
"dev": true,
"license": "MIT"
},
"node_modules/graphql": {
"version": "16.11.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/graphql-tag": {
"version": "2.12.6",
"resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz",
"integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==",
"dependencies": {
"tslib": "^2.1.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/graphql-ws": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.6.tgz",
"integrity": "sha512-zgfER9s+ftkGKUZgc0xbx8T7/HMO4AV5/YuYiFc+AtgcO5T0v8AxYYNQ+ltzuzDZgNkYJaFspm5MMYLjQzrkmw==",
"engines": {
"node": ">=20"
},
"peerDependencies": {
"@fastify/websocket": "^10 || ^11",
"crossws": "~0.3",
"graphql": "^15.10.1 || ^16",
"uWebSockets.js": "^20",
"ws": "^8"
},
"peerDependenciesMeta": {
"@fastify/websocket": {
"optional": true
},
"crossws": {
"optional": true
},
"uWebSockets.js": {
"optional": true
},
"ws": {
"optional": true
}
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3182,6 +3477,15 @@
"dev": true,
"license": "ISC"
},
"node_modules/isomorphic-unfetch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz",
"integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==",
"dependencies": {
"node-fetch": "^2.6.1",
"unfetch": "^4.2.0"
}
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@@ -3208,11 +3512,18 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -3275,6 +3586,14 @@
"node": ">=6"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"engines": {
"node": ">=18"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -3339,6 +3658,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -3353,7 +3683,6 @@
"version": "0.544.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz",
"integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@@ -3450,6 +3779,25 @@
"dev": true,
"license": "MIT"
},
"node_modules/node-fetch": {
"version": "2.6.13",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz",
"integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-releases": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz",
@@ -3497,6 +3845,17 @@
"node": ">= 6"
}
},
"node_modules/optimism": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz",
"integrity": "sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==",
"dependencies": {
"@wry/caches": "^1.0.0",
"@wry/context": "^0.7.0",
"@wry/trie": "^0.5.0",
"tslib": "^2.3.0"
}
},
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -4146,6 +4505,15 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
@@ -4508,6 +4876,11 @@
"node": ">=8.0"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
@@ -4528,6 +4901,11 @@
"dev": true,
"license": "Apache-2.0"
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4579,6 +4957,11 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/unfetch": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz",
"integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA=="
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
@@ -4620,6 +5003,19 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-isomorphic-layout-effect": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
"integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
@@ -4764,6 +5160,20 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4885,6 +5295,15 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/xstate": {
"version": "4.38.3",
"resolved": "https://registry.npmjs.org/xstate/-/xstate-4.38.3.tgz",
"integrity": "sha512-SH7nAaaPQx57dx6qvfcIgqKRXIh4L0A1iYEqim4s1u7c9VoCgzZc+63FY90AKU4ZzOC2cfJzTnpO4zK7fCUzzw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/xstate"
}
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

عرض الملف

@@ -10,6 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
"@apollo/client": "^4.0.7",
"@nhost/react": "^3.11.2",
"graphql": "^16.11.0",
"graphql-ws": "^6.0.6",
"lucide-react": "^0.544.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",

عرض الملف

@@ -23,6 +23,14 @@ function App() {
<Route path="/portfolio" element={<ProtectedRoute><Portfolio /></ProtectedRoute>} />
<Route path="/strategy" element={<ProtectedRoute><Strategy /></ProtectedRoute>} />
<Route path="/settings" element={<ProtectedRoute><Settings /></ProtectedRoute>} />
{/* <Route path="/" element={<Dashboard />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/strategy" element={<Strategy />} />
<Route path="/settings" element={<Settings />} /> */}
</Routes>
<Footer />
</div>

عرض الملف

@@ -1,11 +1,106 @@
// بسم الله الرحمن الرحيم
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import './App.css'
import App from './App.tsx'
import { NhostProvider, NhostClient } from '@nhost/react'
import { ApolloClient, InMemoryCache, createHttpLink, split } from "@apollo/client"
import { ApolloProvider } from "@apollo/client/react";
import { setContext } from '@apollo/client/link/context'
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
import { createClient } from 'graphql-ws'
import { getMainDefinition } from '@apollo/client/utilities'
// Initialize Nhost client
const nhost = new NhostClient({
authUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
storageUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
functionsUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
graphqlUrl: 'https://onekeyword-auth-76aaf2ee939c.hosted.ghaymah.systems',
})
// Auth link for Apollo Client
const authLink = setContext(async (_, { headers }) => {
// Get the authentication state from Nhost
const isAuthenticated = await nhost.auth.isAuthenticatedAsync()
if (isAuthenticated) {
const token = nhost.auth.getAccessToken()
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
}
}
} else {
// Use public role when not authenticated
return {
headers: {
...headers,
'x-hasura-role': 'public',
}
}
}
})
// HTTP link for queries and mutations
const httpLink = createHttpLink({
uri: 'https://hasura-bc7db43160df.hosted.ghaymah.systems/v1/graphql',
})
// WebSocket link for subscriptions
const wsLink = new GraphQLWsLink(
createClient({
url: 'wss://hasura-bc7db43160df.hosted.ghaymah.systems/v1/graphql',
connectionParams: async () => {
const isAuthenticated = await nhost.auth.isAuthenticatedAsync()
if (isAuthenticated) {
const token = nhost.auth.getAccessToken()
return {
headers: {
authorization: token ? `Bearer ${token}` : '',
}
}
} else {
return {
headers: {
'x-hasura-role': 'public',
}
}
}
},
})
)
// Split links based on operation type
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
authLink.concat(httpLink)
)
// Apollo Client setup
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
})
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
<NhostProvider nhost={nhost}>
<StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</StrictMode>
</NhostProvider>,
)

تم حذف اختلاف الملف لأن الملف كبير جداً تحميل الاختلاف

213
src/pages/useAuth.tsx Normal file
عرض الملف

@@ -0,0 +1,213 @@
import { useState } from 'react';
import { useNhostClient } from '@nhost/react';
export const useAuth = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
const nhost = useNhostClient();
const handleLogin = async (email: string, password: string) => {
setIsLoading(true);
setError('');
try {
const { session, error } = await nhost.auth.signIn({
email,
password,
});
if (error) {
throw new Error(error.message || 'Failed to login. Please check your credentials.');
}
if (session) {
const accessToken = session.accessToken;
const refreshToken = session.refreshToken;
const userId = session.user?.id;
// Store user data in localStorage
const userData = {
email,
accessToken,
userId,
isLoggedIn: true,
lastLogin: new Date().toISOString()
};
localStorage.setItem('sp_user', JSON.stringify(userData));
localStorage.setItem('user_id', userId);
window.dispatchEvent(new Event('userChanged'));
// Store tokens in HttpOnly cookies (if still needed)
try {
await fetch('/api/auth/store-tokens', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
access_token: accessToken,
refresh_token: refreshToken,
expires_in: 3600
})
});
} catch (error) {
console.error('Error storing token in HttpOnly cookie:', error);
}
return { success: true, data: { session } };
} else {
throw new Error('Login failed: No session returned');
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleSignUp = async (email: string, password: string) => {
setIsLoading(true);
setError('');
try {
const { session, error } = await nhost.auth.signUp({
email,
password,
});
if (error) {
throw new Error(error.message || 'Signup failed. Please check your info.');
}
if (session) {
const accessToken = session.accessToken;
const refreshToken = session.refreshToken;
const userId = session.user?.id;
const userData = {
email,
accessToken,
userId,
isLoggedIn: true,
lastLogin: new Date().toISOString()
};
localStorage.setItem('sp_user', JSON.stringify(userData));
localStorage.setItem('user_id', userId);
window.dispatchEvent(new Event('userChanged'));
// Store tokens in HttpOnly cookies (if still needed)
try {
await fetch('/api/auth/store-tokens', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
access_token: accessToken,
refresh_token: refreshToken,
expires_in: 3600
})
});
} catch (error) {
console.error('Error storing token in HttpOnly cookie:', error);
}
return { success: true, data: { session } };
} else {
// Note: NHost may not return a session immediately if email verification is required
return {
success: true,
data: {
message: 'Signup successful! Please check your email for verification.'
}
};
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleForgotPassword = async (email: string) => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.resetPassword({ email });
if (error) {
throw new Error(error.message || 'Failed to send reset email.');
}
return {
success: true,
message: 'If the email exists, a reset link has been sent.'
};
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
// Additional NHost auth methods you might find useful
const handleSignOut = async () => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.signOut();
if (error) {
throw new Error(error.message || 'Failed to sign out.');
}
// Clear local storage
localStorage.removeItem('sp_user');
localStorage.removeItem('user_id');
window.dispatchEvent(new Event('userChanged'));
return { success: true };
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
const handleChangePassword = async (newPassword: string) => {
setIsLoading(true);
setError('');
try {
const { error } = await nhost.auth.changePassword({ newPassword });
if (error) {
throw new Error(error.message || 'Failed to change password.');
}
return { success: true, message: 'Password changed successfully.' };
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
return { success: false, error: errorMessage };
} finally {
setIsLoading(false);
}
};
return {
isLoading,
error,
handleLogin,
handleSignUp,
handleForgotPassword,
handleSignOut,
handleChangePassword,
setError
};
};