-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Monorepo updates and enhancements - Updated `404` component with default values - Updated package dependencies - feat: Added page links' variables and updated details pages - Refactored document page structure - fix: Resolved build error due to duplicate import - Switched package manager from `npm` to `pnpm` - Updated Dockerfile configuration for Tenscan frontend - fix: Display full address on desktop view - Added monorepo structure documentation for TEN frontend projects
- Loading branch information
Showing
124 changed files
with
32,540 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "go-ten", | ||
"version": "1.0.0", | ||
"description": "go-ten", | ||
"main": "index.js", | ||
"directories": { | ||
"lib": "lib" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ten-protocol/go-ten.git" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"bugs": { | ||
"url": "https://github.com/ten-protocol/go-ten/issues" | ||
}, | ||
"homepage": "https://github.com/ten-protocol/go-ten#readme", | ||
"dependencies": { | ||
"turbo": "^1.13.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Monorepo Structure for TEN Frontend Projects | ||
|
||
This repository uses a monorepo setup to manage multiple frontend projects and shared resources such as components, utilities, and hooks. The structure enhances code reuse, maintainability, and collaboration across projects like **Tenscan**, **Gateway**, **Bridge**, and more. | ||
|
||
## Folder Structure | ||
|
||
```bash | ||
📁 packages | ||
├── 📁 apis - Server-side logic, API routes, and backend services | ||
│ ├── 📁 .config - Configuration files for the APIs | ||
│ ├── 📁 src - Source files for API logic | ||
│ └── 📁 storage - Storage-related logic or utilities | ||
├── 📁 eslint-config - Centralized ESLint configuration for all frontend projects | ||
├── 📁 shared - Reusable components, hooks, and utilities shared across frontend apps | ||
│ └── 📁 src - Main directory containing shared code | ||
├── 📁 typescript-config - Centralized TypeScript configurations | ||
│ ├── 📄 base.json - Base TypeScript configuration for general projects | ||
│ ├── 📄 nextjs.json - Configuration specific to Next.js projects | ||
│ └── 📄 react-library.json - Configuration for React libraries | ||
└── 📁 ui - | ||
├── 📁 api - API logic consumed by the frontend | ||
├── 📁 components - Reusable React components used in the UI | ||
├── 📁 hooks - Custom hooks used across the frontend | ||
├── 📁 lib - Utility functions used across the frontend | ||
├── 📁 public - Static files such as images and assets | ||
├── 📁 services - External service interactions like APIs | ||
├── 📁 routes - Routing configuration and route-related logic | ||
└── 📁 stores - Global state mgt | ||
``` | ||
|
||
## Getting Started | ||
|
||
1. **Clone the Repository:** | ||
|
||
```bash | ||
git clone https://github.com/ten-protocol/go-ten.git | ||
``` | ||
|
||
2. **Install Dependencies:** | ||
|
||
```bash | ||
pnpm install | ||
``` | ||
|
||
3. **Navigate to the Project:** | ||
|
||
```bash | ||
Tenscan: cd tools/tenscan/frontend | ||
Gateway: cd tools/walletextension/frontend | ||
Bridge: cd tools/bridge-frontend | ||
``` | ||
|
||
4. **Run the Project:** | ||
|
||
```bash | ||
pnpm dev | ||
``` | ||
|
||
|
||
## Built With | ||
|
||
- [Next.js](https://nextjs.org/) | ||
- [Tailwind CSS](https://tailwindcss.com/) | ||
- [TypeScript](https://www.typescriptlang.org/) | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! Follow our [contribution guidelines](/docs/_docs/community/contributions.md). | ||
|
||
## License | ||
|
||
This project is licensed under the [GNU Affero General Public License v3.0](/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// @ts-expect-error | ||
import { defineConfig } from "@openapi-codegen/cli"; | ||
import { | ||
generateReactQueryComponents, | ||
generateSchemaTypes, | ||
} from "@openapi-codegen/typescript"; | ||
|
||
export default defineConfig({ | ||
digest: { | ||
from: { | ||
relativePath: "./storage/digest-openapi.json", | ||
source: "file", | ||
}, | ||
outputDir: "./src/api/codegen", | ||
// @ts-expect-error | ||
to: async (context) => { | ||
const filenamePrefix = "digest"; | ||
|
||
const { schemasFiles } = await generateSchemaTypes(context, { | ||
filenamePrefix, | ||
}); | ||
return await generateReactQueryComponents(context, { | ||
filenamePrefix, | ||
schemasFiles, | ||
}); | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"outputFormat": "json", | ||
"operationId": "auto" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@repo/apis", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"sync": "npm run api:generate", | ||
"api:generate": "pnpm run convert:collection && npm run generate:fetcher", | ||
"generate:fetcher": "npx openapi-codegen -c .config/openapi-codegen.config.ts digest", | ||
"convert:collection": "pnpm exec p2o ./storage/digest-collection.json -f ./storage/digest-openapi.json -o .config/p2o.config.json" | ||
}, | ||
"dependencies": { | ||
"@repo/shared": "workspace:*", | ||
"@repo/typescript-config": "workspace:*", | ||
"destr": "^2.0.2", | ||
"effect": "^2.4.1", | ||
"ofetch": "1.3.3", | ||
"ramda": "^0.29.1", | ||
"rxjs": "^7.8.1" | ||
}, | ||
"devDependencies": { | ||
"@openapi-codegen/cli": "^2.0.0", | ||
"@openapi-codegen/typescript": "^8.0.0", | ||
"@types/ramda": "^0.29.10", | ||
"postman-to-openapi": "^3.0.1", | ||
"typescript": "5.3.3", | ||
"vite": "^5.0.11" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import { safeStr } from "@repo/shared/src/data.helpers"; | ||
import { Match } from "effect"; | ||
import { FetchError } from "ofetch"; | ||
import { has, identity, is } from "ramda"; | ||
import { | ||
ApiError, | ||
ApiErrors, | ||
Okay, | ||
ResponseType, | ||
SafeRes, | ||
UnknownError, | ||
} from "./response-types"; | ||
|
||
export const resolveUrl = ( | ||
url: string, | ||
queryParams: Record<string, string> = {}, | ||
pathParams: Record<string, string> = {}, | ||
) => { | ||
let query = new URLSearchParams(queryParams).toString(); | ||
if (query) query = `?${query}`; | ||
|
||
return url.replace(/\{\w*\}/g, (key) => pathParams[key.slice(1, -1)]) + query; | ||
}; | ||
|
||
export async function safeFetchResponse<T>( | ||
promise: Promise<T>, | ||
): Promise<SafeRes<T>> { | ||
try { | ||
const value = await promise; | ||
return resolveFetchResponse<T>(value); | ||
} catch (err: unknown) { | ||
return resolveFetchError(err); | ||
} | ||
} | ||
|
||
export const resolveFetchResponse = <T>(response: T): SafeRes<T> => { | ||
const hasError = has("error", response) && response.error === true; | ||
const hasMessage = has("msg", response); | ||
|
||
const messageIsStr = hasMessage && typeof response?.msg === "string"; | ||
|
||
if (UnacceptedError.validate(response)) { | ||
return UnacceptedError.respond(response); | ||
} | ||
|
||
if (Array.isArray(response)) return Okay(response); | ||
|
||
if (hasError && hasMessage && is(Object, response?.msg)) | ||
// @ts-expect-error Still trying to response structure | ||
return ValidationError(response?.msg); | ||
|
||
if (hasError && hasMessage && messageIsStr) | ||
return ApiError({ | ||
message: response.msg as string, | ||
|
||
error: response.error, | ||
}); | ||
|
||
if (response === undefined || response === null) { | ||
return UnknownError({ | ||
message: "Something went wrong", | ||
value: response, | ||
}); | ||
} | ||
|
||
return Okay(response); | ||
}; | ||
|
||
// biome-ignore lint/suspicious/noExplicitAny: Error type must be any | ||
export function resolveFetchError(error: any): ApiErrors { | ||
if ( | ||
["Network Error", "NetworkError"].some((str) => | ||
safeStr(error?.message).includes(str), | ||
) | ||
) { | ||
return ApiError({ | ||
message: "Seems like you're offline. Please check your network", | ||
}); | ||
} | ||
|
||
return handleErrorByType(error); | ||
} | ||
|
||
const handleErrorByType = ResponseType.pipe( | ||
Match.tag("ApiError", identity), | ||
Match.tag("ValidationError", identity), | ||
Match.tag("UnknownError", identity), | ||
Match.orElse((err) => handleRandomError(err)), | ||
); | ||
|
||
function handleRandomError(error: unknown) { | ||
const err = error as FetchError; | ||
if (err instanceof FetchError) { | ||
const { status = 400 } = guessRequestError(err); | ||
const reason_for_failure = err?.data?.message || err.message; | ||
|
||
if (status === 404) | ||
return ApiError({ message: "404: Resource not found", error: err }); | ||
|
||
if (401 === status) { | ||
return ApiError({ | ||
message: "Unable to process request. You're unauthorized", | ||
error: err, | ||
}); | ||
} | ||
|
||
if (403 === status) { | ||
return ApiError({ | ||
message: "You do not have permission to perform this operation", | ||
error: err, | ||
}); | ||
} | ||
|
||
if (status >= 400 && status < 500) | ||
return ApiError({ message: reason_for_failure, error: err }); | ||
|
||
if (status >= 500) | ||
return ApiError({ message: reason_for_failure, error: err }); | ||
} | ||
|
||
const err_msg = has("message", error) ? safeStr(error.message) : ""; | ||
|
||
if (err_msg.includes("<no response>")) { | ||
return ApiError({ | ||
message: "Something new wrong. Server didn't respond", | ||
}); | ||
} | ||
|
||
return ApiError({ message: err_msg }); | ||
|
||
function guessRequestError(err: FetchError) { | ||
return err instanceof FetchError | ||
? err | ||
: { status: 0, statusText: "UNKNOWN" }; | ||
} | ||
} | ||
|
||
export type ResponseResolver = { | ||
validate: (data: unknown) => boolean; | ||
respond: <T>(data: T) => ApiErrors; | ||
interceptResponse: <T>(data: T) => T; | ||
}; | ||
|
||
export const UnacceptedError: ResponseResolver = { | ||
validate(response: unknown) { | ||
return ( | ||
has("accepted", response) && | ||
has("message", response) && | ||
response.accepted === false | ||
); | ||
}, | ||
|
||
respond(response: unknown) { | ||
return ApiError({ | ||
// @ts-expect-error | ||
message: response?.message ?? "Unknown Error...", | ||
error: response, | ||
}); | ||
}, | ||
|
||
interceptResponse(response) { | ||
if (!this.validate(response)) return response; | ||
|
||
throw this.respond(response); | ||
}, | ||
}; |
Oops, something went wrong.