@@ -19,15 +19,15 @@ export default function Home() {
Looking for a starting point or more instructions? Head over to{" "}
Templates
{" "}
or the{" "}
Learning
{" "}
@@ -38,23 +38,23 @@ export default function Home() {
Deploy Now
Documentation
diff --git a/apps/dashboard/components.json b/apps/dashboard/components.json
index e8fe6ac..64644b3 100644
--- a/apps/dashboard/components.json
+++ b/apps/dashboard/components.json
@@ -1,20 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
- "style": "new-york",
- "rsc": true,
- "tsx": true,
- "tailwind": {
- "config": "",
- "css": "../../packages/ui/src/styles/globals.css",
- "baseColor": "neutral",
- "cssVariables": true
- },
- "iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"hooks": "@/hooks",
"lib": "@/lib",
- "utils": "@basango/ui/lib/utils",
- "ui": "@basango/ui/components"
- }
+ "ui": "@basango/ui/components",
+ "utils": "@basango/ui/lib/utils"
+ },
+ "iconLibrary": "lucide",
+ "rsc": true,
+ "style": "new-york",
+ "tailwind": {
+ "baseColor": "neutral",
+ "config": "",
+ "css": "../../packages/ui/src/styles/globals.css",
+ "cssVariables": true
+ },
+ "tsx": true
}
diff --git a/apps/dashboard/next.config.ts b/apps/dashboard/next.config.ts
index 938dbfc..212c17e 100644
--- a/apps/dashboard/next.config.ts
+++ b/apps/dashboard/next.config.ts
@@ -1,6 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["@basango/ui"],
-}
+};
-export default nextConfig
+export default nextConfig;
diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json
index 485c5e8..30d4bf4 100644
--- a/apps/dashboard/package.json
+++ b/apps/dashboard/package.json
@@ -1,23 +1,23 @@
{
- "name": "@basango/dashboard",
- "private": true,
- "scripts": {
- "dev": "next dev",
- "build": "next build",
- "start": "next start",
- "lint": "eslint"
- },
"dependencies": {
+ "next": "catalog:",
"react": "catalog:",
- "react-dom": "catalog:",
- "next": "catalog:"
+ "react-dom": "catalog:"
},
"devDependencies": {
- "typescript": "catalog:",
+ "@tailwindcss/postcss": "^4",
"@types/bun": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
- "@tailwindcss/postcss": "^4",
- "tailwindcss": "^4"
+ "tailwindcss": "^4",
+ "typescript": "catalog:"
+ },
+ "name": "@basango/dashboard",
+ "private": true,
+ "scripts": {
+ "build": "next build",
+ "dev": "next dev",
+ "lint": "eslint",
+ "start": "next start"
}
}
diff --git a/apps/dashboard/tsconfig.json b/apps/dashboard/tsconfig.json
index cd8a37e..31bf14d 100644
--- a/apps/dashboard/tsconfig.json
+++ b/apps/dashboard/tsconfig.json
@@ -1,5 +1,4 @@
{
- "extends": "@basango/typescript-config/nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
@@ -12,12 +11,7 @@
}
]
},
- "include": [
- "next-env.d.ts",
- "next.config.ts",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": ["node_modules"]
+ "exclude": ["node_modules"],
+ "extends": "@basango/tsconfig/nextjs.json",
+ "include": ["next-env.d.ts", "next.config.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"]
}
diff --git a/apps/mobile-legacy/app.json b/apps/mobile-legacy/app.json
index fc39fc9..82adf55 100644
--- a/apps/mobile-legacy/app.json
+++ b/apps/mobile-legacy/app.json
@@ -1,40 +1,43 @@
{
"expo": {
- "name": "basango",
- "slug": "basango",
- "version": "1.0.0",
- "orientation": "portrait",
- "icon": "./src/assets/images/logo.png",
- "scheme": "basango",
- "userInterfaceStyle": "automatic",
- "newArchEnabled": true,
- "githubUrl": "https://github.com/bernard-ng/basango",
- "ios": {
- "supportsTablet": true,
- "bundleIdentifier": "dev.ngandu.basango"
- },
"android": {
"adaptiveIcon": {
- "foregroundImage": "./src/assets/images/logo.png",
"backgroundColor": "#ffffff",
+ "foregroundImage": "./src/assets/images/logo.png",
"package": "dev.ngandu.basango"
},
"package": "dev.ngandu.basango"
},
- "web": {
- "bundler": "metro",
- "output": "static",
- "favicon": "./src/assets/images/logo.png"
+ "experiments": {
+ "typedRoutes": true
},
+ "extra": {
+ "eas": {
+ "projectId": "57281e7a-46e3-4aac-8715-5165fa0bf560"
+ },
+ "router": {
+ "origin": false
+ }
+ },
+ "githubUrl": "https://github.com/bernard-ng/basango",
+ "icon": "./src/assets/images/logo.png",
+ "ios": {
+ "bundleIdentifier": "dev.ngandu.basango",
+ "supportsTablet": true
+ },
+ "name": "basango",
+ "newArchEnabled": true,
+ "orientation": "portrait",
+ "owner": "bernard-ng",
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
+ "backgroundColor": "#ffffff",
"image": "./src/assets/images/logo.png",
"imageWidth": 200,
- "resizeMode": "contain",
- "backgroundColor": "#ffffff"
+ "resizeMode": "contain"
}
],
"expo-build-properties",
@@ -42,23 +45,20 @@
[
"@sentry/react-native/expo",
{
- "url": "https://glitchtip.devscast.tech/",
+ "organization": "devscast-software",
"project": "basango",
- "organization": "devscast-software"
+ "url": "https://glitchtip.devscast.tech/"
}
]
],
- "experiments": {
- "typedRoutes": true
- },
- "extra": {
- "router": {
- "origin": false
- },
- "eas": {
- "projectId": "57281e7a-46e3-4aac-8715-5165fa0bf560"
- }
- },
- "owner": "bernard-ng"
+ "scheme": "basango",
+ "slug": "basango",
+ "userInterfaceStyle": "automatic",
+ "version": "1.0.0",
+ "web": {
+ "bundler": "metro",
+ "favicon": "./src/assets/images/logo.png",
+ "output": "static"
+ }
}
}
diff --git a/apps/mobile-legacy/babel.config.js b/apps/mobile-legacy/babel.config.js
index b21c172..9ee4747 100644
--- a/apps/mobile-legacy/babel.config.js
+++ b/apps/mobile-legacy/babel.config.js
@@ -1,7 +1,7 @@
-module.exports = function (api) {
- api.cache(true);
- return {
- presets: [["babel-preset-expo", { jsxRuntime: "automatic" }]],
- plugins: ["react-native-reanimated/plugin"],
- };
+module.exports = (api) => {
+ api.cache(true);
+ return {
+ plugins: ["react-native-reanimated/plugin"],
+ presets: [["babel-preset-expo", { jsxRuntime: "automatic" }]],
+ };
};
diff --git a/apps/mobile-legacy/commitlint.config.js b/apps/mobile-legacy/commitlint.config.js
index ef93365..3185047 100644
--- a/apps/mobile-legacy/commitlint.config.js
+++ b/apps/mobile-legacy/commitlint.config.js
@@ -1,23 +1,23 @@
module.exports = {
- extends: ["@commitlint/config-conventional"],
- rules: {
- "type-enum": [
- 2,
- "always",
- [
- "feat", // New feature
- "fix", // Bug fix
- "docs", // Documentation only changes
- "style", // Changes that do not affect the meaning of the code (white-space, formatting, etc)
- "refactor", // Code changes that neither fixes a bug nor adds a feature
- "perf", // Performance improvements
- "test", // Adding missing tests or correcting existing tests
- "build", // Changes that affect the build system or external dependencies
- "ci", // Changes to CI configuration files and scripts
- "chore", // Other changes that don't modify src or test files
- "revert", // Reverts a previous commit
- ],
- ],
- "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]],
- },
+ extends: ["@commitlint/config-conventional"],
+ rules: {
+ "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]],
+ "type-enum": [
+ 2,
+ "always",
+ [
+ "feat", // New feature
+ "fix", // Bug fix
+ "docs", // Documentation only changes
+ "style", // Changes that do not affect the meaning of the code (white-space, formatting, etc)
+ "refactor", // Code changes that neither fixes a bug nor adds a feature
+ "perf", // Performance improvements
+ "test", // Adding missing tests or correcting existing tests
+ "build", // Changes that affect the build system or external dependencies
+ "ci", // Changes to CI configuration files and scripts
+ "chore", // Other changes that don't modify src or test files
+ "revert", // Reverts a previous commit
+ ],
+ ],
+ },
};
diff --git a/apps/mobile-legacy/eas.json b/apps/mobile-legacy/eas.json
index a1a498e..b7967bb 100644
--- a/apps/mobile-legacy/eas.json
+++ b/apps/mobile-legacy/eas.json
@@ -1,8 +1,4 @@
{
- "cli": {
- "version": ">= 16.3.1",
- "appVersionSource": "remote"
- },
"build": {
"development": {
"developmentClient": true,
@@ -15,6 +11,10 @@
"autoIncrement": true
}
},
+ "cli": {
+ "appVersionSource": "remote",
+ "version": ">= 16.3.1"
+ },
"submit": {
"production": {}
}
diff --git a/apps/mobile-legacy/eslint.config.js b/apps/mobile-legacy/eslint.config.js
deleted file mode 100644
index 6d5fe64..0000000
--- a/apps/mobile-legacy/eslint.config.js
+++ /dev/null
@@ -1,56 +0,0 @@
-const { defineConfig } = require("eslint/config");
-const expoConfig = require("eslint-config-expo/flat");
-const prettierPlugin = require("eslint-plugin-prettier");
-const unusedImportsPlugin = require("eslint-plugin-unused-imports");
-
-module.exports = defineConfig([
- expoConfig,
- {
- plugins: {
- prettier: prettierPlugin,
- "unused-imports": unusedImportsPlugin,
- },
- rules: {
- "import/default": "off",
- "react/prop-types": "off",
- "react/react-in-jsx-scope": "off",
- "import/named": "off",
- "import/namespace": "error",
- "import/export": "error",
- "no-unused-vars": "off",
- "unused-imports/no-unused-imports": "error",
- "unused-imports/no-unused-vars": [
- "warn",
- {
- vars: "all",
- varsIgnorePattern: "^_",
- args: "after-used",
- argsIgnorePattern: "^_",
- },
- ],
- "import/order": [
- "error",
- {
- groups: ["builtin", "external", "internal"],
- pathGroups: [
- {
- pattern: "react",
- group: "external",
- position: "before",
- },
- ],
- pathGroupsExcludedImportTypes: ["react"],
- "newlines-between": "always",
- alphabetize: {
- order: "asc",
- caseInsensitive: true,
- },
- },
- ],
- "prettier/prettier": "error",
- },
- },
- {
- ignores: ["dist/*"],
- },
-]);
diff --git a/apps/mobile-legacy/ios/Podfile.properties.json b/apps/mobile-legacy/ios/Podfile.properties.json
index 5f99b5d..4f49b45 100644
--- a/apps/mobile-legacy/ios/Podfile.properties.json
+++ b/apps/mobile-legacy/ios/Podfile.properties.json
@@ -1,8 +1,8 @@
{
- "expo.jsEngine": "hermes",
- "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
- "newArchEnabled": "true",
- "apple.extraPods": "[]",
"apple.ccacheEnabled": "false",
- "apple.privacyManifestAggregationEnabled": "true"
+ "apple.extraPods": "[]",
+ "apple.privacyManifestAggregationEnabled": "true",
+ "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true",
+ "expo.jsEngine": "hermes",
+ "newArchEnabled": "true"
}
diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json
index 90d8d4c..4da364a 100644
--- a/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/apps/mobile-legacy/ios/basango/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -8,7 +8,7 @@
}
],
"info": {
- "version": 1,
- "author": "expo"
+ "author": "expo",
+ "version": 1
}
-}
\ No newline at end of file
+}
diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json
index ed285c2..0b946fb 100644
--- a/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json
+++ b/apps/mobile-legacy/ios/basango/Images.xcassets/Contents.json
@@ -1,6 +1,6 @@
{
- "info" : {
- "version" : 1,
- "author" : "expo"
+ "info": {
+ "author": "expo",
+ "version": 1
}
}
diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json
index 15f02ab..c640711 100644
--- a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json
+++ b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenBackground.colorset/Contents.json
@@ -2,19 +2,19 @@
"colors": [
{
"color": {
+ "color-space": "srgb",
"components": {
"alpha": "1.000",
"blue": "1.00000000000000",
"green": "1.00000000000000",
"red": "1.00000000000000"
- },
- "color-space": "srgb"
+ }
},
"idiom": "universal"
}
],
"info": {
- "version": 1,
- "author": "expo"
+ "author": "expo",
+ "version": 1
}
-}
\ No newline at end of file
+}
diff --git a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json
index f65c008..f5ad720 100644
--- a/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json
+++ b/apps/mobile-legacy/ios/basango/Images.xcassets/SplashScreenLogo.imageset/Contents.json
@@ -1,23 +1,23 @@
{
"images": [
{
- "idiom": "universal",
"filename": "image.png",
+ "idiom": "universal",
"scale": "1x"
},
{
- "idiom": "universal",
"filename": "image@2x.png",
+ "idiom": "universal",
"scale": "2x"
},
{
- "idiom": "universal",
"filename": "image@3x.png",
+ "idiom": "universal",
"scale": "3x"
}
],
"info": {
- "version": 1,
- "author": "expo"
+ "author": "expo",
+ "version": 1
}
-}
\ No newline at end of file
+}
diff --git a/apps/mobile-legacy/package.json b/apps/mobile-legacy/package.json
index 518c874..49d7359 100644
--- a/apps/mobile-legacy/package.json
+++ b/apps/mobile-legacy/package.json
@@ -1,49 +1,4 @@
{
- "name": "drc-news",
- "main": "expo-router/entry",
- "version": "1.0.0",
- "scripts": {
- "start": "expo start",
- "android": "expo run:android",
- "ios": "expo run:ios",
- "web": "expo start --web",
- "test": "jest --watchAll",
- "============= EAS BUILD =============": "",
- "build:ios:dev": "eas build --profile development --platform ios",
- "build:ios:sim": "eas build --profile dev-sim --platform ios",
- "build:ios:prev": "eas build --profile preview --platform ios",
- "build:ios:e2e": "eas build --profile ios-e2e --platform ios",
- "build:android:dev": "eas build --profile development --platform android",
- "build:android:sim": "eas build --profile dev-sim --platform android",
- "build:android:prev": "eas build --profile preview --platform android",
- "build:android:e2e": "eas build --profile android-e2e --platform android",
- "build:android:prod": "eas build --profile production --platform android",
- "build:ios:prod": "eas build --profile production --platform ios",
- "===================== EAS SUBMIT =====================": "",
- "eas:android:submit": "eas submit -p android --profile production",
- "eas:ios:submit": "eas submit -p ios --profile production",
- "=========== CODE STYLE ============": "",
- "check-types": "tsc --noEmit",
- "check": "prettier src --check",
- "format": "prettier src --write",
- "lint:check": "eslint src --debug",
- "lint:fix": "eslint src --fix",
- "============= HUSKY =============": "",
- "prepare": "husky",
- "commit": "cz",
- "============= MISCELLANEOUS =============": "",
- "delete:dstore": "find -name '.DS_Store' -type f -delete"
- },
- "lint-staged": {
- "*.ts": [
- "prettier --write",
- "eslint --fix"
- ],
- "*.tsx": [
- "prettier --write",
- "eslint --fix"
- ]
- },
"commitlint": {
"extends": [
"@commitlint/config-conventional"
@@ -54,12 +9,6 @@
"path": "cz-conventional-changelog"
}
},
- "jest": {
- "preset": "jest-expo"
- },
- "overrides": {
- "globals": "14.0.0"
- },
"dependencies": {
"@expo-google-fonts/inter": "^0.3.0",
"@expo/vector-icons": "^14.0.2",
@@ -132,5 +81,56 @@
"react-test-renderer": "18.3.1",
"typescript": "^5.3.3"
},
- "private": true
+ "jest": {
+ "preset": "jest-expo"
+ },
+ "lint-staged": {
+ "*.ts": [
+ "prettier --write",
+ "eslint --fix"
+ ],
+ "*.tsx": [
+ "prettier --write",
+ "eslint --fix"
+ ]
+ },
+ "main": "expo-router/entry",
+ "name": "drc-news",
+ "overrides": {
+ "globals": "14.0.0"
+ },
+ "private": true,
+ "scripts": {
+ "=========== CODE STYLE ============": "",
+ "============= EAS BUILD =============": "",
+ "============= HUSKY =============": "",
+ "============= MISCELLANEOUS =============": "",
+ "===================== EAS SUBMIT =====================": "",
+ "android": "expo run:android",
+ "build:android:dev": "eas build --profile development --platform android",
+ "build:android:e2e": "eas build --profile android-e2e --platform android",
+ "build:android:prev": "eas build --profile preview --platform android",
+ "build:android:prod": "eas build --profile production --platform android",
+ "build:android:sim": "eas build --profile dev-sim --platform android",
+ "build:ios:dev": "eas build --profile development --platform ios",
+ "build:ios:e2e": "eas build --profile ios-e2e --platform ios",
+ "build:ios:prev": "eas build --profile preview --platform ios",
+ "build:ios:prod": "eas build --profile production --platform ios",
+ "build:ios:sim": "eas build --profile dev-sim --platform ios",
+ "check": "prettier src --check",
+ "check-types": "tsc --noEmit",
+ "commit": "cz",
+ "delete:dstore": "find -name '.DS_Store' -type f -delete",
+ "eas:android:submit": "eas submit -p android --profile production",
+ "eas:ios:submit": "eas submit -p ios --profile production",
+ "format": "prettier src --write",
+ "ios": "expo run:ios",
+ "lint:check": "eslint src --debug",
+ "lint:fix": "eslint src --fix",
+ "prepare": "husky",
+ "start": "expo start",
+ "test": "jest --watchAll",
+ "web": "expo start --web"
+ },
+ "version": "1.0.0"
}
diff --git a/apps/mobile-legacy/src/api/client.ts b/apps/mobile-legacy/src/api/client.ts
index b058eaa..508173d 100644
--- a/apps/mobile-legacy/src/api/client.ts
+++ b/apps/mobile-legacy/src/api/client.ts
@@ -5,113 +5,113 @@ import { clearTokens, getAccessToken, getRefreshToken, setTokens } from "@/store
const endpoint = process.env.EXPO_PUBLIC_API_URL!;
const client: AxiosInstance = axios.create({
- baseURL: endpoint,
- headers: {
- "Content-Type": "application/json",
- Accept: "application/json",
- },
+ baseURL: endpoint,
+ headers: {
+ Accept: "application/json",
+ "Content-Type": "application/json",
+ },
});
let isAuthTokenRefreshing = false;
let failedRequestsQueue: ((token: string) => void)[] = [];
const processFailedRequestsQueue = (token: string) => {
- failedRequestsQueue.forEach(callback => callback(token));
- failedRequestsQueue = [];
+ failedRequestsQueue.forEach((callback) => callback(token));
+ failedRequestsQueue = [];
};
// Wait for 120 seconds before timing out
-axios.interceptors.request.use(config => {
- config.timeout = 120_000;
- return config;
+axios.interceptors.request.use((config) => {
+ config.timeout = 120_000;
+ return config;
});
// Add the Authorization header to all requests
-client.interceptors.request.use(async config => {
- const token = await getAccessToken();
- if (token) {
- config.headers["Authorization"] = `Bearer ${token}`;
- }
+client.interceptors.request.use(async (config) => {
+ const token = await getAccessToken();
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
- return config;
+ return config;
});
// Handle 401 errors and refresh the token
client.interceptors.response.use(
- response => response,
- async error => {
- const originalRequest = error.config;
- const status = error.response?.status;
+ (response) => response,
+ async (error) => {
+ const originalRequest = error.config;
+ const status = error.response?.status;
- if (status === 401 && !originalRequest._retry) {
- originalRequest._retry = true;
+ if (status === 401 && !originalRequest._retry) {
+ originalRequest._retry = true;
- if (isAuthTokenRefreshing) {
- return new Promise(resolve => {
- failedRequestsQueue.push((token: string) => {
- originalRequest.headers["Authorization"] = `Bearer ${token}`;
- resolve(client(originalRequest));
- });
- });
- }
+ if (isAuthTokenRefreshing) {
+ return new Promise((resolve) => {
+ failedRequestsQueue.push((token: string) => {
+ originalRequest.headers.Authorization = `Bearer ${token}`;
+ resolve(client(originalRequest));
+ });
+ });
+ }
- isAuthTokenRefreshing = true;
+ isAuthTokenRefreshing = true;
- try {
- const refreshToken = await getRefreshToken();
- if (!refreshToken) {
- await clearTokens();
- return Promise.reject(error);
- }
-
- const response = await axios.post(`${endpoint}/token/refresh`, {
- refresh_token: refreshToken,
- } as RefreshTokenPayload);
-
- const updatedToken = response.data.token;
- await setTokens(updatedToken, refreshToken);
- processFailedRequestsQueue(updatedToken);
-
- originalRequest.headers["Authorization"] = `Bearer ${updatedToken}`;
- return client(originalRequest);
- } catch (error) {
- await clearTokens();
- return Promise.reject(error);
- } finally {
- isAuthTokenRefreshing = false;
- }
+ try {
+ const refreshToken = await getRefreshToken();
+ if (!refreshToken) {
+ await clearTokens();
+ return Promise.reject(error);
}
+ const response = await axios.post(`${endpoint}/token/refresh`, {
+ refresh_token: refreshToken,
+ } as RefreshTokenPayload);
+
+ const updatedToken = response.data.token;
+ await setTokens(updatedToken, refreshToken);
+ processFailedRequestsQueue(updatedToken);
+
+ originalRequest.headers.Authorization = `Bearer ${updatedToken}`;
+ return client(originalRequest);
+ } catch (error) {
+ await clearTokens();
return Promise.reject(error);
+ } finally {
+ isAuthTokenRefreshing = false;
+ }
}
+
+ return Promise.reject(error);
+ },
);
if (__DEV__) {
- // Log HTTP requests and responses
- client.interceptors.request.use(
- async config => {
- console.log("HTTP REQUEST", {
- baseURL: config.baseURL,
- url: config.url,
- data: config.data,
- });
+ // Log HTTP requests and responses
+ client.interceptors.request.use(
+ async (config) => {
+ console.log("HTTP REQUEST", {
+ baseURL: config.baseURL,
+ data: config.data,
+ url: config.url,
+ });
- return config;
- },
- error => console.log(JSON.stringify(error))
- );
+ return config;
+ },
+ (error) => console.log(JSON.stringify(error)),
+ );
- client.interceptors.response.use(
- response => {
- console.log("HTTP RESPONSE", {
- stats: response.status,
- data: response.data,
- });
+ client.interceptors.response.use(
+ (response) => {
+ console.log("HTTP RESPONSE", {
+ data: response.data,
+ stats: response.status,
+ });
- return response;
- },
- error => console.log(JSON.stringify(error))
- );
+ return response;
+ },
+ (error) => console.log(JSON.stringify(error)),
+ );
}
export default client;
diff --git a/apps/mobile-legacy/src/api/endpoint.ts b/apps/mobile-legacy/src/api/endpoint.ts
index c422e2b..b467d09 100644
--- a/apps/mobile-legacy/src/api/endpoint.ts
+++ b/apps/mobile-legacy/src/api/endpoint.ts
@@ -1,33 +1,33 @@
export const endpoint = {
- feedManagement: {
- addArticleToBookmark: (bookmarkId: string, articleId: string) =>
- `feed/bookmarks/${bookmarkId}/articles/${articleId}`,
- addCommentToArticle: (articleId: string) => `/feed/articles/${articleId}/comments`,
- createBookmark: `/feed/bookmarks`,
- deleteBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`,
- followSource: (sourceId: string) => `/feed/sources/${sourceId}/follow`,
- getArticleCommentList: (articleId: string) => `/feed/articles/${articleId}/comments`,
- getArticleDetails: (articleId: string) => `/feed/articles/${articleId}`,
- getArticleOverviewList: `/feed/articles`,
- getBookmarkList: `/feed/bookmarks`,
- getBookmarkedArticlesList: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}/articles`,
- getSourceArticleOverviewList: (sourceId: string) => `/feed/sources/${sourceId}/articles`,
- getSourceDetails: (sourceId: string) => `/feed/sources/${sourceId}`,
- getSourceOverviewList: `/feed/sources`,
- removeArticleFromBookmark: (bookmarkId: string, articleId: string) =>
- `/feed/bookmarks/${bookmarkId}/articles/${articleId}`,
- unfollowSource: (sourceId: string) => `/feed/sources/${sourceId}/unfollow`,
- updateBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`,
- },
- identityAndAccess: {
- login: "/login_check",
- logout: "/token/invalidate",
- register: "/register",
- getUserProfile: "/me",
- requestPassword: "/password/request",
- confirmAccount: (token: string) => `/account/confirm/${token}`,
- resetPassword: (token: string) => `/password/reset/${token}`,
- unlockAccount: (token: string) => `/account/unlock/${token}`,
- updatePassword: "/password/update",
- },
+ feedManagement: {
+ addArticleToBookmark: (bookmarkId: string, articleId: string) =>
+ `feed/bookmarks/${bookmarkId}/articles/${articleId}`,
+ addCommentToArticle: (articleId: string) => `/feed/articles/${articleId}/comments`,
+ createBookmark: `/feed/bookmarks`,
+ deleteBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`,
+ followSource: (sourceId: string) => `/feed/sources/${sourceId}/follow`,
+ getArticleCommentList: (articleId: string) => `/feed/articles/${articleId}/comments`,
+ getArticleDetails: (articleId: string) => `/feed/articles/${articleId}`,
+ getArticleOverviewList: `/feed/articles`,
+ getBookmarkedArticlesList: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}/articles`,
+ getBookmarkList: `/feed/bookmarks`,
+ getSourceArticleOverviewList: (sourceId: string) => `/feed/sources/${sourceId}/articles`,
+ getSourceDetails: (sourceId: string) => `/feed/sources/${sourceId}`,
+ getSourceOverviewList: `/feed/sources`,
+ removeArticleFromBookmark: (bookmarkId: string, articleId: string) =>
+ `/feed/bookmarks/${bookmarkId}/articles/${articleId}`,
+ unfollowSource: (sourceId: string) => `/feed/sources/${sourceId}/unfollow`,
+ updateBookmark: (bookmarkId: string) => `/feed/bookmarks/${bookmarkId}`,
+ },
+ identityAndAccess: {
+ confirmAccount: (token: string) => `/account/confirm/${token}`,
+ getUserProfile: "/me",
+ login: "/login_check",
+ logout: "/token/invalidate",
+ register: "/register",
+ requestPassword: "/password/request",
+ resetPassword: (token: string) => `/password/reset/${token}`,
+ unlockAccount: (token: string) => `/account/unlock/${token}`,
+ updatePassword: "/password/update",
+ },
};
diff --git a/apps/mobile-legacy/src/api/request/feed-management/article.ts b/apps/mobile-legacy/src/api/request/feed-management/article.ts
index 6775960..5b2c545 100644
--- a/apps/mobile-legacy/src/api/request/feed-management/article.ts
+++ b/apps/mobile-legacy/src/api/request/feed-management/article.ts
@@ -1,19 +1,30 @@
import { endpoint } from "@/api/endpoint";
import { Article, ArticleOverview, TrendingArticle } from "@/api/schema/feed-management/article";
-import { ArticleFilters, useGetQuery, usePaginatedInfiniteQuery, usePaginatedQuery } from "@/api/shared";
+import {
+ ArticleFilters,
+ useGetQuery,
+ usePaginatedInfiniteQuery,
+ usePaginatedQuery,
+} from "@/api/shared";
export const useArticleTrendingList = (filters: ArticleFilters = {}) => {
- return usePaginatedQuery("/feed/trending", filters);
+ return usePaginatedQuery("/feed/trending", filters);
};
export const useArticleDetails = (articleId: string) => {
- return useGetQuery(endpoint.feedManagement.getArticleDetails(articleId));
+ return useGetQuery(endpoint.feedManagement.getArticleDetails(articleId));
};
export const useArticleOverviewList = (filters: ArticleFilters = {}) => {
- return usePaginatedQuery(endpoint.feedManagement.getArticleOverviewList, filters);
+ return usePaginatedQuery(
+ endpoint.feedManagement.getArticleOverviewList,
+ filters,
+ );
};
export const useInfiniteArticleOverviewList = (filters: ArticleFilters = {}) => {
- return usePaginatedInfiniteQuery(endpoint.feedManagement.getArticleOverviewList, filters);
+ return usePaginatedInfiniteQuery(
+ endpoint.feedManagement.getArticleOverviewList,
+ filters,
+ );
};
diff --git a/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts b/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts
index 6d901c8..420498c 100644
--- a/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts
+++ b/apps/mobile-legacy/src/api/request/feed-management/bookmark.ts
@@ -1,34 +1,44 @@
import { endpoint } from "@/api/endpoint";
-import { Bookmark, BookmarkedArticle, BookmarkPayload } from "@/api/schema/feed-management/bookmark";
-import { ArticleFilters, useDeleteQuery, usePaginatedInfiniteQuery, usePostQuery, usePutQuery } from "@/api/shared";
+import {
+ Bookmark,
+ BookmarkedArticle,
+ BookmarkPayload,
+} from "@/api/schema/feed-management/bookmark";
+import {
+ ArticleFilters,
+ useDeleteQuery,
+ usePaginatedInfiniteQuery,
+ usePostQuery,
+ usePutQuery,
+} from "@/api/shared";
export const useCreateBookmark = () => {
- return usePostQuery(endpoint.feedManagement.createBookmark);
+ return usePostQuery(endpoint.feedManagement.createBookmark);
};
export const useUpdateBookmark = (bookmarkId: string) => {
- return usePutQuery(endpoint.feedManagement.updateBookmark(bookmarkId));
+ return usePutQuery(endpoint.feedManagement.updateBookmark(bookmarkId));
};
export const useDeleteBookmark = (bookmarkId: string) => {
- return useDeleteQuery(endpoint.feedManagement.deleteBookmark(bookmarkId));
+ return useDeleteQuery(endpoint.feedManagement.deleteBookmark(bookmarkId));
};
export const useAddArticleToBookmark = (bookmarkId: string, articleId: string) => {
- return usePostQuery(endpoint.feedManagement.addArticleToBookmark(bookmarkId, articleId));
+ return usePostQuery(endpoint.feedManagement.addArticleToBookmark(bookmarkId, articleId));
};
export const useRemoveArticleFromBookmark = (bookmarkId: string, articleId: string) => {
- return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(bookmarkId, articleId));
+ return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(bookmarkId, articleId));
};
export const useBookmarkList = (filters: ArticleFilters = {}) => {
- return usePaginatedInfiniteQuery(endpoint.feedManagement.getBookmarkList, filters);
+ return usePaginatedInfiniteQuery(endpoint.feedManagement.getBookmarkList, filters);
};
export const useBookmarkedArticlesList = (bookmarkId: string, filters: ArticleFilters = {}) => {
- return usePaginatedInfiniteQuery(
- endpoint.feedManagement.getBookmarkedArticlesList(bookmarkId),
- filters
- );
+ return usePaginatedInfiniteQuery(
+ endpoint.feedManagement.getBookmarkedArticlesList(bookmarkId),
+ filters,
+ );
};
diff --git a/apps/mobile-legacy/src/api/request/feed-management/comment.ts b/apps/mobile-legacy/src/api/request/feed-management/comment.ts
index cadbe5e..724d7ff 100644
--- a/apps/mobile-legacy/src/api/request/feed-management/comment.ts
+++ b/apps/mobile-legacy/src/api/request/feed-management/comment.ts
@@ -3,13 +3,15 @@ import { Comment, CommentPayload } from "@/api/schema/feed-management/comment";
import { useDeleteQuery, usePaginatedInfiniteQuery, usePostQuery } from "@/api/shared";
export const useArticleCommentList = (articleId: string) => {
- return usePaginatedInfiniteQuery(endpoint.feedManagement.getArticleCommentList(articleId));
+ return usePaginatedInfiniteQuery(
+ endpoint.feedManagement.getArticleCommentList(articleId),
+ );
};
export const useAddCommentToArticle = (articleId: string) => {
- return usePostQuery(endpoint.feedManagement.addCommentToArticle(articleId));
+ return usePostQuery(endpoint.feedManagement.addCommentToArticle(articleId));
};
export const useRemoveCommentFromArticle = (articleId: string, commentId: string) => {
- return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(articleId, commentId));
+ return useDeleteQuery(endpoint.feedManagement.removeArticleFromBookmark(articleId, commentId));
};
diff --git a/apps/mobile-legacy/src/api/request/feed-management/source.ts b/apps/mobile-legacy/src/api/request/feed-management/source.ts
index 8a442c8..2fa8af7 100644
--- a/apps/mobile-legacy/src/api/request/feed-management/source.ts
+++ b/apps/mobile-legacy/src/api/request/feed-management/source.ts
@@ -1,27 +1,36 @@
import { endpoint } from "@/api/endpoint";
import { ArticleOverview } from "@/api/schema/feed-management/article";
import { SourceDetails, SourceOverview } from "@/api/schema/feed-management/source";
-import { ArticleFilters, useDeleteQuery, useGetQuery, usePaginatedInfiniteQuery, usePostQuery } from "@/api/shared";
+import {
+ ArticleFilters,
+ useDeleteQuery,
+ useGetQuery,
+ usePaginatedInfiniteQuery,
+ usePostQuery,
+} from "@/api/shared";
export const useSourceDetails = (sourceId: string) => {
- return useGetQuery(endpoint.feedManagement.getSourceDetails(sourceId));
+ return useGetQuery(endpoint.feedManagement.getSourceDetails(sourceId));
};
export const useSourceOverviewList = (filters: ArticleFilters = {}) => {
- return usePaginatedInfiniteQuery(endpoint.feedManagement.getSourceOverviewList, filters);
+ return usePaginatedInfiniteQuery(
+ endpoint.feedManagement.getSourceOverviewList,
+ filters,
+ );
};
export const useSourceArticleOverviewList = (sourceId: string, filters: ArticleFilters = {}) => {
- return usePaginatedInfiniteQuery(
- endpoint.feedManagement.getSourceArticleOverviewList(sourceId),
- filters
- );
+ return usePaginatedInfiniteQuery(
+ endpoint.feedManagement.getSourceArticleOverviewList(sourceId),
+ filters,
+ );
};
export const useFollowSource = (sourceId: string) => {
- return usePostQuery(endpoint.feedManagement.followSource(sourceId));
+ return usePostQuery(endpoint.feedManagement.followSource(sourceId));
};
export const useUnfollowSource = (sourceId: string) => {
- return useDeleteQuery(endpoint.feedManagement.unfollowSource(sourceId));
+ return useDeleteQuery(endpoint.feedManagement.unfollowSource(sourceId));
};
diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/login.ts b/apps/mobile-legacy/src/api/request/identity-and-access/login.ts
index 71c18f7..802cf3f 100644
--- a/apps/mobile-legacy/src/api/request/identity-and-access/login.ts
+++ b/apps/mobile-legacy/src/api/request/identity-and-access/login.ts
@@ -3,13 +3,13 @@ import { LoginPayload, LoginResponse } from "@/api/schema/identity-and-access/lo
import { useGetQuery, usePostQuery } from "@/api/shared";
export const useLogin = () => {
- return usePostQuery(endpoint.identityAndAccess.login);
+ return usePostQuery(endpoint.identityAndAccess.login);
};
export const useLogout = () => {
- return usePostQuery(endpoint.identityAndAccess.logout);
+ return usePostQuery(endpoint.identityAndAccess.logout);
};
export const useUnlockAccount = (token: string) => {
- return useGetQuery(endpoint.identityAndAccess.unlockAccount(token));
+ return useGetQuery(endpoint.identityAndAccess.unlockAccount(token));
};
diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/password.ts b/apps/mobile-legacy/src/api/request/identity-and-access/password.ts
index be22a56..6f33b48 100644
--- a/apps/mobile-legacy/src/api/request/identity-and-access/password.ts
+++ b/apps/mobile-legacy/src/api/request/identity-and-access/password.ts
@@ -1,19 +1,19 @@
import { endpoint } from "@/api/endpoint";
import {
- RequestPasswordPayload,
- ResetPasswordPayload,
- UpdatePasswordPayload,
+ RequestPasswordPayload,
+ ResetPasswordPayload,
+ UpdatePasswordPayload,
} from "@/api/schema/identity-and-access/password";
import { usePostQuery, usePutQuery } from "@/api/shared";
export const usePasswordForgotten = () => {
- return usePostQuery(endpoint.identityAndAccess.requestPassword);
+ return usePostQuery(endpoint.identityAndAccess.requestPassword);
};
export const usePasswordReset = (token: string) => {
- return usePostQuery(endpoint.identityAndAccess.resetPassword(token));
+ return usePostQuery(endpoint.identityAndAccess.resetPassword(token));
};
export const usePasswordUpdate = () => {
- return usePutQuery(endpoint.identityAndAccess.updatePassword);
+ return usePutQuery(endpoint.identityAndAccess.updatePassword);
};
diff --git a/apps/mobile-legacy/src/api/request/identity-and-access/register.ts b/apps/mobile-legacy/src/api/request/identity-and-access/register.ts
index a5258f3..528e371 100644
--- a/apps/mobile-legacy/src/api/request/identity-and-access/register.ts
+++ b/apps/mobile-legacy/src/api/request/identity-and-access/register.ts
@@ -3,9 +3,9 @@ import { RegisterPayload } from "@/api/schema/identity-and-access/register";
import { useGetQuery, usePostQuery } from "@/api/shared";
export const useRegister = () => {
- return usePostQuery(endpoint.identityAndAccess.register);
+ return usePostQuery(endpoint.identityAndAccess.register);
};
export const useConfirmAccount = (token: string) => {
- return useGetQuery(endpoint.identityAndAccess.confirmAccount(token));
+ return useGetQuery(endpoint.identityAndAccess.confirmAccount(token));
};
diff --git a/apps/mobile-legacy/src/api/schema/feed-management/article.ts b/apps/mobile-legacy/src/api/schema/feed-management/article.ts
index 450b99e..e890afb 100644
--- a/apps/mobile-legacy/src/api/schema/feed-management/article.ts
+++ b/apps/mobile-legacy/src/api/schema/feed-management/article.ts
@@ -1,45 +1,45 @@
import { SourceReference } from "@/api/schema/feed-management/source";
export type ArticleOverview = {
- id: string;
- title: string;
- link: string;
- categories: string[];
- excerpt: string;
- source: SourceReference;
- publishedAt: string;
- image?: string;
- readingTime: number;
- bookmarked: boolean;
+ id: string;
+ title: string;
+ link: string;
+ categories: string[];
+ excerpt: string;
+ source: SourceReference;
+ publishedAt: string;
+ image?: string;
+ readingTime: number;
+ bookmarked: boolean;
};
export type Article = {
- id: string;
- title: string;
- link: string;
- categories: string[];
- body: string;
- source: SourceReference;
- hash: string;
- credibility: {
- bias: "neutral" | "slightly" | "partisan" | "extreme";
- reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust";
- transparency: "low" | "medium" | "high";
- };
- sentiment: "negative" | "positive" | "neutral";
- metadata?: {
- title?: string;
- description?: string;
- image?: string;
- video?: string;
- audio?: string;
- locale?: string;
- };
- readingTime: number;
- publishedAt: string;
- crawledAt: string;
- updatedAt: string;
- bookmarked: boolean;
+ id: string;
+ title: string;
+ link: string;
+ categories: string[];
+ body: string;
+ source: SourceReference;
+ hash: string;
+ credibility: {
+ bias: "neutral" | "slightly" | "partisan" | "extreme";
+ reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust";
+ transparency: "low" | "medium" | "high";
+ };
+ sentiment: "negative" | "positive" | "neutral";
+ metadata?: {
+ title?: string;
+ description?: string;
+ image?: string;
+ video?: string;
+ audio?: string;
+ locale?: string;
+ };
+ readingTime: number;
+ publishedAt: string;
+ crawledAt: string;
+ updatedAt: string;
+ bookmarked: boolean;
};
export type TrendingArticle = ArticleOverview;
diff --git a/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts b/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts
index 85113bc..9689796 100644
--- a/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts
+++ b/apps/mobile-legacy/src/api/schema/feed-management/bookmark.ts
@@ -3,28 +3,28 @@ import Joi from "joi";
import { ArticleOverview } from "@/api/schema/feed-management/article";
export type BookmarkPayload = {
- name: string;
- description?: string;
- isPublic: boolean;
+ name: string;
+ description?: string;
+ isPublic: boolean;
};
export type Bookmark = {
- id: string;
- name: string;
- createdAt: string;
- description?: string;
- articlesCount: number;
- isPublic: boolean;
- updatedAt?: string;
+ id: string;
+ name: string;
+ createdAt: string;
+ description?: string;
+ articlesCount: number;
+ isPublic: boolean;
+ updatedAt?: string;
};
export type BookmarkedArticle = ArticleOverview;
export const BookmarkPayloadSchema = Joi.object({
- name: Joi.string().required().messages({
- "string.empty": "Le nom est requis",
- "any.required": "Le nom est requis",
- }),
- description: Joi.string().optional(),
- isPublic: Joi.boolean().optional(),
+ description: Joi.string().optional(),
+ isPublic: Joi.boolean().optional(),
+ name: Joi.string().required().messages({
+ "any.required": "Le nom est requis",
+ "string.empty": "Le nom est requis",
+ }),
});
diff --git a/apps/mobile-legacy/src/api/schema/feed-management/comment.ts b/apps/mobile-legacy/src/api/schema/feed-management/comment.ts
index ca6b4ad..e30ee8a 100644
--- a/apps/mobile-legacy/src/api/schema/feed-management/comment.ts
+++ b/apps/mobile-legacy/src/api/schema/feed-management/comment.ts
@@ -1,14 +1,14 @@
export type Comment = {
+ id: string;
+ content: string;
+ user: {
id: string;
- content: string;
- user: {
- id: string;
- name: string;
- };
- sentiment: "positive" | "neutral" | "negative";
- createdAt: string;
+ name: string;
+ };
+ sentiment: "positive" | "neutral" | "negative";
+ createdAt: string;
};
export type CommentPayload = {
- content: string;
+ content: string;
};
diff --git a/apps/mobile-legacy/src/api/schema/feed-management/source.ts b/apps/mobile-legacy/src/api/schema/feed-management/source.ts
index 66f737f..1c02d57 100644
--- a/apps/mobile-legacy/src/api/schema/feed-management/source.ts
+++ b/apps/mobile-legacy/src/api/schema/feed-management/source.ts
@@ -1,54 +1,54 @@
export type SourceReference = {
- id: string;
- name: string;
- displayName?: string;
- image: string;
- url: string;
+ id: string;
+ name: string;
+ displayName?: string;
+ image: string;
+ url: string;
};
export type SourceOverview = {
- id: string;
- name: string;
- displayName?: string;
- image: string;
- url: string;
- followed: boolean;
+ id: string;
+ name: string;
+ displayName?: string;
+ image: string;
+ url: string;
+ followed: boolean;
};
export type CategoryShare = {
- name: string;
- count: number;
- percentage: number;
+ name: string;
+ count: number;
+ percentage: number;
};
export type PublicationEntry = {
- date: string;
- count: number;
+ date: string;
+ count: number;
};
export type SourceDetails = {
- id: string;
- name: string;
- url: string;
- credibility: {
- bias: "neutral" | "slightly" | "partisan" | "extreme";
- reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust";
- transparency: "low" | "medium" | "high";
- };
- publicationGraph: {
- items: PublicationEntry[];
- total: number;
- };
- categoryShares: {
- items: CategoryShare[];
- total: number;
- };
- articlesCount: number;
- crawledAt: string;
- displayName?: string;
- description?: string;
- updatedAt?: string;
- metadataAvailable: number;
- followed: boolean;
- image: string;
+ id: string;
+ name: string;
+ url: string;
+ credibility: {
+ bias: "neutral" | "slightly" | "partisan" | "extreme";
+ reliability: "trusted" | "reliable" | "average" | "unreliable" | "low_trust";
+ transparency: "low" | "medium" | "high";
+ };
+ publicationGraph: {
+ items: PublicationEntry[];
+ total: number;
+ };
+ categoryShares: {
+ items: CategoryShare[];
+ total: number;
+ };
+ articlesCount: number;
+ crawledAt: string;
+ displayName?: string;
+ description?: string;
+ updatedAt?: string;
+ metadataAvailable: number;
+ followed: boolean;
+ image: string;
};
diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts
index 94a37e1..8348558 100644
--- a/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts
+++ b/apps/mobile-legacy/src/api/schema/identity-and-access/login.ts
@@ -1,31 +1,31 @@
import Joi from "joi";
export type LoginPayload = {
- username: string;
- password: string;
+ username: string;
+ password: string;
};
export type LoginResponse = {
- token: string;
- refresh_token: string;
+ token: string;
+ refresh_token: string;
};
export type RefreshTokenPayload = {
- refresh_token: string;
+ refresh_token: string;
};
export type RefreshTokenResponse = {
- token: string;
+ token: string;
};
export const LoginPayloadSchema = Joi.object({
- username: Joi.string().required().messages({
- "string.empty": "L'email est requis",
- "any.required": "L'email est requis",
- }),
- password: Joi.string().min(4).required().messages({
- "string.empty": "Le mot de passe est requis",
- "string.min": "Le mot de passe doit comporter au moins 4 caractères",
- "any.required": "Le mot de passe est requis",
- }),
+ password: Joi.string().min(4).required().messages({
+ "any.required": "Le mot de passe est requis",
+ "string.empty": "Le mot de passe est requis",
+ "string.min": "Le mot de passe doit comporter au moins 4 caractères",
+ }),
+ username: Joi.string().required().messages({
+ "any.required": "L'email est requis",
+ "string.empty": "L'email est requis",
+ }),
});
diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts
index 85faf03..ead279e 100644
--- a/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts
+++ b/apps/mobile-legacy/src/api/schema/identity-and-access/password.ts
@@ -1,53 +1,53 @@
import Joi from "joi";
export type RequestPasswordPayload = {
- email: string;
+ email: string;
};
export type ResetPasswordPayload = {
- password: string;
- confirm: string;
+ password: string;
+ confirm: string;
};
export type UpdatePasswordPayload = {
- current: string;
- password: string;
- confirm: string;
+ current: string;
+ password: string;
+ confirm: string;
};
export const RequestPasswordPayloadSchema = Joi.object({
- email: Joi.string().required().messages({
- "string.empty": "L'email est requis",
- "any.required": "L'email est requis",
- }),
+ email: Joi.string().required().messages({
+ "any.required": "L'email est requis",
+ "string.empty": "L'email est requis",
+ }),
});
export const ResetPasswordPayloadSchema = Joi.object({
- password: Joi.string().min(6).required().messages({
- "string.empty": "Le mot de passe est requis",
- "string.min": "Le mot de passe doit comporter au moins 6 caractères",
- "any.required": "Le mot de passe est requis",
- }),
- confirm: Joi.string().valid(Joi.ref("password")).required().messages({
- "any.only": "Les mots de passe ne correspondent pas",
- "string.empty": "La confirmation du mot de passe est requise",
- "any.required": "La confirmation du mot de passe est requise",
- }),
+ confirm: Joi.string().valid(Joi.ref("password")).required().messages({
+ "any.only": "Les mots de passe ne correspondent pas",
+ "any.required": "La confirmation du mot de passe est requise",
+ "string.empty": "La confirmation du mot de passe est requise",
+ }),
+ password: Joi.string().min(6).required().messages({
+ "any.required": "Le mot de passe est requis",
+ "string.empty": "Le mot de passe est requis",
+ "string.min": "Le mot de passe doit comporter au moins 6 caractères",
+ }),
});
export const UpdatePasswordPayloadSchema = Joi.object({
- current: Joi.string().required().messages({
- "string.empty": "Le mot de passe actuel est requis",
- "any.required": "Le mot de passe actuel est requis",
- }),
- password: Joi.string().min(6).required().messages({
- "string.empty": "Le nouveau mot de passe est requis",
- "string.min": "Le nouveau mot de passe doit comporter au moins 6 caractères",
- "any.required": "Le nouveau mot de passe est requis",
- }),
- confirm: Joi.string().valid(Joi.ref("password")).required().messages({
- "any.only": "Les mots de passe ne correspondent pas",
- "string.empty": "La confirmation du nouveau mot de passe est requise",
- "any.required": "La confirmation du nouveau mot de passe est requise",
- }),
+ confirm: Joi.string().valid(Joi.ref("password")).required().messages({
+ "any.only": "Les mots de passe ne correspondent pas",
+ "any.required": "La confirmation du nouveau mot de passe est requise",
+ "string.empty": "La confirmation du nouveau mot de passe est requise",
+ }),
+ current: Joi.string().required().messages({
+ "any.required": "Le mot de passe actuel est requis",
+ "string.empty": "Le mot de passe actuel est requis",
+ }),
+ password: Joi.string().min(6).required().messages({
+ "any.required": "Le nouveau mot de passe est requis",
+ "string.empty": "Le nouveau mot de passe est requis",
+ "string.min": "Le nouveau mot de passe doit comporter au moins 6 caractères",
+ }),
});
diff --git a/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts b/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts
index a97fc90..d3268cf 100644
--- a/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts
+++ b/apps/mobile-legacy/src/api/schema/identity-and-access/register.ts
@@ -1,23 +1,23 @@
import Joi from "joi";
export type RegisterPayload = {
- name: string;
- email: string;
- password: string;
+ name: string;
+ email: string;
+ password: string;
};
export const RegisterPayloadSchema = Joi.object({
- name: Joi.string().required().messages({
- "string.empty": "Le nom est requis",
- "any.required": "Le nom est requis",
- }),
- email: Joi.string().required().messages({
- "string.empty": "L'email est requis",
- "any.required": "L'email est requis",
- }),
- password: Joi.string().min(6).required().messages({
- "string.empty": "Le mot de passe est requis",
- "string.min": "Le mot de passe doit comporter au moins 4 caractères",
- "any.required": "Le mot de passe est requis",
- }),
+ email: Joi.string().required().messages({
+ "any.required": "L'email est requis",
+ "string.empty": "L'email est requis",
+ }),
+ name: Joi.string().required().messages({
+ "any.required": "Le nom est requis",
+ "string.empty": "Le nom est requis",
+ }),
+ password: Joi.string().min(6).required().messages({
+ "any.required": "Le mot de passe est requis",
+ "string.empty": "Le mot de passe est requis",
+ "string.min": "Le mot de passe doit comporter au moins 4 caractères",
+ }),
});
diff --git a/apps/mobile-legacy/src/api/shared.ts b/apps/mobile-legacy/src/api/shared.ts
index ece1da2..d7cdad5 100644
--- a/apps/mobile-legacy/src/api/shared.ts
+++ b/apps/mobile-legacy/src/api/shared.ts
@@ -1,150 +1,167 @@
-import { skipToken, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import {
+ skipToken,
+ useInfiniteQuery,
+ useMutation,
+ useQuery,
+ useQueryClient,
+} from "@tanstack/react-query";
import { AxiosError } from "axios";
import qs from "qs";
import client from "@/api/client";
export type PaginationFilters = {
- page?: number;
- limit?: number;
- lastId?: string;
+ page?: number;
+ limit?: number;
+ lastId?: string;
};
export type ArticleFilters = PaginationFilters & {
- dateRange?: {
- start: number;
- end: number;
- };
- search?: string;
- sortDirection?: "asc" | "desc";
+ dateRange?: {
+ start: number;
+ end: number;
+ };
+ search?: string;
+ sortDirection?: "asc" | "desc";
};
export type PaginationInfo = {
- current: number;
- limit: number;
- lastId?: string;
- offset: number;
+ current: number;
+ limit: number;
+ lastId?: string;
+ offset: number;
};
export type ClientDetailErrorResponse = {
- type: string;
- title: string;
- detail: string;
- status: number;
+ type: string;
+ title: string;
+ detail: string;
+ status: number;
};
export type ClientErrorResponse = {
- code: string;
- message: string;
+ code: string;
+ message: string;
};
export type ErrorResponse = AxiosError;
export type PaginatedResponse = {
- items: TItem[];
- pagination: PaginationInfo;
+ items: TItem[];
+ pagination: PaginationInfo;
};
-export const safeMessage = (error: AxiosError | Error): string => {
- if (error instanceof AxiosError && error.response) {
- const response = error.response.data;
+export const safeMessage = (
+ error: AxiosError | Error,
+): string => {
+ if (error instanceof AxiosError && error.response) {
+ const response = error.response.data;
- if ("message" in response) {
- return response.message;
- } else if ("detail" in response) {
- return response.detail;
- }
+ if ("message" in response) {
+ return response.message;
+ } else if ("detail" in response) {
+ return response.detail;
}
+ }
- return "Une erreur est survenue";
+ return "Une erreur est survenue";
};
-export const usePaginatedInfiniteQuery = (endpoint: string, filters: PaginationFilters = {}) => {
- return useInfiniteQuery, ErrorResponse>({
- initialData: undefined,
- initialPageParam: null,
- queryKey: [endpoint, filters],
- queryFn: async ({ pageParam = null }) => {
- const query = qs.stringify({ ...filters, lastId: pageParam }, { skipNulls: true });
- const url = `${endpoint}?${query}`;
- const response = await client.get>(url);
- return response.data;
- },
- getNextPageParam: (lastPage: PaginatedResponse) => {
- const { lastId } = lastPage.pagination;
- return lastId ? lastId : null;
- },
- staleTime: 1_000 * 60 * 10,
- });
+export const usePaginatedInfiniteQuery = (
+ endpoint: string,
+ filters: PaginationFilters = {},
+) => {
+ return useInfiniteQuery, ErrorResponse>({
+ getNextPageParam: (lastPage: PaginatedResponse) => {
+ const { lastId } = lastPage.pagination;
+ return lastId ? lastId : null;
+ },
+ initialData: undefined,
+ initialPageParam: null,
+ queryFn: async ({ pageParam = null }) => {
+ const query = qs.stringify({ ...filters, lastId: pageParam }, { skipNulls: true });
+ const url = `${endpoint}?${query}`;
+ const response = await client.get>(url);
+ return response.data;
+ },
+ queryKey: [endpoint, filters],
+ staleTime: 1_000 * 60 * 10,
+ });
};
export const usePaginatedQuery = (endpoint: string, filters: PaginationFilters = {}) => {
- return useQuery, ErrorResponse>({
- queryKey: [endpoint, filters],
- queryFn: async (): Promise> => {
- const query = qs.stringify({ ...filters, lastId: null }, { skipNulls: true });
- const url = `${endpoint}?${query}`;
- const response = await client.get>(url);
- return response.data;
- },
- staleTime: 1_000 * 60 * 10,
- });
+ return useQuery, ErrorResponse>({
+ queryFn: async (): Promise> => {
+ const query = qs.stringify({ ...filters, lastId: null }, { skipNulls: true });
+ const url = `${endpoint}?${query}`;
+ const response = await client.get>(url);
+ return response.data;
+ },
+ queryKey: [endpoint, filters],
+ staleTime: 1_000 * 60 * 10,
+ });
};
export const useGetQuery = (endpoint: string, enabled: boolean = true) => {
- return useQuery({
- queryKey: [endpoint],
- queryFn: enabled
- ? async (): Promise => {
- const response = await client.get(endpoint);
- return response.data;
- }
- : skipToken,
- staleTime: 1_000 * 60 * 10,
- });
+ return useQuery({
+ queryFn: enabled
+ ? async (): Promise => {
+ const response = await client.get(endpoint);
+ return response.data;
+ }
+ : skipToken,
+ queryKey: [endpoint],
+ staleTime: 1_000 * 60 * 10,
+ });
};
-export const usePostQuery = (endpoint: string, keys: string[] = []) => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: async (data: TPayload): Promise => {
- const response = await client.post(endpoint, data);
- return response.data;
- },
- onSuccess: async () => {
- for (const key of keys) {
- await queryClient.invalidateQueries({ queryKey: [key] });
- }
- },
- });
+export const usePostQuery = (
+ endpoint: string,
+ keys: string[] = [],
+) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: async (data: TPayload): Promise => {
+ const response = await client.post(endpoint, data);
+ return response.data;
+ },
+ onSuccess: async () => {
+ for (const key of keys) {
+ await queryClient.invalidateQueries({ queryKey: [key] });
+ }
+ },
+ });
};
-export const usePutQuery = (endpoint: string, keys: string[] = []) => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: async (data: TPayload): Promise => {
- const response = await client.put(endpoint, data);
- return response.data;
- },
- onSuccess: async () => {
- for (const key of keys) {
- await queryClient.invalidateQueries({ queryKey: [key] });
- }
- },
- });
+export const usePutQuery = (
+ endpoint: string,
+ keys: string[] = [],
+) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: async (data: TPayload): Promise => {
+ const response = await client.put(endpoint, data);
+ return response.data;
+ },
+ onSuccess: async () => {
+ for (const key of keys) {
+ await queryClient.invalidateQueries({ queryKey: [key] });
+ }
+ },
+ });
};
export const useDeleteQuery = (endpoint: string, keys: string[] = []) => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: async (): Promise => {
- const response = await client.delete(endpoint);
- return response.data;
- },
- onSuccess: async () => {
- for (const key of keys) {
- await queryClient.invalidateQueries({ queryKey: [key] });
- }
- },
- });
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: async (): Promise => {
+ const response = await client.delete(endpoint);
+ return response.data;
+ },
+ onSuccess: async () => {
+ for (const key of keys) {
+ await queryClient.invalidateQueries({ queryKey: [key] });
+ }
+ },
+ });
};
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx
index 0a7047a..1878fc2 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/_layout.tsx
@@ -1,82 +1,80 @@
-import React from "react";
-
import { BookMarked, Globe, Home, User } from "@tamagui/lucide-icons";
import { Tabs } from "expo-router";
import { useColorScheme } from "react-native";
import { Paragraph } from "tamagui";
export default function TabLayout() {
- const colorScheme = useColorScheme();
+ const colorScheme = useColorScheme();
- return (
-
- (
-
- Actualités
-
- ),
- tabBarIcon: ({ color, size }) => ,
- }}
- />
- (
-
- Sources
-
- ),
- tabBarIcon: ({ color, size }) => ,
- }}
- />
- (
-
- Signets
-
- ),
- tabBarIcon: ({ color, size }) => ,
- }}
- />
- (
-
- Profil
-
- ),
- tabBarIcon: ({ color, size }) => ,
- }}
- />
-
- );
+ return (
+
+ ,
+ tabBarLabel: ({ color }) => (
+
+ Actualités
+
+ ),
+ }}
+ />
+ ,
+ tabBarLabel: ({ color }) => (
+
+ Sources
+
+ ),
+ }}
+ />
+ ,
+ tabBarLabel: ({ color }) => (
+
+ Signets
+
+ ),
+ }}
+ />
+ ,
+ tabBarLabel: ({ color }) => (
+
+ Profil
+
+ ),
+ }}
+ />
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx
index 73ffdbf..ef76f39 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/_layout.tsx
@@ -1,5 +1,5 @@
import { Stack } from "expo-router";
export default function Layout() {
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx
index 2d4317a..82816fc 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/index.tsx
@@ -5,26 +5,26 @@ import { Label, ListItem, ScrollView, Separator, YGroup } from "tamagui";
import { ScreenView } from "@/ui/components/layout";
export default function Index() {
- const router = useRouter();
+ const router = useRouter();
- return (
-
-
+ return (
+
+
-
-
-
-
- router.push("/account/settings")}
- icon={Settings}
- iconAfter={ChevronRight}
- title="Settings"
- />
-
-
-
-
-
- );
+
+
+
+
+ router.push("/account/settings")}
+ title="Settings"
+ />
+
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx
index 9e17bdb..e96e781 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/account/settings/index.tsx
@@ -6,30 +6,30 @@ import { useAuth } from "@/providers/auth-provider";
import { ScreenView } from "@/ui/components/layout";
export default function Index() {
- const authState = useAuth();
- const { mutate, isPending } = useLogout();
+ const authState = useAuth();
+ const { mutate, isPending } = useLogout();
- const handleLogout = async () => {
- mutate(undefined, {
- onSuccess: () => authState.logout(),
- onError: () => authState.logout(),
- });
- };
+ const handleLogout = async () => {
+ mutate(undefined, {
+ onError: () => authState.logout(),
+ onSuccess: () => authState.logout(),
+ });
+ };
- return (
-
-
+ return (
+
+
-
-
-
-
- );
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx
index 0c133bd..0172919 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/[id].tsx
@@ -12,79 +12,84 @@ import { ArticleCategoryPill, ArticleCoverImage } from "@/ui/components/content/
import { SourceReferencePill } from "@/ui/components/content/source";
import { BackButton } from "@/ui/components/controls/BackButton";
import { IconButton } from "@/ui/components/controls/IconButton";
-import { ScreenView } from "@/ui/components/layout";
import { LoadingView } from "@/ui/components/LoadingView";
+import { ScreenView } from "@/ui/components/layout";
import { Caption, Text } from "@/ui/components/typography";
export default function ArticleDetails() {
- const router = useRouter();
- const { id } = useLocalSearchParams();
- const { data, isLoading, error } = useArticleDetails(id as string);
- const article: Article | undefined = data ?? undefined;
- const relativeTime = useRelativeTime(article?.publishedAt);
+ const router = useRouter();
+ const { id } = useLocalSearchParams();
+ const { data, isLoading, error } = useArticleDetails(id as string);
+ const article: Article | undefined = data ?? undefined;
+ const relativeTime = useRelativeTime(article?.publishedAt);
- const handleReadIntegrality = async () => {
- await WebBrowser.openBrowserAsync(article!.link);
- };
+ const handleReadIntegrality = async () => {
+ await WebBrowser.openBrowserAsync(article!.link);
+ };
- if (error) {
- Toast.show({
- type: "error",
- text1: "Erreur",
- text2: safeMessage(error),
- });
- router.replace("/(authed)/(tabs)/articles");
- }
+ if (error) {
+ Toast.show({
+ text1: "Erreur",
+ text2: safeMessage(error),
+ type: "error",
+ });
+ router.replace("/(authed)/(tabs)/articles");
+ }
- if (isLoading || article === undefined) {
- return ;
- }
+ if (isLoading || article === undefined) {
+ return ;
+ }
- return (
-
- router.dismissTo("/(authed)/(tabs)/articles")} />}
- trailingActions={
- <>
- {}} icon={} />
- {}} icon={} />
- {}} icon={} />
- >
- }
+ return (
+
+ router.dismissTo("/(authed)/(tabs)/articles")} />}
+ trailingActions={
+ <>
+ } onPress={() => {}} />
+ } onPress={() => {}} />
+ } onPress={() => {}} />
+ >
+ }
+ />
+
+
+ {article.metadata?.image && (
+
-
-
- {article.metadata?.image && (
-
- )}
-
-
-
- {article.categories.map((category, index) => (
-
- ))}
-
-
- {article.title}
-
+ )}
+
+
+
+ {article.categories.map((category, index) => (
+
+ ))}
+
+
+ {article.title}
+
-
-
-
- {relativeTime}
-
- {article.readingTime} minutes de lecture
-
-
+
+
+
+ {relativeTime}
+
+ {article.readingTime} minutes de lecture
+
+
-
- {article.body.trim()}
-
-
-
-
-
- );
+
+ {article.body.trim()}
+
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx
index 73ffdbf..ef76f39 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/_layout.tsx
@@ -1,5 +1,5 @@
import { Stack } from "expo-router";
export default function Layout() {
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx
index 57e0c49..fb5c8ff 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/index.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { ScrollView, YStack } from "tamagui";
import { useArticleOverviewList } from "@/api/request/feed-management/article";
@@ -13,39 +11,42 @@ import { ScreenView } from "@/ui/components/layout";
import { Heading } from "@/ui/components/typography";
export default function Index() {
- const { data: articles, isLoading: articlesLoading } = useArticleOverviewList({ limit: 10 });
- const { data: sources, isLoading: sourcesLoading } = useSourceOverviewList();
- const articleOverviews: ArticleOverview[] = useFlattenedItems(articles);
- const sourcesOverviews: SourceOverview[] = useFlattenedItems(sources);
+ const { data: articles, isLoading: articlesLoading } = useArticleOverviewList({ limit: 10 });
+ const { data: sources, isLoading: sourcesLoading } = useSourceOverviewList();
+ const articleOverviews: ArticleOverview[] = useFlattenedItems(articles);
+ const sourcesOverviews: SourceOverview[] = useFlattenedItems(sources);
- return (
-
- Actualités
-
-
-
-
+ return (
+
+ Actualités
+
+
+
+
- {articlesLoading && }
- {!articlesLoading && (
-
- )}
-
-
-
+ {articlesLoading && }
+ {!articlesLoading && (
+
+ )}
+
+
+
- {sourcesLoading && }
- {!sourcesLoading && (
-
- )}
-
-
-
-
- );
+ {sourcesLoading && }
+ {!sourcesLoading && (
+
+ )}
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx
index dd727f1..fd84583 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/articles/trending.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { useRouter } from "expo-router";
import { useInfiniteArticleOverviewList } from "@/api/request/feed-management/article";
@@ -10,31 +8,30 @@ import { BackButton } from "@/ui/components/controls/BackButton";
import { ScreenView } from "@/ui/components/layout";
export default function Trending() {
- const router = useRouter();
- const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } = useInfiniteArticleOverviewList(
- { limit: 20 }
- );
- const articles: TrendingArticle[] = useFlattenedItems(data);
+ const router = useRouter();
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } =
+ useInfiniteArticleOverviewList({ limit: 20 });
+ const articles: TrendingArticle[] = useFlattenedItems(data);
- return (
-
- router.dismissTo("/(authed)/(tabs)/articles")} />}
- title="Actualités"
- />
+ return (
+
+ router.dismissTo("/(authed)/(tabs)/articles")} />}
+ title="Actualités"
+ />
- {isLoading && }
- {!isLoading && (
-
- )}
-
- );
+ {isLoading && }
+ {!isLoading && (
+
+ )}
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx
index 42de48c..25cef7a 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/[id].tsx
@@ -5,14 +5,14 @@ import { ScreenView } from "@/ui/components/layout";
import { Heading } from "@/ui/components/typography";
export default function Details() {
- const { id } = useLocalSearchParams();
- // const { data, isLoading } = useBookmarkedArticlesList(id as string);
- // const articles: BookmarkedArticle[] = useFlattenedItems(data);
+ const { id } = useLocalSearchParams();
+ // const { data, isLoading } = useBookmarkedArticlesList(id as string);
+ // const articles: BookmarkedArticle[] = useFlattenedItems(data);
- return (
-
- Bookmark Infos
- {id}
-
- );
+ return (
+
+ Bookmark Infos
+ {id}
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx
index 73ffdbf..ef76f39 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/_layout.tsx
@@ -1,5 +1,5 @@
import { Stack } from "expo-router";
export default function Layout() {
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx
index 7a53c97..981318b 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/bookmarks/index.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Plus, Search } from "@tamagui/lucide-icons";
import { YStack } from "tamagui";
@@ -8,35 +6,36 @@ import { Bookmark } from "@/api/schema/feed-management/bookmark";
import { useFlattenedItems } from "@/hooks/use-flattened-items";
import { BookmarkList } from "@/ui/components/content/bookmark";
import { IconButton } from "@/ui/components/controls/IconButton";
-import { ScreenView } from "@/ui/components/layout";
import { LoadingView } from "@/ui/components/LoadingView";
+import { ScreenView } from "@/ui/components/layout";
export default function Index() {
- const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } = useBookmarkList();
- const bookmarks: Bookmark[] = useFlattenedItems(data);
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } =
+ useBookmarkList();
+ const bookmarks: Bookmark[] = useFlattenedItems(data);
- return (
-
- {}} icon={} />}
- trailingActions={ {}} icon={} />}
- />
+ return (
+
+ } onPress={() => {}} />}
+ title="Bookmarks"
+ trailingActions={} onPress={() => {}} />}
+ />
-
- {isLoading && }
- {!isLoading && (
-
- )}
-
-
- );
+
+ {isLoading && }
+ {!isLoading && (
+
+ )}
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx
index ab09f1e..da3c2d1 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/[name].tsx
@@ -4,12 +4,12 @@ import { ScreenView } from "@/ui/components/layout";
import { Heading, Text } from "@/ui/components/typography";
export default function SourceDetails() {
- const { name } = useLocalSearchParams();
+ const { name } = useLocalSearchParams();
- return (
-
- Source Details
- {name}
-
- );
+ return (
+
+ Source Details
+ {name}
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx
index 73ffdbf..ef76f39 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/_layout.tsx
@@ -1,5 +1,5 @@
import { Stack } from "expo-router";
export default function Layout() {
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx
index 272a345..1f5ebe3 100644
--- a/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/(tabs)/sources/index.tsx
@@ -5,15 +5,15 @@ import { SourceList, SourceSkeletonList } from "@/ui/components/content/source";
import { ScreenView } from "@/ui/components/layout";
export default function Sources() {
- const { data, isLoading } = useSourceOverviewList();
- const sources: SourceOverview[] = useFlattenedItems(data);
+ const { data, isLoading } = useSourceOverviewList();
+ const sources: SourceOverview[] = useFlattenedItems(data);
- return (
-
-
+ return (
+
+
- {isLoading && }
- {!isLoading && }
-
- );
+ {isLoading && }
+ {!isLoading && }
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(authed)/_layout.tsx b/apps/mobile-legacy/src/app/(authed)/_layout.tsx
index 5269578..21df812 100644
--- a/apps/mobile-legacy/src/app/(authed)/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(authed)/_layout.tsx
@@ -3,15 +3,15 @@ import { Redirect, Stack } from "expo-router";
import { useAuth } from "@/providers/auth-provider";
export default function AuthedLayout() {
- const auth = useAuth();
+ const auth = useAuth();
- if (!auth.isReady) {
- return null;
- }
+ if (!auth.isReady) {
+ return null;
+ }
- if (!auth.isLoggedIn) {
- return ;
- }
+ if (!auth.isLoggedIn) {
+ return ;
+ }
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx b/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx
index a524f81..b12aa2d 100644
--- a/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx
+++ b/apps/mobile-legacy/src/app/(unauthed)/_layout.tsx
@@ -3,15 +3,15 @@ import { Redirect, Stack } from "expo-router";
import { useAuth } from "@/providers/auth-provider";
export default function AuthedLayout() {
- const auth = useAuth();
+ const auth = useAuth();
- if (!auth.isReady) {
- return null;
- }
+ if (!auth.isReady) {
+ return null;
+ }
- if (auth.isLoggedIn) {
- return ;
- }
+ if (auth.isLoggedIn) {
+ return ;
+ }
- return ;
+ return ;
}
diff --git a/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx b/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx
index a249d18..fb7cf32 100644
--- a/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx
+++ b/apps/mobile-legacy/src/app/(unauthed)/password-request.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { joiResolver } from "@hookform/resolvers/joi";
import { Link, useRouter } from "expo-router";
import { useForm } from "react-hook-form";
@@ -7,7 +5,10 @@ import Toast from "react-native-toast-message";
import { YStack } from "tamagui";
import { usePasswordForgotten } from "@/api/request/identity-and-access/password";
-import { RequestPasswordPayload, RequestPasswordPayloadSchema } from "@/api/schema/identity-and-access/password";
+import {
+ RequestPasswordPayload,
+ RequestPasswordPayloadSchema,
+} from "@/api/schema/identity-and-access/password";
import { ErrorResponse, safeMessage } from "@/api/shared";
import { FormEmailInput } from "@/ui/components/controls/forms";
import { SubmitButton } from "@/ui/components/controls/SubmitButton";
@@ -15,55 +16,56 @@ import { ScreenView } from "@/ui/components/layout";
import { Heading, Text } from "@/ui/components/typography";
export default function PasswordRequest() {
- const { mutate, isPending } = usePasswordForgotten();
- const router = useRouter();
+ const { mutate, isPending } = usePasswordForgotten();
+ const router = useRouter();
- const { control, handleSubmit, formState } = useForm({
- resolver: joiResolver(RequestPasswordPayloadSchema),
- });
+ const { control, handleSubmit, formState } = useForm({
+ resolver: joiResolver(RequestPasswordPayloadSchema),
+ });
- const onSubmit = (data: RequestPasswordPayload) => {
- mutate(data, {
- onSuccess: () => {
- Toast.show({
- text1: "Succès",
- text2: "Un mail avec les instructions vous a été envoyé",
- type: "success",
- });
- router.push("/(unauthed)/signin");
- },
- onError: (error: ErrorResponse) => {
- Toast.show({
- text1: "Erreur de connexion",
- text2: safeMessage(error),
- type: "error",
- });
- },
+ const onSubmit = (data: RequestPasswordPayload) => {
+ mutate(data, {
+ onError: (error: ErrorResponse) => {
+ Toast.show({
+ text1: "Erreur de connexion",
+ text2: safeMessage(error),
+ type: "error",
});
- };
+ },
+ onSuccess: () => {
+ Toast.show({
+ text1: "Succès",
+ text2: "Un mail avec les instructions vous a été envoyé",
+ type: "success",
+ });
+ router.push("/(unauthed)/signin");
+ },
+ });
+ };
- return (
-
-
-
- Mot de passe oublié ?
-
- Veuillez entrer votre adresse e-mail pour recevoir un lien de réinitialisation de mot de passe.
-
-
+ return (
+
+
+
+ Mot de passe oublié ?
+
+ Veuillez entrer votre adresse e-mail pour recevoir un lien de réinitialisation de mot de
+ passe.
+
+
-
+
-
- Vous avez pas de compte ? Se connecter
-
-
-
-
- );
+
+ Vous avez pas de compte ? Se connecter
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(unauthed)/signin.tsx b/apps/mobile-legacy/src/app/(unauthed)/signin.tsx
index 176517b..a137a74 100644
--- a/apps/mobile-legacy/src/app/(unauthed)/signin.tsx
+++ b/apps/mobile-legacy/src/app/(unauthed)/signin.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { joiResolver } from "@hookform/resolvers/joi";
import { Link, useRouter } from "expo-router";
import { useForm } from "react-hook-form";
@@ -7,7 +5,11 @@ import Toast from "react-native-toast-message";
import { YStack } from "tamagui";
import { useLogin } from "@/api/request/identity-and-access/login";
-import { LoginPayload, LoginPayloadSchema, LoginResponse } from "@/api/schema/identity-and-access/login";
+import {
+ LoginPayload,
+ LoginPayloadSchema,
+ LoginResponse,
+} from "@/api/schema/identity-and-access/login";
import { ErrorResponse, safeMessage } from "@/api/shared";
import { useAuth } from "@/providers/auth-provider";
import { FormEmailInput, FormPasswordInput } from "@/ui/components/controls/forms";
@@ -16,66 +18,66 @@ import { ScreenView } from "@/ui/components/layout";
import { Caption, Heading, Text } from "@/ui/components/typography";
export default function SignIn() {
- const { mutate, isPending } = useLogin();
- const auth = useAuth();
- const router = useRouter();
+ const { mutate, isPending } = useLogin();
+ const auth = useAuth();
+ const router = useRouter();
- if (auth.isLoggedIn) {
- router.replace("/(authed)/(tabs)/articles");
- }
+ if (auth.isLoggedIn) {
+ router.replace("/(authed)/(tabs)/articles");
+ }
- const { control, handleSubmit, formState } = useForm({
- resolver: joiResolver(LoginPayloadSchema),
- });
+ const { control, handleSubmit, formState } = useForm({
+ resolver: joiResolver(LoginPayloadSchema),
+ });
- const onSubmit = (data: LoginPayload) => {
- mutate(data, {
- onSuccess: async (data: LoginResponse) => {
- auth.login(data.token, data.refresh_token);
- Toast.show({ text1: "Connexion réussie", type: "success" });
- },
- onError: (error: ErrorResponse) => {
- Toast.show({
- text1: "Erreur de connexion",
- text2: safeMessage(error),
- type: "error",
- });
- },
+ const onSubmit = (data: LoginPayload) => {
+ mutate(data, {
+ onError: (error: ErrorResponse) => {
+ Toast.show({
+ text1: "Erreur de connexion",
+ text2: safeMessage(error),
+ type: "error",
});
- };
+ },
+ onSuccess: async (data: LoginResponse) => {
+ auth.login(data.token, data.refresh_token);
+ Toast.show({ text1: "Connexion réussie", type: "success" });
+ },
+ });
+ };
- return (
-
-
-
- Connexion
- Bienvenue sur Basango, la plateforme d'actualités intelligente
-
+ return (
+
+
+
+ Connexion
+ Bienvenue sur Basango, la plateforme d'actualités intelligente
+
-
-
-
-
-
- Mot de passe oublié ?
-
-
-
+
+
+
+
+
+ Mot de passe oublié ?
+
+
+
-
- En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez avoir lu
- notre politique de confidentialité.
-
-
- Vous n'avez pas de compte ? Créer un compte
-
-
-
-
- );
+
+ En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez
+ avoir lu notre politique de confidentialité.
+
+
+ Vous n'avez pas de compte ? Créer un compte
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(unauthed)/signup.tsx b/apps/mobile-legacy/src/app/(unauthed)/signup.tsx
index 02fd6b1..18aeb52 100644
--- a/apps/mobile-legacy/src/app/(unauthed)/signup.tsx
+++ b/apps/mobile-legacy/src/app/(unauthed)/signup.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { joiResolver } from "@hookform/resolvers/joi";
import { User } from "@tamagui/lucide-icons";
import { Link, useRouter } from "expo-router";
@@ -16,66 +14,66 @@ import { ScreenView } from "@/ui/components/layout";
import { Caption, Heading, Text } from "@/ui/components/typography";
export default function SingUp() {
- const router = useRouter();
- const { mutate, isPending } = useRegister();
+ const router = useRouter();
+ const { mutate, isPending } = useRegister();
- const { control, handleSubmit, formState } = useForm({
- resolver: joiResolver(RegisterPayloadSchema),
- });
+ const { control, handleSubmit, formState } = useForm({
+ resolver: joiResolver(RegisterPayloadSchema),
+ });
- const onSubmit = (data: RegisterPayload) => {
- mutate(data, {
- onSuccess: () => {
- Toast.show({
- text1: "Félicitations !",
- text2: "les détails de votre compte vous ont été envoyés par e-mail.",
- type: "success",
- });
- router.replace("/(unauthed)/signin");
- },
- onError: (error: ErrorResponse) => {
- Toast.show({
- text1: "Erreur",
- text2: safeMessage(error),
- type: "error",
- });
- },
+ const onSubmit = (data: RegisterPayload) => {
+ mutate(data, {
+ onError: (error: ErrorResponse) => {
+ Toast.show({
+ text1: "Erreur",
+ text2: safeMessage(error),
+ type: "error",
});
- };
+ },
+ onSuccess: () => {
+ Toast.show({
+ text1: "Félicitations !",
+ text2: "les détails de votre compte vous ont été envoyés par e-mail.",
+ type: "success",
+ });
+ router.replace("/(unauthed)/signin");
+ },
+ });
+ };
- return (
-
-
-
- Inscription
- Rejoignez la communauté Basango et restez informé des dernières actualités
-
+ return (
+
+
+
+ Inscription
+ Rejoignez la communauté Basango et restez informé des dernières actualités
+
-
-
-
-
-
-
- En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez avoir lu
- notre politique de confidentialité.
-
-
- Vous avez un compte ? Connectez-vous
-
-
-
-
- );
+
+
+
+
+
+
+ En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez
+ avoir lu notre politique de confidentialité.
+
+
+ Vous avez un compte ? Connectez-vous
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx b/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx
index e14c3b5..2b9a34e 100644
--- a/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx
+++ b/apps/mobile-legacy/src/app/(unauthed)/welcome.tsx
@@ -6,34 +6,34 @@ import { ScreenView } from "@/ui/components/layout";
import { Caption, Display, Text } from "@/ui/components/typography";
export default function Welcome() {
- const router = useRouter();
+ const router = useRouter();
- return (
-
-
-
-
- Bienvenue sur Basango
-
- La première plateforme d'actualités intelligente qui vous aide à rester informé sur
- congolaise et internationale.
-
-
+ return (
+
+
+
+
+ Bienvenue sur Basango
+
+ La première plateforme d'actualités intelligente qui vous aide à rester informé sur
+ congolaise et internationale.
+
+
-
-
-
- Ouvrir un compte
-
-
+
+
+
+ Ouvrir un compte
+
+
-
- En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez avoir lu
- notre politique de confidentialité.
-
-
-
- );
+
+ En continuant, vous acceptez les conditions d'utilisation de Basango et reconnaissez
+ avoir lu notre politique de confidentialité.
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/+not-found.tsx b/apps/mobile-legacy/src/app/+not-found.tsx
index 2be952e..bff11e6 100644
--- a/apps/mobile-legacy/src/app/+not-found.tsx
+++ b/apps/mobile-legacy/src/app/+not-found.tsx
@@ -6,28 +6,28 @@ import { ScreenView } from "@/ui/components/layout";
import { Heading, Text } from "@/ui/components/typography";
export default function NotFoundScreen() {
- return (
-
-
-
-
-
-
-
-
- Une erreur s'est produite
-
-
- Nous avons une difficulté à charger la page que vous recherchez.
-
-
+ return (
+
+
+
+
+
+
+
+
+ Une erreur s'est produite
+
+
+ Nous avons une difficulté à charger la page que vous recherchez.
+
+
-
- Recommencer
-
-
-
-
-
- );
+
+ Recommencer
+
+
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/app/_layout.tsx b/apps/mobile-legacy/src/app/_layout.tsx
index 0a4f33a..2dd39c3 100644
--- a/apps/mobile-legacy/src/app/_layout.tsx
+++ b/apps/mobile-legacy/src/app/_layout.tsx
@@ -1,7 +1,6 @@
-import React from "react";
-
import * as Sentry from "@sentry/react-native";
import { Stack } from "expo-router";
+import React from "react";
import { useColorScheme } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Toast from "react-native-toast-message";
@@ -12,28 +11,28 @@ import { RootProviders } from "@/providers/root-providers";
export { ErrorBoundary } from "expo-router";
Sentry.init({
- dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
- sendDefaultPii: true,
- debug: __DEV__,
- tracesSampleRate: 1.0,
- tracePropagationTargets: [/.*?/],
- spotlight: __DEV__,
+ debug: __DEV__,
+ dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
+ sendDefaultPii: true,
+ spotlight: __DEV__,
+ tracePropagationTargets: [/.*?/],
+ tracesSampleRate: 1.0,
});
function RootLayout() {
- const colorScheme = useColorScheme();
- const insets = useSafeAreaInsets();
+ const colorScheme = useColorScheme();
+ const insets = useSafeAreaInsets();
- return (
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ );
}
export default Sentry.wrap(RootLayout);
diff --git a/apps/mobile-legacy/src/app/index.tsx b/apps/mobile-legacy/src/app/index.tsx
index 108aa32..ff00fb1 100644
--- a/apps/mobile-legacy/src/app/index.tsx
+++ b/apps/mobile-legacy/src/app/index.tsx
@@ -3,11 +3,15 @@ import { Redirect } from "expo-router";
import { useAuth } from "@/providers/auth-provider";
export default function Index() {
- const auth = useAuth();
+ const auth = useAuth();
- if (!auth.isReady) {
- return null;
- }
+ if (!auth.isReady) {
+ return null;
+ }
- return auth.isLoggedIn ? : ;
+ return auth.isLoggedIn ? (
+
+ ) : (
+
+ );
}
diff --git a/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx b/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx
index d0c9dc5..34a86ea 100644
--- a/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx
+++ b/apps/mobile-legacy/src/assets/illustrations/BookmarkIllustration.tsx
@@ -1,5 +1,3 @@
-import * as React from "react";
-
import Svg, { Circle, G, Path, Rect, SvgProps } from "react-native-svg";
/**
@@ -8,302 +6,314 @@ import Svg, { Circle, G, Path, Rect, SvgProps } from "react-native-svg";
* @constructor
*/
export default function BookmarkIllustration(props: SvgProps) {
- return (
-
- );
+ return (
+
+ );
}
diff --git a/apps/mobile-legacy/src/hooks/use-flattened-items.ts b/apps/mobile-legacy/src/hooks/use-flattened-items.ts
index fd59b7b..4b9e5ce 100644
--- a/apps/mobile-legacy/src/hooks/use-flattened-items.ts
+++ b/apps/mobile-legacy/src/hooks/use-flattened-items.ts
@@ -1,26 +1,26 @@
import { useMemo } from "react";
interface Page {
- items: T[];
+ items: T[];
}
interface PaginatedResult {
- pages?: Page[];
- items?: T[];
+ pages?: Page[];
+ items?: T[];
}
export const useFlattenedItems = (data: PaginatedResult | undefined | null): T[] => {
- return useMemo((): T[] => {
- if (!data) {
- return [];
- }
+ return useMemo((): T[] => {
+ if (!data) {
+ return [];
+ }
- if (data.pages && Array.isArray(data.pages) && data.pages.length > 0) {
- return data.pages.flatMap(page => page.items || []);
- } else if (data.items && Array.isArray(data.items)) {
- return data.items;
- } else {
- return [];
- }
- }, [data]);
+ if (data.pages && Array.isArray(data.pages) && data.pages.length > 0) {
+ return data.pages.flatMap((page) => page.items || []);
+ } else if (data.items && Array.isArray(data.items)) {
+ return data.items;
+ } else {
+ return [];
+ }
+ }, [data]);
};
diff --git a/apps/mobile-legacy/src/hooks/use-relative-time.ts b/apps/mobile-legacy/src/hooks/use-relative-time.ts
index 6d09007..03e8f73 100644
--- a/apps/mobile-legacy/src/hooks/use-relative-time.ts
+++ b/apps/mobile-legacy/src/hooks/use-relative-time.ts
@@ -1,61 +1,60 @@
-import { useEffect, useState } from "react";
-
import { formatDistanceToNowStrict, Locale } from "date-fns";
import { fr } from "date-fns/locale";
+import { useEffect, useState } from "react";
export const useRelativeTime = (
- dateInput: string | Date | number | null | undefined,
- options?: {
- addSuffix?: boolean;
- unit?: "second" | "minute" | "hour" | "day" | "month" | "year";
- locale?: Locale;
- roundingMethod?: "floor" | "ceil" | "round";
- includeSeconds?: boolean;
- },
- updateInterval: number = 60000
+ dateInput: string | Date | number | null | undefined,
+ options?: {
+ addSuffix?: boolean;
+ unit?: "second" | "minute" | "hour" | "day" | "month" | "year";
+ locale?: Locale;
+ roundingMethod?: "floor" | "ceil" | "round";
+ includeSeconds?: boolean;
+ },
+ updateInterval: number = 60000,
): string => {
- const [relativeTime, setRelativeTime] = useState("");
+ const [relativeTime, setRelativeTime] = useState("");
- useEffect(() => {
- if (dateInput === null || dateInput === undefined) {
- setRelativeTime("");
- return;
- }
+ useEffect(() => {
+ if (dateInput === null || dateInput === undefined) {
+ setRelativeTime("");
+ return;
+ }
- const date = new Date(dateInput);
+ const date = new Date(dateInput);
- // Check if the date is valid
- if (isNaN(date.getTime())) {
- setRelativeTime("Invalid Date");
- return;
- }
+ // Check if the date is valid
+ if (Number.isNaN(date.getTime())) {
+ setRelativeTime("Invalid Date");
+ return;
+ }
- const updateTime = () => {
- // Default options if none provided, ensures suffix is added
- const effectiveOptions = {
- locale: fr,
- addSuffix: true,
- ...options,
- };
+ const updateTime = () => {
+ // Default options if none provided, ensures suffix is added
+ const effectiveOptions = {
+ addSuffix: true,
+ locale: fr,
+ ...options,
+ };
- try {
- const formattedTime = formatDistanceToNowStrict(date, effectiveOptions);
- setRelativeTime(formattedTime);
- } catch (error) {
- console.error("Error formatting relative time:", error);
- setRelativeTime(dateInput.toString()); // Handle potential errors during formatting
- }
- };
+ try {
+ const formattedTime = formatDistanceToNowStrict(date, effectiveOptions);
+ setRelativeTime(formattedTime);
+ } catch (error) {
+ console.error("Error formatting relative time:", error);
+ setRelativeTime(dateInput.toString()); // Handle potential errors during formatting
+ }
+ };
- // Initial update
- updateTime();
+ // Initial update
+ updateTime();
- // Set up interval for periodic updates
- const intervalId = setInterval(updateTime, updateInterval);
+ // Set up interval for periodic updates
+ const intervalId = setInterval(updateTime, updateInterval);
- // Clean up the interval when the component unmounts or dateInput changes
- return () => clearInterval(intervalId);
- }, [dateInput, options, updateInterval]);
+ // Clean up the interval when the component unmounts or dateInput changes
+ return () => clearInterval(intervalId);
+ }, [dateInput, options, updateInterval]);
- return relativeTime;
+ return relativeTime;
};
diff --git a/apps/mobile-legacy/src/providers/auth-provider.tsx b/apps/mobile-legacy/src/providers/auth-provider.tsx
index d365bb5..5aa7d82 100644
--- a/apps/mobile-legacy/src/providers/auth-provider.tsx
+++ b/apps/mobile-legacy/src/providers/auth-provider.tsx
@@ -1,86 +1,88 @@
+import { SplashScreen, useRouter } from "expo-router";
import React, { createContext, useContext, useEffect, useState } from "react";
-import { useRouter, SplashScreen } from "expo-router";
-
-import { clearTokens, setTokens, getAccessToken, getRefreshToken } from "@/store/auth";
+import { clearTokens, getAccessToken, getRefreshToken, setTokens } from "@/store/auth";
SplashScreen.preventAutoHideAsync();
type AuthState = {
- isReady: boolean;
- isLoggedIn: boolean;
- login: (accessToken: string, refreshToken: string) => void;
- logout: () => void;
- accessToken: string | null;
- refreshToken: string | null;
+ isReady: boolean;
+ isLoggedIn: boolean;
+ login: (accessToken: string, refreshToken: string) => void;
+ logout: () => void;
+ accessToken: string | null;
+ refreshToken: string | null;
};
const AuthContext = createContext({
- isReady: false,
- isLoggedIn: false,
- login: () => {},
- logout: () => {},
- accessToken: null,
- refreshToken: null,
+ accessToken: null,
+ isLoggedIn: false,
+ isReady: false,
+ login: () => {},
+ logout: () => {},
+ refreshToken: null,
});
export function useAuth() {
- return useContext(AuthContext);
+ return useContext(AuthContext);
}
export function AuthProvider({ children }: React.PropsWithChildren) {
- const [isReady, setIsReady] = useState(false);
- const [accessToken, setAccessToken] = useState(null);
- const [refreshToken, setRefreshToken] = useState(null);
- const router = useRouter();
+ const [isReady, setIsReady] = useState(false);
+ const [accessToken, setAccessToken] = useState(null);
+ const [refreshToken, setRefreshToken] = useState(null);
+ const router = useRouter();
- const isLoggedIn = !!(accessToken && refreshToken);
+ const isLoggedIn = !!(accessToken && refreshToken);
- const login = (access: string, refresh: string) => {
- setAccessToken(access);
- setRefreshToken(refresh);
- setTokens(access, refresh);
- router.replace("/(authed)/(tabs)/articles");
+ const login = (access: string, refresh: string) => {
+ setAccessToken(access);
+ setRefreshToken(refresh);
+ setTokens(access, refresh);
+ router.replace("/(authed)/(tabs)/articles");
+ };
+
+ const logout = () => {
+ setAccessToken(null);
+ setRefreshToken(null);
+ clearTokens();
+ router.replace("/signin");
+ };
+
+ useEffect(() => {
+ const loadTokens = async () => {
+ try {
+ const [storedAccess, storedRefresh] = await Promise.all([
+ getAccessToken(),
+ getRefreshToken(),
+ ]);
+
+ if (storedAccess && storedRefresh) {
+ setAccessToken(storedAccess);
+ setRefreshToken(storedRefresh);
+ }
+ } catch (error) {
+ console.error("Unable to retrieve auth tokens", error);
+ } finally {
+ setIsReady(true);
+ await SplashScreen.hideAsync();
+ }
};
+ loadTokens();
+ }, []);
- const logout = () => {
- setAccessToken(null);
- setRefreshToken(null);
- clearTokens();
- router.replace("/signin");
- };
-
- useEffect(() => {
- const loadTokens = async () => {
- try {
- const [storedAccess, storedRefresh] = await Promise.all([getAccessToken(), getRefreshToken()]);
-
- if (storedAccess && storedRefresh) {
- setAccessToken(storedAccess);
- setRefreshToken(storedRefresh);
- }
- } catch (error) {
- console.error("Unable to retrieve auth tokens", error);
- } finally {
- setIsReady(true);
- await SplashScreen.hideAsync();
- }
- };
- loadTokens();
- }, []);
-
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
}
diff --git a/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx b/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx
index 3060351..3ca164c 100644
--- a/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx
+++ b/apps/mobile-legacy/src/providers/fonts-loader-provider.tsx
@@ -1,7 +1,23 @@
+import {
+ Inter_100Thin,
+ Inter_200ExtraLight,
+ Inter_300Light,
+ Inter_400Regular,
+ Inter_500Medium,
+ Inter_600SemiBold,
+ Inter_700Bold,
+ Inter_800ExtraBold,
+ Inter_900Black,
+ useFonts,
+} from "@expo-google-fonts/inter";
+import { SplashScreen } from "expo-router";
import type React from "react";
import { useEffect } from "react";
-import {
+SplashScreen.preventAutoHideAsync();
+
+export const FontsLoaderProvider = ({ children }: React.PropsWithChildren) => {
+ const [fontsLoaded, fontError] = useFonts({
Inter_100Thin,
Inter_200ExtraLight,
Inter_300Light,
@@ -11,34 +27,17 @@ import {
Inter_700Bold,
Inter_800ExtraBold,
Inter_900Black,
- useFonts,
-} from "@expo-google-fonts/inter";
-import { SplashScreen } from "expo-router";
+ });
-SplashScreen.preventAutoHideAsync();
-
-export const FontsLoaderProvider = ({ children }: React.PropsWithChildren) => {
- const [fontsLoaded, fontError] = useFonts({
- Inter_100Thin,
- Inter_200ExtraLight,
- Inter_300Light,
- Inter_400Regular,
- Inter_500Medium,
- Inter_600SemiBold,
- Inter_700Bold,
- Inter_800ExtraBold,
- Inter_900Black,
- });
-
- useEffect(() => {
- if (fontsLoaded || fontError) {
- SplashScreen.hideAsync();
- }
- }, [fontsLoaded, fontError]);
-
- if (!fontsLoaded && !fontError) {
- return null;
+ useEffect(() => {
+ if (fontsLoaded || fontError) {
+ SplashScreen.hideAsync();
}
+ }, [fontsLoaded, fontError]);
- return <>{children}>;
+ if (!fontsLoaded && !fontError) {
+ return null;
+ }
+
+ return <>{children}>;
};
diff --git a/apps/mobile-legacy/src/providers/network-provider.tsx b/apps/mobile-legacy/src/providers/network-provider.tsx
index 73f8b0d..cc8199a 100644
--- a/apps/mobile-legacy/src/providers/network-provider.tsx
+++ b/apps/mobile-legacy/src/providers/network-provider.tsx
@@ -1,42 +1,41 @@
-import React, { createContext, useContext, useEffect, useState } from "react";
-
import * as Network from "expo-network";
import { NetworkStateEvent } from "expo-network";
+import React, { createContext, useContext, useEffect, useState } from "react";
type NetworkState = {
- isConnected: boolean;
+ isConnected: boolean;
};
const NetworkContext = createContext({
- isConnected: true,
+ isConnected: true,
});
export const useNetwork = () => useContext(NetworkContext);
export const NetworkProvider = ({ children }: React.PropsWithChildren) => {
- const [isConnected, setIsConnected] = useState(true);
+ const [isConnected, setIsConnected] = useState(true);
- useEffect(() => {
- let subscription: { remove: () => any };
+ useEffect(() => {
+ let subscription: { remove: () => any };
- const subscribeToNetworkChanges = async () => {
- const state = await Network.getNetworkStateAsync();
- updateConnection(state);
+ const subscribeToNetworkChanges = async () => {
+ const state = await Network.getNetworkStateAsync();
+ updateConnection(state);
- subscription = Network.addNetworkStateListener(updateConnection);
- };
+ subscription = Network.addNetworkStateListener(updateConnection);
+ };
- const updateConnection = (state: NetworkStateEvent) => {
- const connected = state.isConnected && state.isInternetReachable === true;
- setIsConnected(connected === undefined ? false : connected);
- };
+ const updateConnection = (state: NetworkStateEvent) => {
+ const connected = state.isConnected && state.isInternetReachable === true;
+ setIsConnected(connected === undefined ? false : connected);
+ };
- subscribeToNetworkChanges();
+ subscribeToNetworkChanges();
- return () => {
- subscription && subscription.remove();
- };
- }, []);
+ return () => {
+ subscription?.remove();
+ };
+ }, []);
- return {children};
+ return {children};
};
diff --git a/apps/mobile-legacy/src/providers/root-providers.tsx b/apps/mobile-legacy/src/providers/root-providers.tsx
index b9f312a..f2ca6a8 100644
--- a/apps/mobile-legacy/src/providers/root-providers.tsx
+++ b/apps/mobile-legacy/src/providers/root-providers.tsx
@@ -10,17 +10,17 @@ import { TamaguiConfigProvider } from "@/providers/tamagui-config-provider";
import { TanstackQueryProvider } from "@/providers/tanstack-query-provider";
export const RootProviders = ({ children }: React.PropsWithChildren) => (
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
);
diff --git a/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx b/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx
index a0b7709..76df54f 100644
--- a/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx
+++ b/apps/mobile-legacy/src/providers/tamagui-config-provider.tsx
@@ -5,5 +5,5 @@ import { TamaguiProvider } from "tamagui";
import { config } from "~/tamagui.config";
export const TamaguiConfigProvider = ({ children }: React.PropsWithChildren) => (
- {children}
+ {children}
);
diff --git a/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx b/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx
index 83eae1b..7a10949 100644
--- a/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx
+++ b/apps/mobile-legacy/src/providers/tanstack-query-provider.tsx
@@ -1,9 +1,8 @@
-import type React from "react";
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import type React from "react";
export const queryClient = new QueryClient();
export const TanstackQueryProvider = ({ children }: React.PropsWithChildren) => (
- {children}
+ {children}
);
diff --git a/apps/mobile-legacy/src/store/auth.ts b/apps/mobile-legacy/src/store/auth.ts
index ad71463..9febd98 100644
--- a/apps/mobile-legacy/src/store/auth.ts
+++ b/apps/mobile-legacy/src/store/auth.ts
@@ -4,24 +4,24 @@ export const getAccessToken = () => SecureStore.getItemAsync("user_access_token"
export const getRefreshToken = () => SecureStore.getItemAsync("user_refresh_token");
export const setTokens = async (access: string, refresh: string) => {
- try {
- await Promise.all([
- SecureStore.setItemAsync("user_access_token", access),
- SecureStore.setItemAsync("user_refresh_token", refresh),
- ]);
- } catch (error) {
- console.log(access, refresh);
- console.error("Unable to save auth tokens", error);
- }
+ try {
+ await Promise.all([
+ SecureStore.setItemAsync("user_access_token", access),
+ SecureStore.setItemAsync("user_refresh_token", refresh),
+ ]);
+ } catch (error) {
+ console.log(access, refresh);
+ console.error("Unable to save auth tokens", error);
+ }
};
export const clearTokens = async () => {
- try {
- await Promise.all([
- SecureStore.deleteItemAsync("user_access_token"),
- SecureStore.deleteItemAsync("user_refresh_token"),
- ]);
- } catch (error) {
- console.error("Unable to clear auth tokens", error);
- }
+ try {
+ await Promise.all([
+ SecureStore.deleteItemAsync("user_access_token"),
+ SecureStore.deleteItemAsync("user_refresh_token"),
+ ]);
+ } catch (error) {
+ console.error("Unable to clear auth tokens", error);
+ }
};
diff --git a/apps/mobile-legacy/src/ui/components/AppIcon.tsx b/apps/mobile-legacy/src/ui/components/AppIcon.tsx
index 574871d..9326652 100644
--- a/apps/mobile-legacy/src/ui/components/AppIcon.tsx
+++ b/apps/mobile-legacy/src/ui/components/AppIcon.tsx
@@ -1,20 +1,20 @@
import { Image } from "tamagui";
type AppLogoProps = {
- width?: number;
- height?: number;
+ width?: number;
+ height?: number;
};
export const AppIcon = (props: AppLogoProps) => {
- const { width = 80, height = 80 } = props;
+ const { width = 80, height = 80 } = props;
- return (
-
- );
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/LoadingView.tsx b/apps/mobile-legacy/src/ui/components/LoadingView.tsx
index 4faa99d..7bfb953 100644
--- a/apps/mobile-legacy/src/ui/components/LoadingView.tsx
+++ b/apps/mobile-legacy/src/ui/components/LoadingView.tsx
@@ -4,8 +4,15 @@ import { View } from "tamagui";
import { Caption } from "@/ui/components/typography";
export const LoadingView = () => (
-
-
- Chargement...
-
+
+
+ Chargement...
+
);
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx
index cecbbc4..f00f648 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleCategoryPill.tsx
@@ -1,13 +1,11 @@
-import React from "react";
-
import { Caption } from "@/ui/components/typography";
type ArticleCategoryPillProps = {
- category: string;
+ category: string;
};
export const ArticleCategoryPill = (props: ArticleCategoryPillProps) => {
- const { category } = props;
+ const { category } = props;
- return {category};
+ return {category};
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx
index 42f465e..ce38a0d 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleCoverImage.tsx
@@ -1,19 +1,21 @@
import { GetProps, Image, styled } from "tamagui";
const StyledImage = styled(Image, {
- borderRadius: "$4",
- backgroundColor: "$gray3",
- objectFit: "cover",
+ backgroundColor: "$gray3",
+ borderRadius: "$4",
+ objectFit: "cover",
});
type ArticleCoverImageProps = GetProps & {
- uri: string;
- width: string | number;
- height: number;
+ uri: string;
+ width: string | number;
+ height: number;
};
export const ArticleCoverImage = (props: ArticleCoverImageProps) => {
- const { width, height, uri, ...rest } = props;
+ const { width, height, uri, ...rest } = props;
- return ;
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx
index 1654613..50e0dcb 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleList.tsx
@@ -15,97 +15,97 @@ const HorizontalSeparator = () => ;
const VerticalSeparator = () => ;
const LoadingIndicator = () => (
- <>
-
-
-
- >
+ <>
+
+
+
+ >
);
export type ArticleListDisplayMode = "card" | "magazine" | "text-only";
type ArticleListProps = Omit, "renderItem"> & {
- data: ArticleOverview[];
- horizontal?: boolean;
- infiniteScroll?: boolean;
- displayMode?: ArticleListDisplayMode;
- hasNextPage?: boolean;
- isFetchingNextPage?: boolean;
- fetchNextPage?: () => void;
+ data: ArticleOverview[];
+ horizontal?: boolean;
+ infiniteScroll?: boolean;
+ displayMode?: ArticleListDisplayMode;
+ hasNextPage?: boolean;
+ isFetchingNextPage?: boolean;
+ fetchNextPage?: () => void;
};
type ArticleListComponent = React.FC & {
- HorizontalSeparator: typeof HorizontalSeparator;
- VerticalSeparator: typeof VerticalSeparator;
- LoadingIndicator: typeof LoadingIndicator;
+ HorizontalSeparator: typeof HorizontalSeparator;
+ VerticalSeparator: typeof VerticalSeparator;
+ LoadingIndicator: typeof LoadingIndicator;
};
const keyExtractor = (item: ArticleOverview) => item.id;
const selectDisplayComponent = (mode: ArticleListDisplayMode) => {
- switch (mode) {
- case "card":
- return ArticleOverviewCard;
- case "magazine":
- return ArticleMagazineCard;
- case "text-only":
- return ArticleTextOnlyCard;
- default:
- throw new Error(`Unknown display mode: ${mode}`);
- }
+ switch (mode) {
+ case "card":
+ return ArticleOverviewCard;
+ case "magazine":
+ return ArticleMagazineCard;
+ case "text-only":
+ return ArticleTextOnlyCard;
+ default:
+ throw new Error(`Unknown display mode: ${mode}`);
+ }
};
const ArticleList: ArticleListComponent = (props: ArticleListProps) => {
- const {
- data,
- displayMode = "magazine",
- horizontal = false,
- infiniteScroll = false,
- hasNextPage,
- isFetchingNextPage,
- fetchNextPage,
- refreshing,
- ...rest
- } = props;
+ const {
+ data,
+ displayMode = "magazine",
+ horizontal = false,
+ infiniteScroll = false,
+ hasNextPage,
+ isFetchingNextPage,
+ fetchNextPage,
+ refreshing,
+ ...rest
+ } = props;
- const renderItem = useCallback(
- ({ item }: { item: ArticleOverview }) => {
- const itemWidth = horizontal ? screenWidth * 0.7 : undefined;
- const DisplayComponent = selectDisplayComponent(displayMode);
+ const renderItem = useCallback(
+ ({ item }: { item: ArticleOverview }) => {
+ const itemWidth = horizontal ? screenWidth * 0.7 : undefined;
+ const DisplayComponent = selectDisplayComponent(displayMode);
- return (
-
-
-
- );
- },
- [horizontal, displayMode]
- );
+ return (
+
+
+
+ );
+ },
+ [horizontal, displayMode],
+ );
- const handleOnEndReached = useCallback(async () => {
- if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) {
- fetchNextPage();
- }
- }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]);
+ const handleOnEndReached = useCallback(async () => {
+ if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) {
+ fetchNextPage();
+ }
+ }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]);
- return (
- Pas d’articles disponibles pour le moment.}
- />
- );
+ return (
+ Pas d’articles disponibles pour le moment.}
+ ListFooterComponent={infiniteScroll ? LoadingIndicator : undefined}
+ onEndReached={handleOnEndReached}
+ onEndReachedThreshold={0.5}
+ refreshing={refreshing}
+ removeClippedSubviews={true}
+ renderItem={renderItem}
+ showsHorizontalScrollIndicator={false}
+ />
+ );
};
ArticleList.HorizontalSeparator = HorizontalSeparator;
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx
index 4bc65b5..34f4d78 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleMagazineCard.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Link } from "expo-router";
import { Card, XStack, YStack } from "tamagui";
@@ -10,36 +8,36 @@ import { SourceReferencePill } from "@/ui/components/content/source/SourceRefere
import { Caption, Text } from "@/ui/components/typography";
type ArticleMagazineCardProps = {
- data: ArticleOverview;
+ data: ArticleOverview;
};
export const ArticleMagazineCard = (props: ArticleMagazineCardProps) => {
- const { data } = props;
- const relativeTime = useRelativeTime(data.publishedAt);
+ const { data } = props;
+ const relativeTime = useRelativeTime(data.publishedAt);
- return (
-
-
-
-
-
- {data.title}
-
-
- {data.excerpt}
-
-
+ return (
+
+
+
+
+
+ {data.title}
+
+
+ {data.excerpt}
+
+
- {data.image && }
-
-
+ {data.image && }
+
+
-
-
-
- {relativeTime}
-
-
-
- );
+
+
+
+ {relativeTime}
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx
index 6047f38..4d84a22 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleOverviewCard.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Link } from "expo-router";
import { Card, XStack, YStack } from "tamagui";
@@ -10,35 +8,33 @@ import { SourceReferencePill } from "@/ui/components/content/source/SourceRefere
import { Caption, Text } from "@/ui/components/typography";
type ArticleOverviewCardProps = {
- data: ArticleOverview;
+ data: ArticleOverview;
};
export const ArticleOverviewCard = (props: ArticleOverviewCardProps) => {
- const { data } = props;
- const relativeTime = useRelativeTime(data.publishedAt);
+ const { data } = props;
+ const relativeTime = useRelativeTime(data.publishedAt);
- return (
-
-
- <>
- {data.image && }
-
-
- {data.title}
-
-
- {data.excerpt}
-
-
- >
-
+ return (
+
+
+ {data.image && }
+
+
+ {data.title}
+
+
+ {data.excerpt}
+
+
+
-
-
-
- {relativeTime}
-
-
-
- );
+
+
+
+ {relativeTime}
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx
index f338d26..188aa2f 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleSkeleton.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback } from "react";
+import { useCallback } from "react";
import ContentLoader, { Circle, Rect } from "react-content-loader/native";
import { Dimensions, FlatList } from "react-native";
@@ -10,120 +10,122 @@ const { width: screenWidth } = Dimensions.get("window");
const data: number[] = new Array(5).fill(0);
type ArticleSkeletonListProps = {
- horizontal?: boolean;
- displayMode?: ArticleListDisplayMode;
+ horizontal?: boolean;
+ displayMode?: ArticleListDisplayMode;
};
const OverviewCardSkeleton = (props: any) => (
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
);
const MagazineCardSkeleton = (props: any) => (
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
);
const TextOnlyCardSkeleton = (props: any) => (
-
-
-
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
);
const keyExtractor = (_: number, index: number) => index.toString();
const selectSkeletonComponent = (displayMode: ArticleListDisplayMode) => {
- switch (displayMode) {
- case "magazine":
- return MagazineCardSkeleton;
- case "text-only":
- return TextOnlyCardSkeleton;
- default:
- return OverviewCardSkeleton;
- }
+ switch (displayMode) {
+ case "magazine":
+ return MagazineCardSkeleton;
+ case "text-only":
+ return TextOnlyCardSkeleton;
+ default:
+ return OverviewCardSkeleton;
+ }
};
export const ArticleSkeletonList = (props: ArticleSkeletonListProps) => {
- const { horizontal = false, displayMode = "magazine" } = props;
+ const { horizontal = false, displayMode = "magazine" } = props;
- const ItemSeparator = horizontal ? ArticleList.HorizontalSeparator : ArticleList.VerticalSeparator;
+ const ItemSeparator = horizontal
+ ? ArticleList.HorizontalSeparator
+ : ArticleList.VerticalSeparator;
- const renderItem = useCallback(() => {
- const itemWidth = horizontal ? screenWidth * 0.7 : screenWidth;
- const SkeletonComponent = selectSkeletonComponent(displayMode);
-
- return (
-
-
-
- );
- }, [horizontal, displayMode]);
+ const renderItem = useCallback(() => {
+ const itemWidth = horizontal ? screenWidth * 0.7 : screenWidth;
+ const SkeletonComponent = selectSkeletonComponent(displayMode);
return (
-
+
+
+
);
+ }, [horizontal, displayMode]);
+
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx b/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx
index 6e6b4b8..57db9fc 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/ArticleTextOnlyCard.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Link } from "expo-router";
import { Card, XStack, YStack } from "tamagui";
@@ -9,34 +7,34 @@ import { SourceReferencePill } from "@/ui/components/content/source/SourceRefere
import { Caption, Text } from "@/ui/components/typography";
type ArticleTextOnlyCardProps = {
- data: ArticleOverview;
+ data: ArticleOverview;
};
export const ArticleTextOnlyCard = (props: ArticleTextOnlyCardProps) => {
- const { data } = props;
- const relativeTime = useRelativeTime(data.publishedAt);
+ const { data } = props;
+ const relativeTime = useRelativeTime(data.publishedAt);
- return (
-
-
-
-
-
- {data.title}
-
-
- {data.excerpt}
-
-
-
-
+ return (
+
+
+
+
+
+ {data.title}
+
+
+ {data.excerpt}
+
+
+
+
-
-
-
- {relativeTime}
-
-
-
- );
+
+
+
+ {relativeTime}
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/article/index.tsx b/apps/mobile-legacy/src/ui/components/content/article/index.tsx
index 49a666a..a3a93ec 100644
--- a/apps/mobile-legacy/src/ui/components/content/article/index.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/article/index.tsx
@@ -1,7 +1,7 @@
export { ArticleCategoryPill } from "@/ui/components/content/article/ArticleCategoryPill";
export { ArticleCoverImage } from "@/ui/components/content/article/ArticleCoverImage";
export { ArticleList } from "@/ui/components/content/article/ArticleList";
-export { ArticleSkeletonList } from "@/ui/components/content/article/ArticleSkeleton";
export { ArticleMagazineCard } from "@/ui/components/content/article/ArticleMagazineCard";
export { ArticleOverviewCard } from "@/ui/components/content/article/ArticleOverviewCard";
+export { ArticleSkeletonList } from "@/ui/components/content/article/ArticleSkeleton";
export { ArticleTextOnlyCard } from "@/ui/components/content/article/ArticleTextOnlyCard";
diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx
index e6c285e..7c7a74a 100644
--- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkCard.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Link } from "expo-router";
import { Card, XStack, YStack } from "tamagui";
@@ -8,41 +6,41 @@ import { useRelativeTime } from "@/hooks/use-relative-time";
import { Caption, Text } from "@/ui/components/typography";
type BookmarkCardProps = {
- data: Bookmark;
+ data: Bookmark;
};
export const BookmarkCard = (props: BookmarkCardProps) => {
- const { data } = props;
- const relativeTime = useRelativeTime(data.createdAt);
+ const { data } = props;
+ const relativeTime = useRelativeTime(data.createdAt);
- return (
-
-
-
-
-
-
-
- {data.name}
-
- {data.description && (
-
- {data.description}
-
- )}
-
-
-
+ return (
+
+
+
+
+
+
+
+ {data.name}
+
+ {data.description && (
+
+ {data.description}
+
+ )}
+
+
+
-
-
- {data.isPublic}
- {data.articlesCount} articles
- {relativeTime}
-
-
-
+
+
+ {data.isPublic}
+ {data.articlesCount} articles
+ {relativeTime}
-
- );
+
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx
index d6b761f..49e9466 100644
--- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkEmptyState.tsx
@@ -5,13 +5,15 @@ import { CreateBookmarkSheet } from "@/ui/components/content/bookmark/CreateBook
import { Heading, Text } from "@/ui/components/typography";
export const BookmarkEmptyState = () => {
- return (
-
-
- Empty Bookmarks
- Create a bookmark to save your favorite articles and access them later.
+ return (
+
+
+ Empty Bookmarks
+
+ Create a bookmark to save your favorite articles and access them later.
+
-
-
- );
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx
index b556e1a..b83130c 100644
--- a/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/bookmark/BookmarkList.tsx
@@ -10,58 +10,66 @@ import { BookmarkEmptyState } from "@/ui/components/content/bookmark/BookmarkEmp
const VerticalSeparator = () => ;
const LoadingIndicator = () => (
- <>
-
-
-
- >
+ <>
+
+
+
+ >
);
type BookmarkListProps = Omit, "renderItem"> & {
- data: Bookmark[];
- infiniteScroll?: boolean;
- hasNextPage?: boolean;
- isFetchingNextPage?: boolean;
- fetchNextPage?: () => void;
+ data: Bookmark[];
+ infiniteScroll?: boolean;
+ hasNextPage?: boolean;
+ isFetchingNextPage?: boolean;
+ fetchNextPage?: () => void;
};
type BookmarkListComponent = React.FC & {
- VerticalSeparator: typeof VerticalSeparator;
- LoadingIndicator: typeof LoadingIndicator;
+ VerticalSeparator: typeof VerticalSeparator;
+ LoadingIndicator: typeof LoadingIndicator;
};
const keyExtractor = (item: Bookmark) => item.id;
const renderItem = ({ item }: { item: Bookmark }) => {
- return ;
+ return ;
};
const BookmarkList: BookmarkListComponent = (props: BookmarkListProps) => {
- const { data, infiniteScroll = false, hasNextPage, isFetchingNextPage, fetchNextPage, refreshing, ...rest } = props;
+ const {
+ data,
+ infiniteScroll = false,
+ hasNextPage,
+ isFetchingNextPage,
+ fetchNextPage,
+ refreshing,
+ ...rest
+ } = props;
- const handleOnEndReached = useCallback(async () => {
- if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) {
- fetchNextPage();
- }
- }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]);
+ const handleOnEndReached = useCallback(async () => {
+ if (infiniteScroll && hasNextPage && !isFetchingNextPage && fetchNextPage) {
+ fetchNextPage();
+ }
+ }, [hasNextPage, isFetchingNextPage, fetchNextPage, infiniteScroll]);
- return (
- }
- ListFooterComponent={infiniteScroll && refreshing ? LoadingIndicator : undefined}
- />
- );
+ return (
+ }
+ ListFooterComponent={infiniteScroll && refreshing ? LoadingIndicator : undefined}
+ onEndReached={handleOnEndReached}
+ onEndReachedThreshold={0.5}
+ refreshing={refreshing}
+ removeClippedSubviews={true}
+ renderItem={renderItem}
+ showsHorizontalScrollIndicator={false}
+ />
+ );
};
BookmarkList.VerticalSeparator = VerticalSeparator;
diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx
index 22c9202..6137d7f 100644
--- a/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/bookmark/CreateBookmarkSheet.tsx
@@ -1,7 +1,6 @@
-import { useState } from "react";
-
import { joiResolver } from "@hookform/resolvers/joi";
import { Sheet } from "@tamagui/sheet";
+import { useState } from "react";
import { useForm } from "react-hook-form";
import Toast from "react-native-toast-message";
import { Button, YStack } from "tamagui";
@@ -13,92 +12,92 @@ import { FormSwitch, FormTextArea, FormTextInput } from "@/ui/components/control
import { SubmitButton } from "@/ui/components/controls/SubmitButton";
export const CreateBookmarkSheet = () => {
- const { mutate, isPending } = useCreateBookmark();
- const [open, setOpen] = useState(false);
+ const { mutate, isPending } = useCreateBookmark();
+ const [open, setOpen] = useState(false);
- const { control, handleSubmit, formState } = useForm({
- resolver: joiResolver(BookmarkPayloadSchema),
- });
+ const { control, handleSubmit, formState } = useForm({
+ resolver: joiResolver(BookmarkPayloadSchema),
+ });
- const onSubmit = (data: BookmarkPayload) => {
- mutate(data, {
- onSuccess: () => {
- Toast.show({
- text1: "Félicitations !",
- text2: "Votre signet a été créé avec succès.",
- type: "success",
- });
- setOpen(false);
- },
- onError: (error: ErrorResponse) => {
- Toast.show({
- text1: "Erreur",
- text2: safeMessage(error),
- type: "error",
- });
- },
+ const onSubmit = (data: BookmarkPayload) => {
+ mutate(data, {
+ onError: (error: ErrorResponse) => {
+ Toast.show({
+ text1: "Erreur",
+ text2: safeMessage(error),
+ type: "error",
});
- };
+ },
+ onSuccess: () => {
+ Toast.show({
+ text1: "Félicitations !",
+ text2: "Votre signet a été créé avec succès.",
+ type: "success",
+ });
+ setOpen(false);
+ },
+ });
+ };
- return (
-
-
+ return (
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx b/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx
index 96c52e6..7b3bafe 100644
--- a/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/bookmark/UpdateBookmarkSheet.tsx
@@ -1,13 +1,16 @@
-import { useEffect, useState } from "react";
-
import { joiResolver } from "@hookform/resolvers/joi";
import { Sheet } from "@tamagui/sheet";
+import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import Toast from "react-native-toast-message";
import { Button, YStack } from "tamagui";
import { useUpdateBookmark } from "@/api/request/feed-management/bookmark";
-import { Bookmark, BookmarkPayload, BookmarkPayloadSchema } from "@/api/schema/feed-management/bookmark";
+import {
+ Bookmark,
+ BookmarkPayload,
+ BookmarkPayloadSchema,
+} from "@/api/schema/feed-management/bookmark";
import { ErrorResponse, safeMessage } from "@/api/shared";
import { FormSwitch } from "@/ui/components/controls/forms/Switch";
import { FormTextArea } from "@/ui/components/controls/forms/TextArea";
@@ -15,101 +18,101 @@ import { FormTextInput } from "@/ui/components/controls/forms/TextInput";
import { SubmitButton } from "@/ui/components/controls/SubmitButton";
type UpdateBookmarkSheetProps = {
- data: Bookmark;
+ data: Bookmark;
};
export const UpdateBookmarkSheet = (props: UpdateBookmarkSheetProps) => {
- const { data } = props;
- const { mutate, isPending } = useUpdateBookmark(data.id);
- const [open, setOpen] = useState(false);
+ const { data } = props;
+ const { mutate, isPending } = useUpdateBookmark(data.id);
+ const [open, setOpen] = useState(false);
- const { control, handleSubmit, formState, reset } = useForm({
- resolver: joiResolver(BookmarkPayloadSchema),
- });
+ const { control, handleSubmit, formState, reset } = useForm({
+ resolver: joiResolver(BookmarkPayloadSchema),
+ });
- useEffect(() => {
- reset({ ...data });
- }, [data, reset]);
+ useEffect(() => {
+ reset({ ...data });
+ }, [data, reset]);
- const onSubmit = (data: BookmarkPayload) => {
- mutate(data, {
- onSuccess: () => {
- Toast.show({
- text1: "Félicitations !",
- text2: "Votre signet a été modifié avec succès.",
- type: "success",
- });
- setOpen(false);
- },
- onError: (error: ErrorResponse) => {
- Toast.show({
- text1: "Erreur",
- text2: safeMessage(error),
- type: "error",
- });
- },
+ const onSubmit = (data: BookmarkPayload) => {
+ mutate(data, {
+ onError: (error: ErrorResponse) => {
+ Toast.show({
+ text1: "Erreur",
+ text2: safeMessage(error),
+ type: "error",
});
- };
+ },
+ onSuccess: () => {
+ Toast.show({
+ text1: "Félicitations !",
+ text2: "Votre signet a été modifié avec succès.",
+ type: "success",
+ });
+ setOpen(false);
+ },
+ });
+ };
- return (
-
-
+ return (
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx
index 2a585db..7896170 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceFollowButton.tsx
@@ -6,57 +6,57 @@ import { Button, GetProps } from "tamagui";
import { useFollowSource, useUnfollowSource } from "@/api/request/feed-management/source";
type SourceFollowButtonProps = GetProps & {
- id: string;
- name: string;
- followed: boolean;
+ id: string;
+ name: string;
+ followed: boolean;
};
export const SourceFollowButton = (props: SourceFollowButtonProps) => {
- const { id, followed, name, ...rest } = props;
- const [isFollowed, setIsFollowed] = useState(followed);
- const { mutate: follow, isPending: following } = useFollowSource(id);
- const { mutate: unfollow, isPending: unfollowing } = useUnfollowSource(id);
- const loading = following || unfollowing;
+ const { id, followed, name, ...rest } = props;
+ const [isFollowed, setIsFollowed] = useState(followed);
+ const { mutate: follow, isPending: following } = useFollowSource(id);
+ const { mutate: unfollow, isPending: unfollowing } = useUnfollowSource(id);
+ const loading = following || unfollowing;
- const handlePress = useCallback(() => {
- if (isFollowed) {
- Alert.alert(
- "Confirmation",
- `Êtes-vous sûr de vouloir ne plus suivre ${name} ?`,
- [
- {
- text: "Annuler",
- style: "cancel",
- },
- {
- text: "Ne plus suivre",
- style: "destructive",
- onPress: () => {
- unfollow();
- setIsFollowed(prev => !prev);
- },
- },
- ],
- { cancelable: false }
- );
- } else {
- follow();
- setIsFollowed(prev => !prev);
- }
- }, [isFollowed, name, unfollow, follow, setIsFollowed]);
+ const handlePress = useCallback(() => {
+ if (isFollowed) {
+ Alert.alert(
+ "Confirmation",
+ `Êtes-vous sûr de vouloir ne plus suivre ${name} ?`,
+ [
+ {
+ style: "cancel",
+ text: "Annuler",
+ },
+ {
+ onPress: () => {
+ unfollow();
+ setIsFollowed((prev) => !prev);
+ },
+ style: "destructive",
+ text: "Ne plus suivre",
+ },
+ ],
+ { cancelable: false },
+ );
+ } else {
+ follow();
+ setIsFollowed((prev) => !prev);
+ }
+ }, [isFollowed, name, unfollow, follow]);
- return (
-
- );
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx
index 89d8c33..38f777c 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceList.tsx
@@ -10,43 +10,43 @@ const HorizontalSeparator = () => ;
const VerticalSeparator = () => ;
type SourceOverviewListProps = Omit, "renderItem"> & {
- data: SourceOverview[];
- horizontal?: boolean;
- infiniteScroll?: boolean;
+ data: SourceOverview[];
+ horizontal?: boolean;
+ infiniteScroll?: boolean;
};
type SourceOverviewListComponent = React.FC & {
- HorizontalSeparator: typeof HorizontalSeparator;
- VerticalSeparator: typeof VerticalSeparator;
+ HorizontalSeparator: typeof HorizontalSeparator;
+ VerticalSeparator: typeof VerticalSeparator;
};
const keyExtractor = (item: SourceOverview) => item.name;
const SourceList: SourceOverviewListComponent = (props: SourceOverviewListProps) => {
- const { data, horizontal = false, ...rest } = props;
+ const { data, horizontal = false, ...rest } = props;
- const renderItem = useCallback(
- ({ item }: { item: SourceOverview }) => {
- return ;
- },
- [horizontal]
- );
+ const renderItem = useCallback(
+ ({ item }: { item: SourceOverview }) => {
+ return ;
+ },
+ [horizontal],
+ );
- return (
- Pas de sources disponibles pour le moment.}
- />
- );
+ return (
+ Pas de sources disponibles pour le moment.}
+ onEndReachedThreshold={0.5}
+ removeClippedSubviews={true}
+ renderItem={renderItem}
+ showsHorizontalScrollIndicator={false}
+ />
+ );
};
SourceList.HorizontalSeparator = HorizontalSeparator;
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx
index 64744e8..ce0b077 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceOverviewCard.tsx
@@ -7,70 +7,74 @@ import { SourceProfileImage } from "@/ui/components/content/source/SourceProfile
import { Text } from "@/ui/components/typography";
const SourceCardFrame = styled(YStack, {
- alignItems: "center",
- gap: "$2",
- borderRadius: "$4",
+ alignItems: "center",
+ borderRadius: "$4",
+ gap: "$2",
- variants: {
- horizontal: {
- true: {
- maxWidth: 100,
- flexShrink: 0,
- },
- false: {
- flexDirection: "row",
- justifyContent: "space-between",
- width: "100%",
- gap: "$4",
- paddingVertical: "$2",
- },
- },
+ variants: {
+ horizontal: {
+ false: {
+ flexDirection: "row",
+ gap: "$4",
+ justifyContent: "space-between",
+ paddingVertical: "$2",
+ width: "100%",
+ },
+ true: {
+ flexShrink: 0,
+ maxWidth: 100,
+ },
},
+ },
} as const);
type SourceCardProps = GetProps & {
- data: SourceOverview;
- horizontal?: boolean;
+ data: SourceOverview;
+ horizontal?: boolean;
};
export const SourceOverviewCard = (props: SourceCardProps) => {
- const { data, horizontal = true, ...rest } = props;
+ const { data, horizontal = true, ...rest } = props;
- const nameFontSize = horizontal ? "$3" : "$4";
+ const nameFontSize = horizontal ? "$3" : "$4";
- return (
-
-
-
-
+ return (
+
+
+
+
-
- {horizontal ? (
-
- {data.displayName ?? data.name}
-
- ) : (
-
-
-
- {data.displayName ?? data.name}
-
-
+
+ {horizontal ? (
+
+ {data.displayName ?? data.name}
+
+ ) : (
+
+
+
+ {data.displayName ?? data.name}
+
+
-
- {data.url}
-
-
- )}
-
+
+ {data.url}
+
+
+ )}
+
-
-
- );
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx
index ca2eeb4..5014123 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceProfileImage.tsx
@@ -1,32 +1,30 @@
-import type React from "react";
-
import { GetProps, Image, styled } from "tamagui";
const StyledImage = styled(Image, {
- borderRadius: "$12",
- backgroundColor: "white",
+ backgroundColor: "white",
+ borderRadius: "$12",
});
type SourceAvatarProps = GetProps & {
- image: string;
- name: string;
- size?: number;
+ image: string;
+ name: string;
+ size?: number;
};
export const SourceProfileImage = (props: SourceAvatarProps) => {
- const { image, name, size = 50, ...rest } = props;
+ const { image, name, size = 50, ...rest } = props;
- return (
-
- );
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx
index 60a29b8..e082a0b 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceReferencePill.tsx
@@ -1,5 +1,3 @@
-import React from "react";
-
import { Link } from "expo-router";
import { Avatar, GetProps, XStack } from "tamagui";
@@ -7,31 +5,31 @@ import { SourceReference } from "@/api/schema/feed-management/source";
import { Text } from "@/ui/components/typography";
type SourceReferencePillProps = GetProps & {
- data: SourceReference;
+ data: SourceReference;
};
export function SourceReferencePill(props: SourceReferencePillProps) {
- const { data, ...rest } = props;
+ const { data, ...rest } = props;
- return (
-
-
-
-
-
-
-
- {data.displayName ?? data.name}
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+ {data.displayName ?? data.name}
+
+
+
+ );
}
diff --git a/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx b/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx
index 8555bfe..36a80a2 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx
+++ b/apps/mobile-legacy/src/ui/components/content/source/SourceSkeleton.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback } from "react";
+import { useCallback } from "react";
import ContentLoader, { Circle, Rect } from "react-content-loader/native";
import { FlatList } from "react-native";
@@ -9,74 +9,74 @@ import { SourceList } from "@/ui/components/content/source/SourceList";
const data: number[] = new Array(5).fill(0);
type SourceSkeletonListProps = {
- horizontal?: boolean;
+ horizontal?: boolean;
};
const VerticalSkeleton = (props: any) => (
-
-
-
-
-
-
+
+
+
+
+
+
);
const HorizontalSkeleton = (props: any) => (
-
-
-
-
-
+
+
+
+
+
);
const keyExtractor = (_: number, index: number) => index.toString();
const selectSkeletonComponent = (horizontal: boolean) => {
- return horizontal ? (
-
- ) : (
-
-
-
- );
+ return horizontal ? (
+
+ ) : (
+
+
+
+ );
};
export const SourceSkeletonList = (props: SourceSkeletonListProps) => {
- const { horizontal = false } = props;
+ const { horizontal = false } = props;
- const ItemSeparator = horizontal ? SourceList.HorizontalSeparator : SourceList.VerticalSeparator;
+ const ItemSeparator = horizontal ? SourceList.HorizontalSeparator : SourceList.VerticalSeparator;
- const renderItem = useCallback(() => {
- return selectSkeletonComponent(horizontal);
- }, [horizontal]);
+ const renderItem = useCallback(() => {
+ return selectSkeletonComponent(horizontal);
+ }, [horizontal]);
- return (
-
- );
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/content/source/index.ts b/apps/mobile-legacy/src/ui/components/content/source/index.ts
index 244fccb..4128321 100644
--- a/apps/mobile-legacy/src/ui/components/content/source/index.ts
+++ b/apps/mobile-legacy/src/ui/components/content/source/index.ts
@@ -1,6 +1,6 @@
-export { SourceList } from "@/ui/components/content/source/SourceList";
export { SourceFollowButton } from "@/ui/components/content/source/SourceFollowButton";
+export { SourceList } from "@/ui/components/content/source/SourceList";
+export { SourceOverviewCard } from "@/ui/components/content/source/SourceOverviewCard";
+export { SourceProfileImage } from "@/ui/components/content/source/SourceProfileImage";
export { SourceReferencePill } from "@/ui/components/content/source/SourceReferencePill";
export { SourceSkeletonList } from "@/ui/components/content/source/SourceSkeleton";
-export { SourceProfileImage } from "@/ui/components/content/source/SourceProfileImage";
-export { SourceOverviewCard } from "@/ui/components/content/source/SourceOverviewCard";
diff --git a/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx b/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx
index 1c68312..809d3ea 100644
--- a/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/BackButton.tsx
@@ -2,24 +2,24 @@ import { ArrowLeft } from "@tamagui/lucide-icons";
import { Button, ButtonProps } from "tamagui";
type BackButtonProps = {
- onPress: () => void;
+ onPress: () => void;
};
export const BackButton = (props: BackButtonProps & ButtonProps) => {
- const { onPress, ...rest } = props;
+ const { onPress, ...rest } = props;
- return (
- }
- onPress={onPress}
- {...rest}
- />
- );
+ return (
+ }
+ onPress={onPress}
+ // backgroundColor="$gray6"
+ size="$4"
+ width="$4"
+ {...rest}
+ />
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/controls/IconButton.tsx b/apps/mobile-legacy/src/ui/components/controls/IconButton.tsx
index 6edcaf9..f2aa4e6 100644
--- a/apps/mobile-legacy/src/ui/components/controls/IconButton.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/IconButton.tsx
@@ -1,22 +1,22 @@
import { Button, ButtonProps } from "tamagui";
type IconButtonProps = {
- onPress: () => void;
+ onPress: () => void;
};
export const IconButton = (props: IconButtonProps & ButtonProps) => {
- const { onPress, ...rest } = props;
+ const { onPress, ...rest } = props;
- return (
-
- );
+ return (
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/controls/SubmitButton.tsx b/apps/mobile-legacy/src/ui/components/controls/SubmitButton.tsx
index 8d3990b..07e125a 100644
--- a/apps/mobile-legacy/src/ui/components/controls/SubmitButton.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/SubmitButton.tsx
@@ -2,27 +2,27 @@ import { ActivityIndicator } from "react-native";
import { Button, GetProps, styled } from "tamagui";
const StyledButton = styled(Button, {
- fontWeight: "bold",
- width: "100%",
+ fontWeight: "bold",
+ width: "100%",
});
type SubmitButtonProps = GetProps & {
- label: string;
- isValid: boolean;
- isPending: boolean;
+ label: string;
+ isValid: boolean;
+ isPending: boolean;
};
export const SubmitButton = (props: SubmitButtonProps) => {
- const { isValid, isPending, label, ...rest } = props;
+ const { isValid, isPending, label, ...rest } = props;
- return (
-
- {isPending ? : label}
-
- );
+ return (
+
+ {isPending ? : label}
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/EmailInput.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/EmailInput.tsx
index 4dae614..df3e082 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/EmailInput.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/EmailInput.tsx
@@ -4,22 +4,22 @@ import { Input, InputProps } from "@/ui/components/controls/forms/Input";
import { withController } from "@/ui/components/controls/forms/withController";
export const EmailInput = (props: InputProps) => {
- const { label = "Email", caption, error, onChangeText, ...rest } = props;
+ const { label = "Email", caption, error, onChangeText, ...rest } = props;
- return (
-
- );
+ return (
+
+ );
};
export const FormEmailInput = withController(EmailInput);
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/Input.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/Input.tsx
index a96d90d..3ee1790 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/Input.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/Input.tsx
@@ -1,73 +1,82 @@
-import React, { useMemo } from "react";
-
import { IconProps } from "@tamagui/helpers-icon";
-import { ColorTokens, GetProps, Input as TamaguiInput, Label, SizeTokens, styled, XStack, YStack } from "tamagui";
+import React, { useMemo } from "react";
+import {
+ ColorTokens,
+ GetProps,
+ Label,
+ SizeTokens,
+ styled,
+ Input as TamaguiInput,
+ XStack,
+ YStack,
+} from "tamagui";
import { Caption } from "@/ui/components/typography";
const StyledInput = styled(TamaguiInput, {
- size: "$large",
- flex: 1,
- borderWidth: 0,
- placeholderTextColor: "$gray8",
- backgroundColor: "transparent",
+ backgroundColor: "transparent",
+ borderWidth: 0,
+ flex: 1,
+ placeholderTextColor: "$gray8",
+ size: "$large",
});
export type InputProps = GetProps & {
- label?: string;
- caption?: string;
- error?: string;
- leadingAdornment?: React.ComponentType;
- trailingAdornment?: React.ReactNode;
- onChangeText?: (text: string) => void;
- id?: string;
+ label?: string;
+ caption?: string;
+ error?: string;
+ leadingAdornment?: React.ComponentType;
+ trailingAdornment?: React.ReactNode;
+ onChangeText?: (text: string) => void;
+ id?: string;
};
export const Input = (props: InputProps) => {
- const { label, caption, error, leadingAdornment, trailingAdornment, onChangeText, id, ...rest } = props;
+ const { label, caption, error, leadingAdornment, trailingAdornment, onChangeText, id, ...rest } =
+ props;
- const isInvalid = !!error;
- const leadingAdornmentComponent = useMemo(() => {
- return leadingAdornment ? (
-
- {React.createElement(leadingAdornment, {
- size: "$1",
- color: "$gray9",
- })}
-
- ) : undefined;
- }, [leadingAdornment]);
+ const isInvalid = !!error;
+ const leadingAdornmentComponent = useMemo(() => {
+ return leadingAdornment ? (
+
+ {React.createElement(leadingAdornment, {
+ color: "$gray9",
+ size: "$1",
+ })}
+
+ ) : undefined;
+ }, [leadingAdornment]);
- return (
-
-
- {label && (
-
- )}
+ return (
+
+
+ {label && (
+
+ )}
-
- {leadingAdornmentComponent}
-
- {trailingAdornment}
-
-
+
+ {leadingAdornmentComponent}
+
+ {trailingAdornment}
+
+
- {caption && !isInvalid && {caption}}
- {isInvalid && error && {error}}
-
- );
+ {caption && !isInvalid && {caption}}
+ {isInvalid && error && {error}}
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/PasswordInput.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/PasswordInput.tsx
index 9db3e12..0bc5b99 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/PasswordInput.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/PasswordInput.tsx
@@ -1,37 +1,36 @@
-import { useState } from "react";
-
import { Eye, EyeOff, Lock } from "@tamagui/lucide-icons";
+import { useState } from "react";
import { XStack } from "tamagui";
import { Input, InputProps } from "@/ui/components/controls/forms/Input";
import { withController } from "@/ui/components/controls/forms/withController";
export const PasswordInput = (props: InputProps) => {
- const { label = "Mot de passe", onChangeText, caption, error, ...rest } = props;
- const [showPassword, setShowPassword] = useState(false);
+ const { label = "Mot de passe", onChangeText, caption, error, ...rest } = props;
+ const [showPassword, setShowPassword] = useState(false);
- return (
- setShowPassword(!showPassword)}
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
- >
- {showPassword ? : }
-
- }
- {...rest}
- />
- );
+ return (
+ setShowPassword(!showPassword)}
+ paddingRight="$3"
+ >
+ {showPassword ? : }
+
+ }
+ {...rest}
+ />
+ );
};
export const FormPasswordInput = withController(PasswordInput);
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/Switch.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/Switch.tsx
index 8d21963..5c7fa3f 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/Switch.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/Switch.tsx
@@ -4,29 +4,35 @@ import { withController } from "@/ui/components/controls/forms/withController";
import { Caption } from "@/ui/components/typography";
type SwitchProps = GetProps & {
- label: string;
- description?: string;
- isChecked: boolean;
- onCheckedChange: (checked: boolean) => void;
- id?: string;
+ label: string;
+ description?: string;
+ isChecked: boolean;
+ onCheckedChange: (checked: boolean) => void;
+ id?: string;
};
export const Switch = (props: SwitchProps) => {
- const { label, description, isChecked, onCheckedChange, id, ...rest } = props;
+ const { label, description, isChecked, onCheckedChange, id, ...rest } = props;
- return (
-
-
-
- {description && {description}}
-
-
-
-
-
- );
+ return (
+
+
+
+ {description && {description}}
+
+
+
+
+
+ );
};
export const FormSwitch = withController(Switch);
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/TextArea.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/TextArea.tsx
index a70095d..5c2e6b7 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/TextArea.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/TextArea.tsx
@@ -4,55 +4,55 @@ import { withController } from "@/ui/components/controls/forms/withController";
import { Caption } from "@/ui/components/typography";
const StyledTextArea = styled(TamaguiTextArea, {
- size: "$4",
- flex: 1,
- minHeight: 100,
- borderWidth: 0,
- placeholderTextColor: "$gray8",
- backgroundColor: "transparent",
+ backgroundColor: "transparent",
+ borderWidth: 0,
+ flex: 1,
+ minHeight: 100,
+ placeholderTextColor: "$gray8",
+ size: "$4",
});
type TextAreaProps = GetProps & {
- label?: string;
- caption?: string;
- error?: string;
- onChangeText?: (text: string) => void;
- id?: string;
+ label?: string;
+ caption?: string;
+ error?: string;
+ onChangeText?: (text: string) => void;
+ id?: string;
};
export const TextArea = (props: TextAreaProps) => {
- const { label, caption, error, onChangeText, id, ...rest } = props;
+ const { label, caption, error, onChangeText, id, ...rest } = props;
- const isInvalid = !!error;
+ const isInvalid = !!error;
- return (
-
- {label && (
-
- )}
+ return (
+
+ {label && (
+
+ )}
-
-
-
+
+
+
- {caption && !isInvalid && {caption}}
- {isInvalid && error && {error}}
-
- );
+ {caption && !isInvalid && {caption}}
+ {isInvalid && error && {error}}
+
+ );
};
export const FormTextArea = withController(TextArea);
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/TextInput.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/TextInput.tsx
index 0b3db05..eaea1c4 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/TextInput.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/TextInput.tsx
@@ -2,18 +2,18 @@ import { Input, InputProps } from "@/ui/components/controls/forms/Input";
import { withController } from "@/ui/components/controls/forms/withController";
export const TextInput = (props: InputProps) => {
- const { label, caption, error, leadingAdornment, onChangeText, ...rest } = props;
+ const { label, caption, error, leadingAdornment, onChangeText, ...rest } = props;
- return (
-
- );
+ return (
+
+ );
};
export const FormTextInput = withController(TextInput);
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/index.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/index.tsx
index 92d4d8c..9ab15b5 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/index.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/index.tsx
@@ -1,5 +1,5 @@
export { EmailInput, FormEmailInput } from "@/ui/components/controls/forms/EmailInput";
-export { TextInput, FormTextInput } from "@/ui/components/controls/forms/TextInput";
-export { PasswordInput, FormPasswordInput } from "@/ui/components/controls/forms/PasswordInput";
-export { Switch, FormSwitch } from "@/ui/components/controls/forms/Switch";
-export { TextArea, FormTextArea } from "@/ui/components/controls/forms/TextArea";
+export { FormPasswordInput, PasswordInput } from "@/ui/components/controls/forms/PasswordInput";
+export { FormSwitch, Switch } from "@/ui/components/controls/forms/Switch";
+export { FormTextArea, TextArea } from "@/ui/components/controls/forms/TextArea";
+export { FormTextInput, TextInput } from "@/ui/components/controls/forms/TextInput";
diff --git a/apps/mobile-legacy/src/ui/components/controls/forms/withController.tsx b/apps/mobile-legacy/src/ui/components/controls/forms/withController.tsx
index e24d892..65bfbc1 100644
--- a/apps/mobile-legacy/src/ui/components/controls/forms/withController.tsx
+++ b/apps/mobile-legacy/src/ui/components/controls/forms/withController.tsx
@@ -3,48 +3,50 @@ import React from "react";
import { Controller, ControllerProps } from "react-hook-form";
type WithControllerProps = {
- value?: any;
- onChangeText?: (val: any) => void;
- isChecked?: boolean;
- onCheckedChange?: (val: boolean) => void;
- error?: string;
+ value?: any;
+ onChangeText?: (val: any) => void;
+ isChecked?: boolean;
+ onCheckedChange?: (val: boolean) => void;
+ error?: string;
};
type ControllerWrapperProps = {
- name: string;
- control: ControllerProps["control"];
+ name: string;
+ control: ControllerProps["control"];
} & Omit;
-export const withController = (Component: React.ComponentType) => {
- const ControllerWrapper = (props: ControllerWrapperProps) => {
- const { name, control, ...rest } = props;
+export const withController = (
+ Component: React.ComponentType,
+) => {
+ const ControllerWrapper = (props: ControllerWrapperProps) => {
+ const { name, control, ...rest } = props;
- return (
- {
- const hasSwitchProps = "isChecked" in rest || "onCheckedChange" in rest;
+ return (
+ {
+ const hasSwitchProps = "isChecked" in rest || "onCheckedChange" in rest;
- const controllerProps: WithControllerProps = {
- error: error?.message,
- };
+ const controllerProps: WithControllerProps = {
+ error: error?.message,
+ };
- if (hasSwitchProps) {
- controllerProps.isChecked = value;
- controllerProps.onCheckedChange = onChange;
- } else {
- controllerProps.value = value;
- controllerProps.onChangeText = onChange;
- }
+ if (hasSwitchProps) {
+ controllerProps.isChecked = value;
+ controllerProps.onCheckedChange = onChange;
+ } else {
+ controllerProps.value = value;
+ controllerProps.onChangeText = onChange;
+ }
- return ;
- }}
- />
- );
- };
+ return ;
+ }}
+ />
+ );
+ };
- ControllerWrapper.displayName = `withController(${Component.displayName || Component.name || "Component"})`;
+ ControllerWrapper.displayName = `withController(${Component.displayName || Component.name || "Component"})`;
- return ControllerWrapper;
+ return ControllerWrapper;
};
diff --git a/apps/mobile-legacy/src/ui/components/layout/ScreenHeading.tsx b/apps/mobile-legacy/src/ui/components/layout/ScreenHeading.tsx
index bd4da45..46a918a 100644
--- a/apps/mobile-legacy/src/ui/components/layout/ScreenHeading.tsx
+++ b/apps/mobile-legacy/src/ui/components/layout/ScreenHeading.tsx
@@ -5,51 +5,57 @@ import { styled, View, XStack } from "tamagui";
import { Text } from "@/ui/components/typography";
const ActionContainer = styled(XStack, {
- alignItems: "center",
- minWidth: "$5",
- gap: "$1",
+ alignItems: "center",
+ gap: "$1",
+ minWidth: "$5",
});
interface ScreenHeadingProps {
- leadingAction?: React.ReactNode;
- title?: string;
- trailingActions?: React.ReactNode | React.ReactNode[];
- paddingHorizontal?: number | string;
- marginBottom?: number | string;
+ leadingAction?: React.ReactNode;
+ title?: string;
+ trailingActions?: React.ReactNode | React.ReactNode[];
+ paddingHorizontal?: number | string;
+ marginBottom?: number | string;
}
export const ScreenHeading = (props: ScreenHeadingProps) => {
- const { leadingAction, title, trailingActions, paddingHorizontal = "$4", marginBottom = "$2" } = props;
- const trailingActionsArray = Array.isArray(trailingActions)
- ? trailingActions
- : trailingActions
- ? [trailingActions]
- : [];
+ const {
+ leadingAction,
+ title,
+ trailingActions,
+ paddingHorizontal = "$4",
+ marginBottom = "$2",
+ } = props;
+ const trailingActionsArray = Array.isArray(trailingActions)
+ ? trailingActions
+ : trailingActions
+ ? [trailingActions]
+ : [];
- return (
-
- {leadingAction}
-
- {title ? (
-
- {title}
-
- ) : (
-
- )}
-
-
- {trailingActionsArray.map((action, index) => (
- {action}
- ))}
-
-
- );
+ return (
+
+ {leadingAction}
+
+ {title ? (
+
+ {title}
+
+ ) : (
+
+ )}
+
+
+ {trailingActionsArray.map((action, index) => (
+ {action}
+ ))}
+
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/layout/ScreenSection.tsx b/apps/mobile-legacy/src/ui/components/layout/ScreenSection.tsx
index aae06ce..e44c510 100644
--- a/apps/mobile-legacy/src/ui/components/layout/ScreenSection.tsx
+++ b/apps/mobile-legacy/src/ui/components/layout/ScreenSection.tsx
@@ -1,5 +1,3 @@
-import type React from "react";
-
import { ArrowRight } from "@tamagui/lucide-icons";
import { Href, Link } from "expo-router";
import { GetProps, Paragraph, styled, XStack } from "tamagui";
@@ -7,41 +5,48 @@ import { GetProps, Paragraph, styled, XStack } from "tamagui";
import { Text } from "@/ui/components/typography";
const SectionContainer = styled(XStack, {
- alignItems: "center",
- justifyContent: "space-between",
- width: "100%",
- paddingVertical: "$2",
+ alignItems: "center",
+ justifyContent: "space-between",
+ paddingVertical: "$2",
+ width: "100%",
});
type ScreenSectionProps = GetProps & {
- title: string;
- forwardLink?: Href;
+ title: string;
+ forwardLink?: Href;
};
type ScreenSectionLinkProps = {
- href: Href;
+ href: Href;
};
const ScreenSectionLink = ({ href }: ScreenSectionLinkProps) => (
-
-
-
- Voir tout
-
-
-
-
+
+
+
+ Voir tout
+
+
+
+
);
export const ScreenSection = (props: ScreenSectionProps) => {
- const { title, forwardLink, ...rest } = props;
+ const { title, forwardLink, ...rest } = props;
- return (
-
-
- {title}
-
- {forwardLink && }
-
- );
+ return (
+
+
+ {title}
+
+ {forwardLink && }
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/layout/ScreenView.tsx b/apps/mobile-legacy/src/ui/components/layout/ScreenView.tsx
index d137f47..6183ea1 100644
--- a/apps/mobile-legacy/src/ui/components/layout/ScreenView.tsx
+++ b/apps/mobile-legacy/src/ui/components/layout/ScreenView.tsx
@@ -1,6 +1,5 @@
-import React from "react";
-
import { StatusBar } from "expo-status-bar";
+import React from "react";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { styled, YStack } from "tamagui";
@@ -8,68 +7,70 @@ import { ScreenHeading } from "@/ui/components/layout/ScreenHeading";
import { ScreenSection } from "@/ui/components/layout/ScreenSection";
type ScreenViewProps = React.ComponentProps & {
- showStatusBar?: boolean;
- statusBarStyle?: "auto" | "inverted" | "light" | "dark";
- statusBarBackgroundColor?: string;
- children?: React.ReactNode;
+ showStatusBar?: boolean;
+ statusBarStyle?: "auto" | "inverted" | "light" | "dark";
+ statusBarBackgroundColor?: string;
+ children?: React.ReactNode;
};
type ScreenViewComponent = React.FC> & {
- Heading: typeof ScreenHeading;
- Section: typeof ScreenSection;
+ Heading: typeof ScreenHeading;
+ Section: typeof ScreenSection;
};
const ScreenContent = styled(YStack, {
- gap: "$4",
- paddingHorizontal: "$4",
- alignItems: "center",
+ alignItems: "center",
+ gap: "$4",
+ paddingHorizontal: "$4",
});
const ScreenView: ScreenViewComponent = (props: React.PropsWithChildren) => {
- const {
- showStatusBar = true,
- statusBarStyle = "auto",
- statusBarBackgroundColor = "transparent",
- padding,
- children,
- ...rest
- } = props;
- const insets = useSafeAreaInsets();
+ const {
+ showStatusBar = true,
+ statusBarStyle = "auto",
+ statusBarBackgroundColor = "transparent",
+ padding,
+ children,
+ ...rest
+ } = props;
+ const insets = useSafeAreaInsets();
- let headingElement: React.ReactNode | null = null;
- const otherChildren: React.ReactNode[] = [];
+ let headingElement: React.ReactNode | null = null;
+ const otherChildren: React.ReactNode[] = [];
- // Iterate through children to find the Heading and separate others
- React.Children.forEach(children, child => {
- if (React.isValidElement(child)) {
- if (child.type === ScreenView.Heading) {
- headingElement = child;
- } else {
- otherChildren.push(child);
- }
- } else {
- otherChildren.push(child);
- }
- });
+ // Iterate through children to find the Heading and separate others
+ React.Children.forEach(children, (child) => {
+ if (React.isValidElement(child)) {
+ if (child.type === ScreenView.Heading) {
+ headingElement = child;
+ } else {
+ otherChildren.push(child);
+ }
+ } else {
+ otherChildren.push(child);
+ }
+ });
- return (
- <>
- {showStatusBar ? : null}
+ return (
+ <>
+ {showStatusBar ? (
+
+ ) : null}
-
- {headingElement}
+
+ {headingElement}
-
- {otherChildren}
-
-
- >
- );
+
+ {otherChildren}
+
+
+ >
+ );
};
ScreenView.Heading = ScreenHeading;
diff --git a/apps/mobile-legacy/src/ui/components/typography/Caption.tsx b/apps/mobile-legacy/src/ui/components/typography/Caption.tsx
index dbacc17..4eaa0da 100644
--- a/apps/mobile-legacy/src/ui/components/typography/Caption.tsx
+++ b/apps/mobile-legacy/src/ui/components/typography/Caption.tsx
@@ -3,11 +3,11 @@ import type React from "react";
import { Paragraph, ParagraphProps } from "tamagui";
export const Caption = (props: React.PropsWithChildren) => {
- const { children, ...rest } = props;
+ const { children, ...rest } = props;
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/typography/Display.tsx b/apps/mobile-legacy/src/ui/components/typography/Display.tsx
index 7efa52b..58eabae 100644
--- a/apps/mobile-legacy/src/ui/components/typography/Display.tsx
+++ b/apps/mobile-legacy/src/ui/components/typography/Display.tsx
@@ -3,11 +3,11 @@ import type React from "react";
import { H2, ParagraphProps } from "tamagui";
export const Display = (props: React.PropsWithChildren) => {
- const { children, ...rest } = props;
+ const { children, ...rest } = props;
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/typography/Heading.tsx b/apps/mobile-legacy/src/ui/components/typography/Heading.tsx
index 8b00a17..a2908ec 100644
--- a/apps/mobile-legacy/src/ui/components/typography/Heading.tsx
+++ b/apps/mobile-legacy/src/ui/components/typography/Heading.tsx
@@ -3,11 +3,11 @@ import type React from "react";
import { H4, ParagraphProps } from "tamagui";
export const Heading = (props: React.PropsWithChildren) => {
- const { children, ...rest } = props;
+ const { children, ...rest } = props;
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
};
diff --git a/apps/mobile-legacy/src/ui/components/typography/Text.tsx b/apps/mobile-legacy/src/ui/components/typography/Text.tsx
index f31def8..59d9ced 100644
--- a/apps/mobile-legacy/src/ui/components/typography/Text.tsx
+++ b/apps/mobile-legacy/src/ui/components/typography/Text.tsx
@@ -3,6 +3,6 @@ import type React from "react";
import { Paragraph, ParagraphProps } from "tamagui";
export const Text = (props: React.PropsWithChildren) => {
- const { children, ...rest } = props;
- return {children};
+ const { children, ...rest } = props;
+ return {children};
};
diff --git a/apps/mobile-legacy/src/ui/components/typography/index.ts b/apps/mobile-legacy/src/ui/components/typography/index.ts
index 3dc4706..ac20692 100644
--- a/apps/mobile-legacy/src/ui/components/typography/index.ts
+++ b/apps/mobile-legacy/src/ui/components/typography/index.ts
@@ -1,4 +1,4 @@
+export { Caption } from "@/ui/components/typography/Caption";
export { Display } from "@/ui/components/typography/Display";
export { Heading } from "@/ui/components/typography/Heading";
-export { Caption } from "@/ui/components/typography/Caption";
export { Text } from "@/ui/components/typography/Text";
diff --git a/apps/mobile-legacy/tamagui.config.ts b/apps/mobile-legacy/tamagui.config.ts
index c791a6e..55073fa 100644
--- a/apps/mobile-legacy/tamagui.config.ts
+++ b/apps/mobile-legacy/tamagui.config.ts
@@ -4,6 +4,6 @@ import { createTamagui } from "tamagui";
import { themes } from "./themes";
export const config = createTamagui({
- ...defaultConfig,
- themes,
+ ...defaultConfig,
+ themes,
});
diff --git a/apps/mobile-legacy/themes.ts b/apps/mobile-legacy/themes.ts
index 429112e..5ec35cd 100644
--- a/apps/mobile-legacy/themes.ts
+++ b/apps/mobile-legacy/themes.ts
@@ -2,120 +2,119 @@ import * as Colors from "@tamagui/colors";
import { createThemes, defaultComponentThemes } from "@tamagui/theme-builder";
const primaryPalette = [
- "hsl(174, 66%, 97%)",
- "hsl(174, 66%, 93%)",
- "hsl(174, 66%, 87%)",
- "hsl(174, 66%, 78%)",
- "hsl(174, 66%, 68%)",
- "hsl(174, 66%, 60%)",
- "hsl(174, 66%, 53%)",
- "hsl(174, 66%, 48%)",
- "hsl(174, 66%, 40%)",
- "hsl(174, 66%, 33%)",
- "hsl(174, 66%, 21%)",
- "hsl(174, 66%, 12%)",
+ "hsl(174, 66%, 97%)",
+ "hsl(174, 66%, 93%)",
+ "hsl(174, 66%, 87%)",
+ "hsl(174, 66%, 78%)",
+ "hsl(174, 66%, 68%)",
+ "hsl(174, 66%, 60%)",
+ "hsl(174, 66%, 53%)",
+ "hsl(174, 66%, 48%)",
+ "hsl(174, 66%, 40%)",
+ "hsl(174, 66%, 33%)",
+ "hsl(174, 66%, 21%)",
+ "hsl(174, 66%, 12%)",
];
const lightPalette = [
- "hsl(174, 6.6%, 98%)",
- "hsl(174, 6.6%, 96%)",
- "hsl(174, 6.6%, 90%)",
- "hsl(174, 6.6%, 84%)",
- "hsl(174, 6.6%, 65%)",
- "hsl(174, 6.6%, 46%)",
- "hsl(174, 6.6%, 34%)",
- "hsl(174, 6.6%, 26%)",
- "hsl(174, 6.6%, 16%)",
- "hsl(174, 6.6%, 10%)",
- "hsl(174, 6.6%, 8%)",
- "hsl(174, 6.6%, 4%)",
+ "hsl(174, 6.6%, 98%)",
+ "hsl(174, 6.6%, 96%)",
+ "hsl(174, 6.6%, 90%)",
+ "hsl(174, 6.6%, 84%)",
+ "hsl(174, 6.6%, 65%)",
+ "hsl(174, 6.6%, 46%)",
+ "hsl(174, 6.6%, 34%)",
+ "hsl(174, 6.6%, 26%)",
+ "hsl(174, 6.6%, 16%)",
+ "hsl(174, 6.6%, 10%)",
+ "hsl(174, 6.6%, 8%)",
+ "hsl(174, 6.6%, 4%)",
];
const darkPalette = [...lightPalette].reverse();
const lightShadows = {
- shadow1: "rgba(0,0,0,0.04)",
- shadow2: "rgba(0,0,0,0.08)",
- shadow3: "rgba(0,0,0,0.16)",
- shadow4: "rgba(0,0,0,0.24)",
- shadow5: "rgba(0,0,0,0.32)",
- shadow6: "rgba(0,0,0,0.4)",
+ shadow1: "rgba(0,0,0,0.04)",
+ shadow2: "rgba(0,0,0,0.08)",
+ shadow3: "rgba(0,0,0,0.16)",
+ shadow4: "rgba(0,0,0,0.24)",
+ shadow5: "rgba(0,0,0,0.32)",
+ shadow6: "rgba(0,0,0,0.4)",
};
const darkShadows = {
- shadow1: "rgba(0,0,0,0.2)",
- shadow2: "rgba(0,0,0,0.3)",
- shadow3: "rgba(0,0,0,0.4)",
- shadow4: "rgba(0,0,0,0.5)",
- shadow5: "rgba(0,0,0,0.6)",
- shadow6: "rgba(0,0,0,0.7)",
+ shadow1: "rgba(0,0,0,0.2)",
+ shadow2: "rgba(0,0,0,0.3)",
+ shadow3: "rgba(0,0,0,0.4)",
+ shadow4: "rgba(0,0,0,0.5)",
+ shadow5: "rgba(0,0,0,0.6)",
+ shadow6: "rgba(0,0,0,0.7)",
};
const builtThemes = createThemes({
- componentThemes: defaultComponentThemes,
- base: {
- palette: {
- dark: darkPalette,
- light: lightPalette,
- },
-
- extra: {
- light: {
- ...Colors.green,
- ...Colors.red,
- ...Colors.yellow,
- ...Colors.gray,
- ...lightShadows,
- shadowColor: lightShadows.shadow1,
- },
- dark: {
- ...Colors.greenDark,
- ...Colors.redDark,
- ...Colors.yellowDark,
- ...Colors.grayDark,
- ...darkShadows,
- shadowColor: darkShadows.shadow1,
- },
- },
+ accent: {
+ palette: {
+ dark: [...primaryPalette].reverse(),
+ light: [...primaryPalette].reverse(),
},
- accent: {
- palette: {
- dark: [...primaryPalette].reverse(),
- light: [...primaryPalette].reverse(),
- },
+ },
+ base: {
+ extra: {
+ dark: {
+ ...Colors.greenDark,
+ ...Colors.redDark,
+ ...Colors.yellowDark,
+ ...Colors.grayDark,
+ ...darkShadows,
+ shadowColor: darkShadows.shadow1,
+ },
+ light: {
+ ...Colors.green,
+ ...Colors.red,
+ ...Colors.yellow,
+ ...Colors.gray,
+ ...lightShadows,
+ shadowColor: lightShadows.shadow1,
+ },
},
- childrenThemes: {
- primary: {
- palette: {
- dark: [...primaryPalette].reverse(),
- light: [...primaryPalette].reverse(),
- },
- },
- gray: {
- palette: {
- dark: darkPalette,
- light: lightPalette,
- },
- },
- warning: {
- palette: {
- dark: Object.values(Colors.yellowDark),
- light: Object.values(Colors.yellow),
- },
- },
- error: {
- palette: {
- dark: Object.values(Colors.redDark),
- light: Object.values(Colors.red),
- },
- },
- success: {
- palette: {
- dark: Object.values(Colors.greenDark),
- light: Object.values(Colors.green),
- },
- },
+ palette: {
+ dark: darkPalette,
+ light: lightPalette,
},
+ },
+ childrenThemes: {
+ error: {
+ palette: {
+ dark: Object.values(Colors.redDark),
+ light: Object.values(Colors.red),
+ },
+ },
+ gray: {
+ palette: {
+ dark: darkPalette,
+ light: lightPalette,
+ },
+ },
+ primary: {
+ palette: {
+ dark: [...primaryPalette].reverse(),
+ light: [...primaryPalette].reverse(),
+ },
+ },
+ success: {
+ palette: {
+ dark: Object.values(Colors.greenDark),
+ light: Object.values(Colors.green),
+ },
+ },
+ warning: {
+ palette: {
+ dark: Object.values(Colors.yellowDark),
+ light: Object.values(Colors.yellow),
+ },
+ },
+ },
+ componentThemes: defaultComponentThemes,
});
export type Themes = typeof builtThemes;
@@ -126,6 +125,6 @@ export type Themes = typeof builtThemes;
// long as you are using the Vite, Next, Webpack plugins this should just work,
// but if not you can just export builtThemes directly as themes:
export const themes: Themes =
- process.env.TAMAGUI_ENVIRONMENT === "client" && process.env.NODE_ENV === "production"
- ? ({} as any)
- : (builtThemes as any);
+ process.env.TAMAGUI_ENVIRONMENT === "client" && process.env.NODE_ENV === "production"
+ ? ({} as any)
+ : (builtThemes as any);
diff --git a/apps/mobile-legacy/tsconfig.json b/apps/mobile-legacy/tsconfig.json
index 701ca08..508b8f5 100644
--- a/apps/mobile-legacy/tsconfig.json
+++ b/apps/mobile-legacy/tsconfig.json
@@ -1,21 +1,12 @@
{
- "extends": "expo/tsconfig.base",
- "exclude": ["__tests__/**/*-test.ts"],
"compilerOptions": {
- "strict": true,
"paths": {
- "@/*": [
- "./src/*"
- ],
- "~/*": [
- "./*"
- ],
- }
+ "@/*": ["./src/*"],
+ "~/*": ["./*"]
+ },
+ "strict": true
},
- "include": [
- "**/*.ts",
- "**/*.tsx",
- ".expo/types/**/*.ts",
- "expo-env.d.ts"
- ]
+ "exclude": ["__tests__/**/*-test.ts"],
+ "extends": "expo/tsconfig.base",
+ "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}
diff --git a/apps/mobile/app.json b/apps/mobile/app.json
index 80f0da4..662cf00 100644
--- a/apps/mobile/app.json
+++ b/apps/mobile/app.json
@@ -1,48 +1,48 @@
{
"expo": {
- "name": "mobile",
- "slug": "mobile",
- "version": "1.0.0",
- "orientation": "portrait",
- "icon": "./assets/images/icon.png",
- "scheme": "mobile",
- "userInterfaceStyle": "automatic",
- "newArchEnabled": true,
- "ios": {
- "supportsTablet": true
- },
"android": {
"adaptiveIcon": {
"backgroundColor": "#E6F4FE",
- "foregroundImage": "./assets/images/android-icon-foreground.png",
"backgroundImage": "./assets/images/android-icon-background.png",
+ "foregroundImage": "./assets/images/android-icon-foreground.png",
"monochromeImage": "./assets/images/android-icon-monochrome.png"
},
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false
},
- "web": {
- "output": "static",
- "favicon": "./assets/images/favicon.png"
+ "experiments": {
+ "reactCompiler": true,
+ "typedRoutes": true
},
+ "icon": "./assets/images/icon.png",
+ "ios": {
+ "supportsTablet": true
+ },
+ "name": "mobile",
+ "newArchEnabled": true,
+ "orientation": "portrait",
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
- "image": "./assets/images/splash-icon.png",
- "imageWidth": 200,
- "resizeMode": "contain",
"backgroundColor": "#ffffff",
"dark": {
"backgroundColor": "#000000"
- }
+ },
+ "image": "./assets/images/splash-icon.png",
+ "imageWidth": 200,
+ "resizeMode": "contain"
}
]
],
- "experiments": {
- "typedRoutes": true,
- "reactCompiler": true
+ "scheme": "mobile",
+ "slug": "mobile",
+ "userInterfaceStyle": "automatic",
+ "version": "1.0.0",
+ "web": {
+ "favicon": "./assets/images/favicon.png",
+ "output": "static"
}
}
}
diff --git a/apps/mobile/app/index.tsx b/apps/mobile/app/index.tsx
index 866b635..7c99b3b 100644
--- a/apps/mobile/app/index.tsx
+++ b/apps/mobile/app/index.tsx
@@ -4,9 +4,9 @@ export default function Index() {
return (
Edit app/index.tsx to edit this screen.
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 3240be0..0f6b069 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -1,15 +1,4 @@
{
- "name": "@basango/mobile",
- "main": "expo-router/entry",
- "version": "1.0.0",
- "scripts": {
- "start": "expo start",
- "reset-project": "node ./scripts/reset-project.js",
- "android": "expo start --android",
- "ios": "expo start --ios",
- "web": "expo start --web",
- "lint": "expo lint"
- },
"dependencies": {
"@expo/vector-icons": "^15.0.3",
"@react-navigation/bottom-tabs": "^7.4.0",
@@ -31,15 +20,26 @@
"react-dom": "catalog:",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
- "react-native-worklets": "0.5.1",
"react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
- "react-native-web": "~0.21.0"
+ "react-native-web": "~0.21.0",
+ "react-native-worklets": "0.5.1"
},
"devDependencies": {
"@types/react": "catalog:",
"typescript": "catalog:"
},
- "private": true
+ "main": "expo-router/entry",
+ "name": "@basango/mobile",
+ "private": true,
+ "scripts": {
+ "android": "expo start --android",
+ "ios": "expo start --ios",
+ "lint": "expo lint",
+ "reset-project": "node ./scripts/reset-project.js",
+ "start": "expo start",
+ "web": "expo start --web"
+ },
+ "version": "1.0.0"
}
diff --git a/apps/mobile/tsconfig.json b/apps/mobile/tsconfig.json
index 909e901..89098e8 100644
--- a/apps/mobile/tsconfig.json
+++ b/apps/mobile/tsconfig.json
@@ -1,17 +1,10 @@
{
- "extends": "expo/tsconfig.base",
"compilerOptions": {
- "strict": true,
"paths": {
- "@/*": [
- "./*"
- ]
- }
+ "@/*": ["./*"]
+ },
+ "strict": true
},
- "include": [
- "**/*.ts",
- "**/*.tsx",
- ".expo/types/**/*.ts",
- "expo-env.d.ts"
- ]
+ "extends": "expo/tsconfig.base",
+ "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}
diff --git a/biome.json b/biome.json
index ef79fc9..57ce865 100644
--- a/biome.json
+++ b/biome.json
@@ -1,12 +1,45 @@
{
- "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json",
- "vcs": {
- "enabled": true,
- "clientKind": "git",
- "useIgnoreFile": true
+ "$schema": "https://biomejs.dev/schemas/2.3.4/schema.json",
+ "assist": {
+ "actions": {
+ "source": {
+ "organizeImports": {
+ "level": "on",
+ "options": {
+ "groups": [
+ [":BUN:", ":NODE:"],
+ ":BLANK_LINE:",
+ [":PACKAGE:", ":URL:", ":PACKAGE_WITH_PROTOCOL:"],
+ ":BLANK_LINE:",
+ [":ALIAS:"],
+ ":BLANK_LINE:",
+ [":PATH:"]
+ ],
+ "identifierOrder": "lexicographic"
+ }
+ },
+ "useSortedAttributes": "on",
+ "useSortedKeys": "on",
+ "useSortedProperties": "on"
+ }
+ },
+ "enabled": true
+ },
+ "css": {
+ "formatter": {
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineEnding": "lf",
+ "lineWidth": 120,
+ "quoteStyle": "double"
+ },
+ "parser": {
+ "tailwindDirectives": true
+ }
},
"files": {
- "ignoreUnknown": false
+ "ignoreUnknown": true,
+ "includes": ["**/apps", "**/packages", "!/apps/api-legacy", "!/apps/mobile-legacy"]
},
"formatter": {
"enabled": true,
@@ -15,34 +48,28 @@
"lineEnding": "lf",
"lineWidth": 100
},
- "linter": {
- "enabled": true,
- "rules": {
- "recommended": true,
- "style": {
- "useImportType": "off",
- "noNonNullAssertion": "off"
- },
- "correctness": {
- "noUnusedImports": "on",
- "useImportExtensions": "off"
- }
- }
- },
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
- "assist": {
+ "linter": {
"enabled": true,
- "actions": {
- "source": {
- "organizeImports": "on",
- "useSortedKeys": "on",
- "useSortedAttributes": "on",
- "useSortedProperties": "on"
+ "rules": {
+ "correctness": {
+ "noUnusedImports": "on",
+ "useImportExtensions": "off"
+ },
+ "recommended": true,
+ "style": {
+ "noNonNullAssertion": "off",
+ "useImportType": "off"
}
}
+ },
+ "vcs": {
+ "clientKind": "git",
+ "enabled": true,
+ "useIgnoreFile": true
}
}
diff --git a/bun.lock b/bun.lock
index 53a83a2..cc0c264 100644
--- a/bun.lock
+++ b/bun.lock
@@ -4,7 +4,7 @@
"": {
"name": "basango",
"devDependencies": {
- "@basango/typescript-config": "workspace:*",
+ "@basango/tsconfig": "workspace:*",
"@biomejs/biome": "^2.3.1",
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
@@ -12,7 +12,6 @@
"commitizen": "^4.3.1",
"cz-conventional-changelog": "^3.3.0",
"husky": "^9.1.7",
- "lint-staged": "^16.2.6",
"turbo": "^2.5.8",
"typescript": "catalog:",
},
@@ -44,27 +43,7 @@
},
},
"packages/tsconfig": {
- "name": "@basango/typescript-config",
- },
- "packages/ui": {
- "name": "@basango/ui",
- "dependencies": {
- "@radix-ui/react-slot": "^1.2.4",
- "@tailwindcss/vite": "^4.1.17",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "lucide-react": "^0.553.0",
- "react": "^19.2.0",
- "react-dom": "^19.2.0",
- "tailwind-merge": "^3.3.1",
- "tailwindcss": "^4.1.17",
- "tw-animate-css": "^1.4.0",
- },
- "devDependencies": {
- "@basango/typescript-config": "workspace:*",
- "@types/bun": "catalog:",
- "typescript": "catalog:",
- },
+ "name": "@basango/tsconfig",
},
},
"catalog": {
@@ -87,9 +66,7 @@
"@basango/logger": ["@basango/logger@workspace:packages/logger"],
- "@basango/typescript-config": ["@basango/typescript-config@workspace:packages/tsconfig"],
-
- "@basango/ui": ["@basango/ui@workspace:packages/ui"],
+ "@basango/tsconfig": ["@basango/tsconfig@workspace:packages/tsconfig"],
"@biomejs/biome": ["@biomejs/biome@2.3.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.4", "@biomejs/cli-darwin-x64": "2.3.4", "@biomejs/cli-linux-arm64": "2.3.4", "@biomejs/cli-linux-arm64-musl": "2.3.4", "@biomejs/cli-linux-x64": "2.3.4", "@biomejs/cli-linux-x64-musl": "2.3.4", "@biomejs/cli-win32-arm64": "2.3.4", "@biomejs/cli-win32-x64": "2.3.4" }, "bin": { "biome": "bin/biome" } }, "sha512-TU08LXjBHdy0mEY9APtEtZdNQQijXUDSXR7IK1i45wgoPD5R0muK7s61QcFir6FpOj/RP1+YkPx5QJlycXUU3w=="],
@@ -203,16 +180,6 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
- "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
-
- "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
-
- "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
-
- "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
-
- "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
-
"@manypkg/cli": ["@manypkg/cli@0.25.1", "", { "dependencies": { "@manypkg/get-packages": "^3.1.0", "detect-indent": "^7.0.1", "normalize-path": "^3.0.0", "p-limit": "^6.2.0", "package-json": "^10.0.1", "parse-github-url": "^1.0.3", "picocolors": "^1.1.1", "sembear": "^0.7.0", "semver": "^7.7.1", "tinyexec": "^1.0.1", "validate-npm-package-name": "^6.0.0" }, "bin": { "manypkg": "bin.js" } }, "sha512-lag906FyiNxzZjsRErkUD5/to174I2JzPk5bZubuJp6loMKKJn73zrtqeU7nHlVkHBg3tgXDTJj22HxUDxLRXw=="],
"@manypkg/find-root": ["@manypkg/find-root@3.1.0", "", { "dependencies": { "@manypkg/tools": "^2.1.0" } }, "sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA=="],
@@ -229,90 +196,10 @@
"@pnpm/npm-conf": ["@pnpm/npm-conf@2.3.1", "", { "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" } }, "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw=="],
- "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
-
- "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
-
- "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
-
- "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="],
-
- "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="],
-
- "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="],
-
- "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="],
-
- "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="],
-
- "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="],
-
- "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="],
-
- "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="],
-
- "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="],
-
- "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="],
-
- "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="],
-
- "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="],
-
- "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="],
-
- "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="],
-
- "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="],
-
- "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="],
-
- "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="],
-
- "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="],
-
- "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="],
-
- "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="],
-
- "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
-
- "@tailwindcss/node": ["@tailwindcss/node@4.1.17", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.17" } }, "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg=="],
-
- "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.17", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.17", "@tailwindcss/oxide-darwin-arm64": "4.1.17", "@tailwindcss/oxide-darwin-x64": "4.1.17", "@tailwindcss/oxide-freebsd-x64": "4.1.17", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", "@tailwindcss/oxide-linux-x64-musl": "4.1.17", "@tailwindcss/oxide-wasm32-wasi": "4.1.17", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" } }, "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA=="],
-
- "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.17", "", { "os": "android", "cpu": "arm64" }, "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ=="],
-
- "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg=="],
-
- "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog=="],
-
- "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g=="],
-
- "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17", "", { "os": "linux", "cpu": "arm" }, "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ=="],
-
- "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ=="],
-
- "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg=="],
-
- "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ=="],
-
- "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ=="],
-
- "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.17", "", { "dependencies": { "@emnapi/core": "^1.6.0", "@emnapi/runtime": "^1.6.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.7", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg=="],
-
- "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A=="],
-
- "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.17", "", { "os": "win32", "cpu": "x64" }, "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw=="],
-
- "@tailwindcss/vite": ["@tailwindcss/vite@4.1.17", "", { "dependencies": { "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "tailwindcss": "4.1.17" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA=="],
-
"@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
"@types/conventional-commits-parser": ["@types/conventional-commits-parser@5.0.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g=="],
- "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
-
"@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
"@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="],
@@ -363,31 +250,23 @@
"chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
- "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
-
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
- "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="],
-
"cli-width": ["cli-width@3.0.0", "", {}, "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="],
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
- "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
-
"color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
"color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
- "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
-
- "commitizen": ["commitizen@4.3.1", "", { "dependencies": { "cachedir": "2.3.0", "cz-conventional-changelog": "3.3.0", "dedent": "0.7.0", "detect-indent": "6.1.0", "find-node-modules": "^2.1.2", "find-root": "1.1.0", "fs-extra": "9.1.0", "glob": "7.2.3", "inquirer": "8.2.5", "is-utf8": "^0.2.1", "lodash": "4.17.21", "minimist": "1.2.7", "strip-bom": "4.0.0", "strip-json-comments": "3.1.1" }, "bin": { "cz": "bin/git-cz", "git-cz": "bin/git-cz", "commitizen": "bin/commitizen" } }, "sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw=="],
+ "commitizen": ["commitizen@4.3.1", "", { "dependencies": { "cachedir": "2.3.0", "cz-conventional-changelog": "3.3.0", "dedent": "0.7.0", "detect-indent": "6.1.0", "find-node-modules": "^2.1.2", "find-root": "1.1.0", "fs-extra": "9.1.0", "glob": "7.2.3", "inquirer": "8.2.5", "is-utf8": "^0.2.1", "lodash": "4.17.21", "minimist": "1.2.7", "strip-bom": "4.0.0", "strip-json-comments": "3.1.1" }, "bin": { "commitizen": "bin/commitizen", "cz": "bin/git-cz", "git-cz": "bin/git-cz" } }, "sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw=="],
"compare-func": ["compare-func@2.0.0", "", { "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA=="],
@@ -427,8 +306,6 @@
"detect-indent": ["detect-indent@7.0.2", "", {}, "sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A=="],
- "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
-
"dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="],
"drizzle-kit": ["drizzle-kit@0.31.6", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-/B4e/4pwnx25QwD5xXgdpo1S+077a2VZdosXbItE/oNmUgQwZydGDz9qJYmnQl/b+5IX0rLfwRhrPnroGtrg8Q=="],
@@ -439,12 +316,8 @@
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
- "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
-
"env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
- "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
-
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
@@ -455,8 +328,6 @@
"escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
- "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
-
"expand-tilde": ["expand-tilde@2.0.2", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw=="],
"external-editor": ["external-editor@3.1.0", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="],
@@ -487,12 +358,8 @@
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
- "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
-
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
- "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
-
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
"git-raw-commits": ["git-raw-commits@4.0.0", "", { "dependencies": { "dargs": "^8.0.0", "meow": "^12.0.1", "split2": "^4.0.0" }, "bin": { "git-raw-commits": "cli.mjs" } }, "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ=="],
@@ -575,36 +442,8 @@
"ky": ["ky@1.14.0", "", {}, "sha512-Rczb6FMM6JT0lvrOlP5WUOCB7s9XKxzwgErzhKlKde1bEV90FXplV1o87fpt4PU/asJFiqjYJxAJyzJhcrxOsQ=="],
- "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
-
- "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
-
- "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
-
- "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
-
- "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
-
- "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
-
- "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
-
- "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
-
- "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
-
- "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
-
- "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
-
- "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
-
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
- "lint-staged": ["lint-staged@16.2.6", "", { "dependencies": { "commander": "^14.0.1", "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-s1gphtDbV4bmW1eylXpVMk2u7is7YsrLl8hzrtvC70h4ByhcMLZFY01Fx05ZUDNuv1H8HO4E+e2zgejV1jVwNw=="],
-
- "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="],
-
"locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
@@ -631,14 +470,8 @@
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
- "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
-
"longest": ["longest@2.0.1", "", {}, "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q=="],
- "lucide-react": ["lucide-react@0.553.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-BRgX5zrWmNy/lkVAe0dXBgd7XQdZ3HTf+Hwe3c9WK6dqgnj9h+hxV+MDncM88xDWlCq27+TKvHGE70ViODNILw=="],
-
- "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
-
"map-obj": ["map-obj@5.0.2", "", {}, "sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A=="],
"meow": ["meow@12.1.1", "", {}, "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw=="],
@@ -649,8 +482,6 @@
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
- "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
-
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"minimist": ["minimist@1.2.7", "", {}, "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="],
@@ -659,10 +490,6 @@
"mute-stream": ["mute-stream@0.0.8", "", {}, "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="],
- "nano-spawn": ["nano-spawn@2.0.0", "", {}, "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw=="],
-
- "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
-
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
@@ -711,9 +538,7 @@
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
- "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
-
- "pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="],
+ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"pino": ["pino@10.1.0", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w=="],
@@ -723,8 +548,6 @@
"pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="],
- "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
-
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
"postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
@@ -743,10 +566,6 @@
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
- "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
-
- "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
-
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
@@ -767,10 +586,6 @@
"restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
- "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
-
- "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
-
"run-async": ["run-async@2.4.1", "", {}, "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="],
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
@@ -781,8 +596,6 @@
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
- "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
-
"secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="],
"sembear": ["sembear@0.7.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-XyLTEich2D02FODCkfdto3mB9DetWPLuTzr4tvoofe9SvyM27h4nQSbV3+iVcYQz94AFyKtqBv5pcZbj3k2hdA=="],
@@ -791,22 +604,16 @@
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
- "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
-
"snakecase-keys": ["snakecase-keys@9.0.2", "", { "dependencies": { "change-case": "^5.4.4", "map-obj": "^5.0.2", "type-fest": "^4.15.0" } }, "sha512-Tr4gONsDj1Pa6HJH9D3b411r6tuRyCGgb1l7YpzDFp/thjVSWs7rcbNjyTyRqJi5SUV23sFpzf9epIJRbLR6Yw=="],
"sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="],
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
- "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
-
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
- "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
-
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
@@ -819,12 +626,6 @@
"supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
- "tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
-
- "tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="],
-
- "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
-
"text-extensions": ["text-extensions@2.4.0", "", {}, "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g=="],
"thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="],
@@ -855,8 +656,6 @@
"turbo-windows-arm64": ["turbo-windows-arm64@2.6.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1Ty+NwIksQY7AtFUCPrTpcKQE7zmd/f7aRjdT+qkqGFQjIjFYctEtN7qo4vpQPBgCfS1U3ka83A2u/9CfJQ3wQ=="],
- "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
-
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
@@ -871,8 +670,6 @@
"validate-npm-package-name": ["validate-npm-package-name@6.0.2", "", {}, "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ=="],
- "vite": ["vite@7.2.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ=="],
-
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
"which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
@@ -887,8 +684,6 @@
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
- "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="],
-
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
@@ -905,45 +700,21 @@
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
- "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
-
- "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
-
- "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
-
- "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="],
-
- "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
-
- "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
-
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
- "cli-truncate/string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="],
-
"commitizen/detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="],
"config-chain/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
- "fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
-
"global-prefix/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"inquirer/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "listr2/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
-
"log-symbols/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "log-update/ansi-escapes": ["ansi-escapes@7.2.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw=="],
-
- "log-update/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
-
- "log-update/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
-
- "log-update/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
+ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"ora/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -959,14 +730,6 @@
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
- "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
-
- "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
-
- "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
-
- "vite/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
-
"wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
@@ -1013,56 +776,28 @@
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
- "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
-
"inquirer/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"inquirer/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
- "listr2/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
-
- "listr2/wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
-
- "listr2/wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
-
"log-symbols/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"log-symbols/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
- "log-update/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
-
- "log-update/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
- "log-update/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
-
- "log-update/wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
-
"ora/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"ora/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"wrap-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
- "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
"inquirer/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"inquirer/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
- "listr2/wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
-
- "listr2/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
"log-symbols/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"log-symbols/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
- "log-update/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
-
- "log-update/cli-cursor/restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
-
- "log-update/wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
-
"ora/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"ora/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
diff --git a/package.json b/package.json
index 9336060..8a34fab 100644
--- a/package.json
+++ b/package.json
@@ -1,66 +1,15 @@
{
- "name": "basango",
- "private": true,
- "scripts": {
- "build": "turbo run build",
- "clean": "git clean -xdf node_modules",
- "clean:workspaces": "turbo run clean",
- "dev": "turbo run dev --parallel",
- "test": "turbo run test --parallel",
- "dev:dashboard": "turbo dev --filter=@basango/dashboard",
- "start:dashboard": "turbo start --filter=@basango/dashboard",
- "build:dashboard": "turbo build --filter=@basango/dashboard",
- "dev:api": "turbo dev --filter=@basango/api",
- "start:api": "turbo start --filter=@basango/api",
- "build:api": "turbo build --filter=@basango/api",
- "lint": "turbo run lint && manypkg check",
- "format": "biome format --write .",
- "typecheck": "turbo run typecheck"
- },
- "devDependencies": {
- "@basango/typescript-config": "workspace:*",
- "@biomejs/biome": "^2.3.1",
- "@commitlint/cli": "^20.1.0",
- "@commitlint/config-conventional": "^20.0.0",
- "@manypkg/cli": "^0.25.1",
- "commitizen": "^4.3.1",
- "cz-conventional-changelog": "^3.3.0",
- "husky": "^9.1.7",
- "lint-staged": "^16.2.6",
- "turbo": "^2.5.8",
- "typescript": "catalog:"
- },
- "engines": {
- "node": ">=22"
- },
- "packageManager": "bun@1.3.1",
- "workspaces": [
- "apps/crawler/*",
- "apps/dashboard/*",
- "apps/mobile/*",
- "packages/*"
- ],
"catalog": {
"@types/bun": "^1.3.1",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
- "typescript": "^5.9.3",
"date-fns": "^3.6.0",
+ "next": "^16.0.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "next": "^16.0.0",
+ "typescript": "^5.9.3",
"zod": "^4.0.0"
},
- "lint-staged": {
- "*.ts": [
- "biome format --write",
- "biome check --write"
- ],
- "*.tsx": [
- "biome format --write",
- "biome check --write"
- ]
- },
"commitlint": {
"extends": [
"@commitlint/config-conventional"
@@ -70,5 +19,45 @@
"commitizen": {
"path": "cz-conventional-changelog"
}
- }
+ },
+ "devDependencies": {
+ "@basango/tsconfig": "workspace:*",
+ "@biomejs/biome": "^2.3.1",
+ "@commitlint/cli": "^20.1.0",
+ "@commitlint/config-conventional": "^20.0.0",
+ "@manypkg/cli": "^0.25.1",
+ "commitizen": "^4.3.1",
+ "cz-conventional-changelog": "^3.3.0",
+ "husky": "^9.1.7",
+ "turbo": "^2.5.8",
+ "typescript": "catalog:"
+ },
+ "engines": {
+ "node": ">=22"
+ },
+ "name": "basango",
+ "packageManager": "bun@1.3.1",
+ "private": true,
+ "scripts": {
+ "build": "turbo run build",
+ "build:api": "turbo build --filter=@basango/api",
+ "build:dashboard": "turbo build --filter=@basango/dashboard",
+ "clean": "git clean -xdf node_modules",
+ "clean:workspaces": "turbo run clean",
+ "dev": "turbo run dev --parallel",
+ "dev:api": "turbo dev --filter=@basango/api",
+ "dev:dashboard": "turbo dev --filter=@basango/dashboard",
+ "format": "biome format --write && biome check --write && biome lint --write",
+ "lint": "biome check && biome lint && manypkg check",
+ "start:api": "turbo start --filter=@basango/api",
+ "start:dashboard": "turbo start --filter=@basango/dashboard",
+ "test": "turbo run test --parallel",
+ "typecheck": "turbo run typecheck"
+ },
+ "workspaces": [
+ "apps/crawler/*",
+ "apps/dashboard/*",
+ "apps/mobile/*",
+ "packages/*"
+ ]
}
diff --git a/packages/db/drizzle.config.ts b/packages/db/drizzle.config.ts
index dd77552..79c5dc8 100644
--- a/packages/db/drizzle.config.ts
+++ b/packages/db/drizzle.config.ts
@@ -1,10 +1,10 @@
import type { Config } from "drizzle-kit";
export default {
- schema: "./src/schema.ts",
- out: "./migrations",
- dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
+ dialect: "postgresql",
+ out: "./migrations",
+ schema: "./src/schema.ts",
} satisfies Config;
diff --git a/packages/db/package.json b/packages/db/package.json
index 0c79cc8..d108747 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -1,19 +1,4 @@
{
- "name": "@basango/db",
- "private": true,
- "scripts": {
- "clean": "rm -rf .turbo node_modules",
- "format": "biome format --write .",
- "lint": "biome check .",
- "lint:fix": "biome check --write .",
- "typecheck": "tsc --noEmit"
- },
- "exports": {
- "./client": "./src/client.ts",
- "./schema": "./src/schema.ts",
- "./utils": "./src/utils/index.ts",
- "./queries": "./src/queries/index.ts"
- },
"dependencies": {
"@basango/logger": "workspace:*",
"@date-fns/utc": "^2.1.1",
@@ -26,5 +11,17 @@
"@types/pg": "^8.15.6",
"drizzle-kit": "^0.31.6",
"typescript": "catalog:"
+ },
+ "exports": {
+ "./client": "./src/client.ts",
+ "./queries": "./src/queries/index.ts",
+ "./schema": "./src/schema.ts",
+ "./utils": "./src/utils/index.ts"
+ },
+ "name": "@basango/db",
+ "private": true,
+ "scripts": {
+ "clean": "rm -rf .turbo node_modules",
+ "typecheck": "tsc --noEmit"
}
}
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
index 42e491f..a8ba9b6 100644
--- a/packages/db/src/client.ts
+++ b/packages/db/src/client.ts
@@ -5,11 +5,11 @@ import * as schema from "@/schema";
const isDevelopment = process.env.NODE_ENV === "development";
const connectionConfig = {
- max: isDevelopment ? 8 : 12,
- idleTimeoutMillis: isDevelopment ? 5_000 : 60_000,
- connectionTimeoutMillis: 15_000,
- maxUses: isDevelopment ? 100 : 0,
allowExitOnIdle: true,
+ connectionTimeoutMillis: 15_000,
+ idleTimeoutMillis: isDevelopment ? 5_000 : 60_000,
+ max: isDevelopment ? 8 : 12,
+ maxUses: isDevelopment ? 100 : 0,
};
const pool = new Pool({
@@ -20,12 +20,12 @@ const pool = new Pool({
// Lightweight connection pool monitoring (single pool)
export const getConnectionPoolStats = () => {
const stats = {
+ active: Math.max(0, (pool.totalCount ?? 0) - (pool.idleCount ?? 0)),
+ ended: (pool as any).ended ?? false,
+ idle: pool.idleCount ?? 0,
name: "primary",
total: pool.options.max ?? 0,
- idle: pool.idleCount ?? 0,
- active: Math.max(0, (pool.totalCount ?? 0) - (pool.idleCount ?? 0)),
waiting: pool.waitingCount ?? 0,
- ended: (pool as any).ended ?? false,
};
const totalConnections = connectionConfig.max;
@@ -33,23 +33,23 @@ export const getConnectionPoolStats = () => {
totalConnections > 0 ? Math.round((stats.active / totalConnections) * 100) : 0;
return {
- timestamp: new Date().toISOString(),
- region: process.env.FLY_REGION || "unknown",
instance: process.env.FLY_ALLOC_ID || "local",
pools: { primary: stats },
+ region: process.env.FLY_REGION || "unknown",
summary: {
- totalConnections,
- totalActive: stats.active,
- totalWaiting: stats.waiting,
hasExhaustedPools: stats.active >= totalConnections || (stats.waiting ?? 0) > 0,
+ totalActive: stats.active,
+ totalConnections,
+ totalWaiting: stats.waiting,
utilizationPercent: utilization,
},
+ timestamp: new Date().toISOString(),
};
};
export const db = drizzle(pool, {
- schema,
casing: "snake_case",
+ schema,
});
export const connectDb = async () => db;
export type Database = Awaited>;
diff --git a/packages/db/src/queries/articles.ts b/packages/db/src/queries/articles.ts
index 1d6b864..98e92a5 100644
--- a/packages/db/src/queries/articles.ts
+++ b/packages/db/src/queries/articles.ts
@@ -133,16 +133,16 @@ export async function* getArticlesForExport(
let query = db
.select({
- articleId: articles.id,
- articleTitle: articles.title,
- articleLink: articles.link,
+ articleBody: articles.body,
articleCategories: sql`array_to_string
(${articles.categories}, ',')`,
- articleBody: articles.body,
- articleSource: sources.name,
- articleHash: articles.hash,
- articlePublishedAt: articles.publishedAt,
articleCrawledAt: articles.crawledAt,
+ articleHash: articles.hash,
+ articleId: articles.id,
+ articleLink: articles.link,
+ articlePublishedAt: articles.publishedAt,
+ articleSource: sources.name,
+ articleTitle: articles.title,
})
.from(articles)
.innerJoin(sources, eq(articles.sourceId, sources.id));
@@ -180,9 +180,9 @@ function normalizeArticleFilters(filters?: ArticleFilters): NormalizedArticleFil
const trimmedCategory = filters?.category?.trim();
return {
- search: trimmedSearch && trimmedSearch.length > 0 ? trimmedSearch : undefined,
category: trimmedCategory && trimmedCategory.length > 0 ? trimmedCategory : undefined,
dateRange: filters?.dateRange ?? null,
+ search: trimmedSearch && trimmedSearch.length > 0 ? trimmedSearch : undefined,
sortDirection: filters?.sortDirection ?? "desc",
};
}
@@ -255,22 +255,22 @@ async function fetchArticleOverview(
const bookmarkExpression = buildBookmarkExistsExpression(options.userId);
const selectFields = {
+ article_excerpt: articles.excerpt,
article_id: articles.id,
- articleTitle: articles.title,
- articleLink: articles.link,
+ article_image: articles.image,
+ article_is_bookmarked: bookmarkExpression,
+ article_published_at: articles.publishedAt,
+ article_reading_time: articles.readingTime,
articleCategories: sql`array_to_string
(${articles.categories}, ',')`,
- article_excerpt: articles.excerpt,
- article_published_at: articles.publishedAt,
- article_image: articles.image,
- article_reading_time: articles.readingTime,
- sourceId: sources.id,
+ articleLink: articles.link,
+ articleTitle: articles.title,
+ source_created_at: sources.createdAt,
source_display_name: sources.displayName,
source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
- sourceUrl: sources.url,
source_name: sources.name,
- source_created_at: sources.createdAt,
- article_is_bookmarked: bookmarkExpression,
+ sourceId: sources.id,
+ sourceUrl: sources.url,
} satisfies Record;
let query = db
@@ -321,8 +321,8 @@ async function fetchArticleOverview(
const rows = await query.orderBy(...orderings).limit(options.page.limit + 1);
return buildPaginationResult(rows, options.page, {
- id: "article_id",
date: "article_published_at",
+ id: "article_id",
});
}
@@ -338,9 +338,9 @@ export async function getArticleOverviewList(
const filters = normalizeArticleFilters(params.filters);
return fetchArticleOverview(db, {
- userId: params.userId,
- page,
filters,
+ page,
+ userId: params.userId,
});
}
@@ -357,10 +357,10 @@ export async function getSourceArticleOverviewList(
const filters = normalizeArticleFilters(params.filters);
return fetchArticleOverview(db, {
- userId: params.userId,
- page,
- filters,
baseConditions: [eq(sources.id, params.sourceId)],
+ filters,
+ page,
+ userId: params.userId,
});
}
@@ -384,22 +384,22 @@ export async function getBookmarkedArticleList(
];
const selectFields = {
+ article_excerpt: articles.excerpt,
article_id: articles.id,
- articleTitle: articles.title,
- articleLink: articles.link,
+ article_image: articles.image,
+ article_is_bookmarked: sql`true`,
+ article_published_at: articles.publishedAt,
+ article_reading_time: articles.readingTime,
articleCategories: sql`array_to_string
(${articles.categories}, ',')`,
- article_excerpt: articles.excerpt,
- article_published_at: articles.publishedAt,
- article_image: articles.image,
- article_reading_time: articles.readingTime,
- sourceId: sources.id,
+ articleLink: articles.link,
+ articleTitle: articles.title,
+ source_created_at: sources.createdAt,
source_display_name: sources.displayName,
source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
- sourceUrl: sources.url,
source_name: sources.name,
- source_created_at: sources.createdAt,
- article_is_bookmarked: sql`true`,
+ sourceId: sources.id,
+ sourceUrl: sources.url,
} satisfies Record;
let query = db
@@ -452,8 +452,8 @@ export async function getBookmarkedArticleList(
const rows = await query.orderBy(...orderings).limit(page.limit + 1);
return buildPaginationResult(rows, page, {
- id: "article_id",
date: "article_published_at",
+ id: "article_id",
});
}
@@ -465,33 +465,33 @@ export async function getArticleDetails(
const [row] = await db
.select({
+ article_bias: articles.bias,
+ article_crawled_at: articles.crawledAt,
+ article_hash: articles.hash,
article_id: articles.id,
- articleTitle: articles.title,
- articleLink: articles.link,
+ article_is_bookmarked: bookmarkExpression,
+ article_metadata: articles.metadata,
+ article_published_at: articles.publishedAt,
+ article_reading_time: articles.readingTime,
+ article_reliability: articles.reliability,
+ article_sentiment: articles.sentiment,
+ article_transparency: articles.transparency,
+ article_updated_at: articles.updatedAt,
+ articleBody: articles.body,
articleCategories: sql`array_to_string
(${articles.categories}, ',')`,
- articleBody: articles.body,
- article_hash: articles.hash,
- article_published_at: articles.publishedAt,
- article_crawled_at: articles.crawledAt,
- article_updated_at: articles.updatedAt,
- article_bias: articles.bias,
- article_reliability: articles.reliability,
- article_transparency: articles.transparency,
- article_sentiment: articles.sentiment,
- article_metadata: articles.metadata,
- article_reading_time: articles.readingTime,
- sourceId: sources.id,
- source_name: sources.name,
- source_description: sources.description,
- sourceUrl: sources.url,
- source_updated_at: sources.updatedAt,
- source_display_name: sources.displayName,
+ articleLink: articles.link,
+ articleTitle: articles.title,
source_bias: sources.bias,
+ source_description: sources.description,
+ source_display_name: sources.displayName,
+ source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
+ source_name: sources.name,
source_reliability: sources.reliability,
source_transparency: sources.transparency,
- source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
- article_is_bookmarked: bookmarkExpression,
+ source_updated_at: sources.updatedAt,
+ sourceId: sources.id,
+ sourceUrl: sources.url,
})
.from(articles)
.innerJoin(sources, eq(articles.sourceId, sources.id))
@@ -520,10 +520,10 @@ export async function getArticleCommentList(
let query = db
.select({
- comment_id: comments.id,
comment_content: comments.content,
- comment_sentiment: comments.sentiment,
comment_created_at: comments.createdAt,
+ comment_id: comments.id,
+ comment_sentiment: comments.sentiment,
user_id: users.id,
user_name: users.name,
})
@@ -541,7 +541,7 @@ export async function getArticleCommentList(
.limit(page.limit + 1);
return buildPaginationResult(rows, page, {
- id: "comment_id",
date: "comment_created_at",
+ id: "comment_id",
});
}
diff --git a/packages/db/src/queries/bookmarks.ts b/packages/db/src/queries/bookmarks.ts
index 1d56d92..95f3713 100644
--- a/packages/db/src/queries/bookmarks.ts
+++ b/packages/db/src/queries/bookmarks.ts
@@ -40,13 +40,13 @@ export async function getBookmarkList(
let query = db
.select({
- bookmark_id: bookmarks.id,
- bookmark_name: bookmarks.name,
- bookmark_description: bookmarks.description,
- bookmark_created_at: bookmarks.createdAt,
- bookmark_updated_at: bookmarks.updatedAt,
bookmark_articles_count: sql`count(${bookmarkArticles.articleId})`,
+ bookmark_created_at: bookmarks.createdAt,
+ bookmark_description: bookmarks.description,
+ bookmark_id: bookmarks.id,
bookmark_is_public: bookmarks.isPublic,
+ bookmark_name: bookmarks.name,
+ bookmark_updated_at: bookmarks.updatedAt,
})
.from(bookmarks)
.leftJoin(bookmarkArticles, eq(bookmarkArticles.bookmarkId, bookmarks.id))
diff --git a/packages/db/src/queries/sources.ts b/packages/db/src/queries/sources.ts
index a8fa02f..0485d11 100644
--- a/packages/db/src/queries/sources.ts
+++ b/packages/db/src/queries/sources.ts
@@ -2,6 +2,7 @@ import type { SQL } from "drizzle-orm";
import { and, desc, eq, lt, or, sql } from "drizzle-orm";
import type { Database } from "@/client";
+import { PUBLICATION_GRAPH_DAYS, SOURCE_IMAGE_BASE } from "@/constant";
import { articles, followedSources, sources } from "@/schema";
import {
buildPaginationResult,
@@ -10,7 +11,6 @@ import {
type PageRequest,
type PaginationMeta,
} from "@/utils/pagination";
-import { PUBLICATION_GRAPH_DAYS, SOURCE_IMAGE_BASE } from "@/constant";
export interface SourceOverviewRow {
sourceId: string;
@@ -70,14 +70,14 @@ export interface SourceStatisticsRow {
export async function getSourceStatisticsList(db: Database): Promise {
const rows = await db
.select({
- sourceId: sources.id,
- sourceName: sources.name,
- sourceCrawledAt: sql`max
- (${articles.crawledAt})`,
- articlesCount: sql`count
- (${articles.id})`,
articleMetadataAvailable: sql`sum
(CASE WHEN ${articles.metadata} IS NOT NULL THEN 1 ELSE 0 END)`,
+ articlesCount: sql`count
+ (${articles.id})`,
+ sourceCrawledAt: sql`max
+ (${articles.crawledAt})`,
+ sourceId: sources.id,
+ sourceName: sources.name,
})
.from(sources)
.leftJoin(articles, eq(articles.sourceId, sources.id))
@@ -85,11 +85,11 @@ export async function getSourceStatisticsList(db: Database): Promise ({
+ articleMetadataAvailable: Number(row.articleMetadataAvailable ?? 0),
+ articlesCount: Number(row.articlesCount ?? 0),
+ sourceCrawledAt: row.sourceCrawledAt,
sourceId: row.sourceId,
sourceName: row.sourceName,
- sourceCrawledAt: row.sourceCrawledAt,
- articlesCount: Number(row.articlesCount ?? 0),
- articleMetadataAvailable: Number(row.articleMetadataAvailable ?? 0),
}));
}
@@ -158,13 +158,13 @@ export async function getSourceOverviewList(
let query = db
.select({
- sourceId: sources.id,
+ source_created_at: sources.createdAt,
source_display_name: sources.displayName,
source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
- sourceUrl: sources.url,
- source_name: sources.name,
- source_created_at: sources.createdAt,
source_is_followed: followExpression,
+ source_name: sources.name,
+ sourceId: sources.id,
+ sourceUrl: sources.url,
})
.from(sources);
@@ -181,8 +181,8 @@ export async function getSourceOverviewList(
const rows = await query.orderBy(desc(sources.createdAt), desc(sources.id)).limit(page.limit + 1);
return buildPaginationResult(rows, page, {
- id: "sourceId",
date: "source_created_at",
+ id: "sourceId",
});
}
@@ -192,7 +192,7 @@ function createBackwardDateRange(days: number): { start: number; end: number } {
const startDate = new Date(now.getTime() - days * 86_400_000);
const start = Math.floor(startDate.getTime() / 1000);
- return { start, end };
+ return { end, start };
}
async function fetchPublicationGraph(db: Database, sourceId: string): Promise {
@@ -200,10 +200,10 @@ async function fetchPublicationGraph(db: Database, sourceId: string): Promise`date
- (${articles.publishedAt})`,
count: sql`count
(${articles.id})`,
+ day: sql`date
+ (${articles.publishedAt})`,
})
.from(articles)
.where(eq(articles.sourceId, sourceId))
@@ -233,7 +233,7 @@ async function fetchPublicationGraph(db: Database, sourceId: string): Promise`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
articles_count: sql`count
(${articles.id})`,
- source_crawled_at: sql`max
- (${articles.crawledAt})`,
articles_metadata_available: sql`count
(*)
FILTER (WHERE
@@ -300,7 +288,19 @@ export async function getSourceDetails(
NOT
NULL
)`,
+ source_bias: sources.bias,
+ source_crawled_at: sql`max
+ (${articles.crawledAt})`,
+ source_description: sources.description,
+ source_display_name: sources.displayName,
+ source_image: sql`('${SOURCE_IMAGE_BASE}' || ${sources.name} || '.png')`,
source_is_followed: followExpression,
+ source_name: sources.name,
+ source_reliability: sources.reliability,
+ source_transparency: sources.transparency,
+ source_updated_at: sources.updatedAt,
+ sourceId: sources.id,
+ sourceUrl: sources.url,
})
.from(sources)
.leftJoin(articles, eq(articles.sourceId, sources.id))
@@ -328,12 +328,12 @@ export async function getSourceDetails(
]);
return {
+ categoryShares,
+ publicationGraph,
source: {
...row,
articles_count: Number(row.articles_count ?? 0),
articles_metadata_available: Number(row.articles_metadata_available ?? 0),
},
- publicationGraph,
- categoryShares,
};
}
diff --git a/packages/db/src/queries/users.ts b/packages/db/src/queries/users.ts
index 3d8aee5..f67f09b 100644
--- a/packages/db/src/queries/users.ts
+++ b/packages/db/src/queries/users.ts
@@ -17,10 +17,10 @@ export async function getUserProfile(
): Promise {
const [row] = await db
.select({
+ user_created_at: users.createdAt,
+ user_email: users.email,
user_id: users.id,
user_name: users.name,
- user_email: users.email,
- user_created_at: users.createdAt,
user_updated_at: users.updatedAt,
})
.from(users)
diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts
index b2f97fc..8e46470 100644
--- a/packages/db/src/schema.ts
+++ b/packages/db/src/schema.ts
@@ -5,9 +5,9 @@ import {
doublePrecision,
foreignKey,
index,
+ inet,
integer,
jsonb,
- inet,
pgEnum,
pgTable,
primaryKey,
@@ -75,16 +75,16 @@ export const verificationTokenPurposeEnum = pgEnum("verification_token_purpose",
export const sources = pgTable(
"source",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- url: varchar("url", { length: 255 }).notNull(),
- name: varchar("name", { length: 255 }).notNull(),
- displayName: varchar("display_name", { length: 255 }),
- description: varchar("description", { length: 1024 }),
- createdAt: timestamp("created_at", { mode: "string" }).defaultNow().notNull(),
- updatedAt: timestamp("updated_at", { mode: "string" }),
bias: biasEnum("bias").notNull().default("neutral"),
+ createdAt: timestamp("created_at", { mode: "string" }).defaultNow().notNull(),
+ description: varchar("description", { length: 1024 }),
+ displayName: varchar("display_name", { length: 255 }),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ name: varchar("name", { length: 255 }).notNull(),
reliability: reliabilityEnum("reliability").notNull().default("reliable"),
transparency: transparencyEnum("transparency").notNull().default("medium"),
+ updatedAt: timestamp("updated_at", { mode: "string" }),
+ url: varchar("url", { length: 255 }).notNull(),
},
(table) => [
uniqueIndex("unq_source_name").using(
@@ -103,33 +103,33 @@ export const sources = pgTable(
export const articles = pgTable(
"article",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- sourceId: uuid("sourceId").notNull(),
- title: varchar("title", { length: 1024 }).notNull(),
+ bias: biasEnum("bias").notNull().default("neutral"),
body: text("body").notNull(),
- hash: varchar("hash", { length: 32 }).notNull(),
categories: text("categories").array(),
- sentiment: articleSentimentEnum("sentiment").notNull().default("neutral"),
- metadata: jsonb("metadata"),
- tokenStatistics: jsonb("token_statistics"),
- image: varchar("image", { length: 1024 }).generatedAlwaysAs(() => sql`(metadata->>'image')`),
+ crawledAt: timestamp("crawled_at", { mode: "string" }).notNull(),
excerpt: varchar("excerpt", { length: 255 }).generatedAlwaysAs(
() => sql`((left(body, 200) || '...'))`,
),
- publishedAt: timestamp("published_at", { mode: "string" }).notNull(),
- crawledAt: timestamp("crawled_at", { mode: "string" }).notNull(),
- updatedAt: timestamp("updated_at", { mode: "string" }),
+ hash: varchar("hash", { length: 32 }).notNull(),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ image: varchar("image", { length: 1024 }).generatedAlwaysAs(() => sql`(metadata->>'image')`),
link: varchar("link", { length: 1024 }).notNull(),
- bias: biasEnum("bias").notNull().default("neutral"),
- reliability: reliabilityEnum("reliability").notNull().default("reliable"),
- transparency: transparencyEnum("transparency").notNull().default("medium"),
+ metadata: jsonb("metadata"),
+ publishedAt: timestamp("published_at", { mode: "string" }).notNull(),
readingTime: integer("reading_time").default(1),
+ reliability: reliabilityEnum("reliability").notNull().default("reliable"),
+ sentiment: articleSentimentEnum("sentiment").notNull().default("neutral"),
+ sourceId: uuid("sourceId").notNull(),
+ title: varchar("title", { length: 1024 }).notNull(),
+ tokenStatistics: jsonb("token_statistics"),
+ transparency: transparencyEnum("transparency").notNull().default("medium"),
tsv: tsvector("tsv").generatedAlwaysAs(
() => sql`(
setweight(to_tsvector('french', coalesce(title, '')), 'A')
|| setweight(to_tsvector('french', coalesce(body, '')), 'B')
)`,
),
+ updatedAt: timestamp("updated_at", { mode: "string" }),
},
(table) => [
index("article_sourceId_idx").on(table.sourceId),
@@ -146,13 +146,13 @@ export const articles = pgTable(
name: "article_sourceId_fkey",
}).onDelete("cascade"),
{
- kind: "check",
expression: sql`reading_time >= 0`,
+ kind: "check",
name: "chk_article_reading_time",
},
{
- kind: "check",
expression: sql`(metadata IS NULL OR jsonb_typeof(metadata) IN ('object','array'))`,
+ kind: "check",
name: "chk_article_metadata_json",
},
],
@@ -161,22 +161,22 @@ export const articles = pgTable(
export const users = pgTable(
"user",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- name: varchar("name", { length: 255 }).notNull(),
- email: varchar("email", { length: 255 }).notNull(),
- password: varchar("password", { length: 512 }).notNull(),
- isLocked: boolean("is_locked").notNull().default(false),
- isConfirmed: boolean("is_confirmed").notNull().default(false),
createdAt: timestamp("created_at", { mode: "string" }).notNull(),
- updatedAt: timestamp("updated_at", { mode: "string" }),
+ email: varchar("email", { length: 255 }).notNull(),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ isConfirmed: boolean("is_confirmed").notNull().default(false),
+ isLocked: boolean("is_locked").notNull().default(false),
+ name: varchar("name", { length: 255 }).notNull(),
+ password: varchar("password", { length: 512 }).notNull(),
roles: jsonb("roles").notNull(),
+ updatedAt: timestamp("updated_at", { mode: "string" }),
},
(table) => [
uniqueIndex("unq_user_email").using("btree", sql`lower (${table.email})`),
{
+ expression: sql`jsonb_typeof(roles) = 'array'`,
kind: "check",
name: "chk_user_roles_array",
- expression: sql`jsonb_typeof(roles) = 'array'`,
},
],
);
@@ -184,13 +184,13 @@ export const users = pgTable(
export const bookmarks = pgTable(
"bookmark",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- userId: uuid("user_id").notNull(),
- name: varchar("name", { length: 255 }).notNull(),
- description: varchar("description", { length: 512 }),
- isPublic: boolean("is_public").notNull().default(false),
createdAt: timestamp("created_at", { mode: "string" }).notNull(),
+ description: varchar("description", { length: 512 }),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ isPublic: boolean("is_public").notNull().default(false),
+ name: varchar("name", { length: 255 }).notNull(),
updatedAt: timestamp("updated_at", { mode: "string" }),
+ userId: uuid("user_id").notNull(),
},
(table) => [
index("bookmark_user_id_idx").on(table.userId),
@@ -206,8 +206,8 @@ export const bookmarks = pgTable(
export const bookmarkArticles = pgTable(
"bookmark_article",
{
- bookmarkId: uuid("bookmark_id").notNull(),
articleId: uuid("article_id").notNull(),
+ bookmarkId: uuid("bookmark_id").notNull(),
},
(table) => [
primaryKey({
@@ -232,13 +232,13 @@ export const bookmarkArticles = pgTable(
export const comments = pgTable(
"comment",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- userId: uuid("user_id").notNull(),
articleId: uuid("article_id").notNull(),
content: varchar("content", { length: 512 }).notNull(),
- sentiment: articleSentimentEnum("sentiment").notNull().default("neutral"),
- isSpam: boolean("is_spam").notNull().default(false),
createdAt: timestamp("created_at", { mode: "string" }).notNull(),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ isSpam: boolean("is_spam").notNull().default(false),
+ sentiment: articleSentimentEnum("sentiment").notNull().default("neutral"),
+ userId: uuid("user_id").notNull(),
},
(table) => [
index("comment_user_id_idx").on(table.userId),
@@ -260,10 +260,10 @@ export const comments = pgTable(
export const followedSources = pgTable(
"followed_source",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- followerId: uuid("follower_id").notNull(),
- sourceId: uuid("sourceId").notNull(),
createdAt: timestamp("created_at", { mode: "string" }).notNull(),
+ followerId: uuid("follower_id").notNull(),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ sourceId: uuid("sourceId").notNull(),
},
(table) => [
index("followed_source_follower_idx").on(table.followerId),
@@ -289,9 +289,9 @@ export const followedSources = pgTable(
export const loginAttempts = pgTable(
"login_attempt",
{
+ createdAt: timestamp("created_at", { mode: "string" }).notNull(),
id: uuid("id").notNull().defaultRandom().primaryKey(),
userId: uuid("user_id").notNull(),
- createdAt: timestamp("created_at", { mode: "string" }).notNull(),
},
(table) => [
index("login_attempt_user_id_idx").on(table.userId),
@@ -307,18 +307,18 @@ export const loginAttempts = pgTable(
export const loginHistories = pgTable(
"login_history",
{
- id: uuid("id").notNull().defaultRandom().primaryKey(),
- userId: uuid("user_id").notNull(),
- ipAddress: inet("ip_address"),
createdAt: timestamp("created_at", { mode: "string" }).notNull(),
- deviceOperatingSystem: varchar("device_operating_system", { length: 255 }),
deviceClient: varchar("device_client", { length: 255 }),
deviceDevice: varchar("device_device", { length: 255 }),
deviceIsBot: boolean("device_is_bot").notNull().default(false),
- locationTimeZone: varchar("location_time_zone", { length: 255 }),
- locationLongitude: doublePrecision("location_longitude"),
- locationLatitude: doublePrecision("location_latitude"),
+ deviceOperatingSystem: varchar("device_operating_system", { length: 255 }),
+ id: uuid("id").notNull().defaultRandom().primaryKey(),
+ ipAddress: inet("ip_address"),
locationAccuracyRadius: integer("location_accuracy_radius"),
+ locationLatitude: doublePrecision("location_latitude"),
+ locationLongitude: doublePrecision("location_longitude"),
+ locationTimeZone: varchar("location_time_zone", { length: 255 }),
+ userId: uuid("user_id").notNull(),
},
(table) => [
index("login_history_user_id_idx").on(table.userId),
@@ -346,11 +346,11 @@ export const refreshTokens = pgTable(
export const verificationTokens = pgTable(
"verification_token",
{
+ createdAt: timestamp("created_at", { mode: "string" }).notNull(),
id: uuid("id").notNull().defaultRandom().primaryKey(),
- userId: uuid("user_id").notNull(),
purpose: verificationTokenPurposeEnum("purpose").notNull(),
token: varchar("token", { length: 60 }),
- createdAt: timestamp("created_at", { mode: "string" }).notNull(),
+ userId: uuid("user_id").notNull(),
},
(table) => [
index("verification_token_user_id_idx").on(table.userId),
@@ -374,40 +374,40 @@ export const sourcesRelations = relations(sources, ({ many }) => ({
}));
export const articlesRelations = relations(articles, ({ one, many }) => ({
+ bookmarkLinks: many(bookmarkArticles),
+ comments: many(comments),
source: one(sources, {
fields: [articles.sourceId],
references: [sources.id],
}),
- bookmarkLinks: many(bookmarkArticles),
- comments: many(comments),
}));
export const appUsersRelations = relations(users, ({ many }) => ({
bookmarks: many(bookmarks),
comments: many(comments),
+ followedSources: many(followedSources),
loginAttempts: many(loginAttempts),
loginHistories: many(loginHistories),
verificationTokens: many(verificationTokens),
- followedSources: many(followedSources),
}));
export const bookmarksRelations = relations(bookmarks, ({ one, many }) => ({
+ articles: many(bookmarkArticles),
user: one(users, {
fields: [bookmarks.userId],
references: [users.id],
}),
- articles: many(bookmarkArticles),
}));
export const bookmarkArticlesRelations = relations(bookmarkArticles, ({ one }) => ({
- bookmark: one(bookmarks, {
- fields: [bookmarkArticles.bookmarkId],
- references: [bookmarks.id],
- }),
article: one(articles, {
fields: [bookmarkArticles.articleId],
references: [articles.id],
}),
+ bookmark: one(bookmarks, {
+ fields: [bookmarkArticles.bookmarkId],
+ references: [bookmarks.id],
+ }),
}));
export const commentsRelations = relations(comments, ({ one }) => ({
diff --git a/packages/db/src/utils/pagination.ts b/packages/db/src/utils/pagination.ts
index a8ff83e..a740bc2 100644
--- a/packages/db/src/utils/pagination.ts
+++ b/packages/db/src/utils/pagination.ts
@@ -53,7 +53,7 @@ export function createPageState(request: PageRequest = {}): PageState {
const cursor = request.cursor ?? null;
const offset = (page - 1) * limit;
- return { page, limit, cursor, offset };
+ return { cursor, limit, offset, page };
}
export function encodeCursor(
@@ -111,9 +111,9 @@ export function buildPaginationResult>(
data,
pagination: {
current: page.page,
- limit: page.limit,
cursor,
hasNext,
+ limit: page.limit,
},
};
}
diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json
index 57633ea..8f5ca5d 100644
--- a/packages/db/tsconfig.json
+++ b/packages/db/tsconfig.json
@@ -1,11 +1,11 @@
{
- "extends": "@basango/typescript-config/base.json",
- "include": ["src"],
- "exclude": ["node_modules"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
- }
+ },
+ "exclude": ["node_modules"],
+ "extends": "@basango/tsconfig/base.json",
+ "include": ["src"]
}
diff --git a/packages/logger/package.json b/packages/logger/package.json
index 3dccf8a..e8efbb2 100644
--- a/packages/logger/package.json
+++ b/packages/logger/package.json
@@ -1,21 +1,18 @@
{
- "name": "@basango/logger",
- "private": true,
- "type": "module",
- "main": "src/index.ts",
- "types": "src/index.ts",
- "scripts": {
- "clean": "rm -rf .turbo node_modules",
- "format": "biome format --write .",
- "lint": "biome check .",
- "lint:fix": "biome check --write .",
- "typecheck": "tsc --noEmit"
+ "dependencies": {
+ "pino": "^10.1.0",
+ "pino-pretty": "^13.1.2"
},
"devDependencies": {
"typescript": "catalog:"
},
- "dependencies": {
- "pino": "^10.1.0",
- "pino-pretty": "^13.1.2"
- }
+ "main": "src/index.ts",
+ "name": "@basango/logger",
+ "private": true,
+ "scripts": {
+ "clean": "rm -rf .turbo node_modules",
+ "typecheck": "tsc --noEmit"
+ },
+ "type": "module",
+ "types": "src/index.ts"
}
diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts
index f55594b..9b2c18f 100644
--- a/packages/logger/src/index.ts
+++ b/packages/logger/src/index.ts
@@ -5,14 +5,14 @@ export const logger = pino({
// Use pretty printing in development, structured JSON in production
...(process.env.NODE_ENV !== "production" && {
transport: {
- target: "pino-pretty",
options: {
colorize: true,
- translateTime: "HH:MM:ss",
+ hideObject: false,
ignore: "pid,hostname",
messageFormat: true,
- hideObject: false,
+ translateTime: "HH:MM:ss",
},
+ target: "pino-pretty",
},
}),
});
diff --git a/packages/logger/tsconfig.json b/packages/logger/tsconfig.json
index 7ed58ff..c390cc9 100644
--- a/packages/logger/tsconfig.json
+++ b/packages/logger/tsconfig.json
@@ -1,5 +1,5 @@
{
- "extends": "@basango/typescript-config/base.json",
- "include": ["src/**/*"],
- "exclude": ["node_modules"]
+ "exclude": ["node_modules"],
+ "extends": "@basango/tsconfig/base.json",
+ "include": ["src/**/*"]
}
diff --git a/packages/typescript-config/base.json b/packages/tsconfig/base.json
similarity index 94%
rename from packages/typescript-config/base.json
rename to packages/tsconfig/base.json
index 0f80cfd..5c7e6cb 100644
--- a/packages/typescript-config/base.json
+++ b/packages/tsconfig/base.json
@@ -1,6 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
- "display": "Default",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
@@ -16,5 +15,6 @@
"skipLibCheck": true,
"strict": true,
"target": "ES2022"
- }
+ },
+ "display": "Default"
}
diff --git a/packages/typescript-config/nextjs.json b/packages/tsconfig/nextjs.json
similarity index 70%
rename from packages/typescript-config/nextjs.json
rename to packages/tsconfig/nextjs.json
index 44f4289..49df921 100644
--- a/packages/typescript-config/nextjs.json
+++ b/packages/tsconfig/nextjs.json
@@ -1,13 +1,13 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
- "display": "Next.js",
- "extends": "./base.json",
"compilerOptions": {
- "plugins": [{ "name": "next" }],
- "module": "ESNext",
- "moduleResolution": "Bundler",
"allowJs": true,
"jsx": "preserve",
- "noEmit": true
- }
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "noEmit": true,
+ "plugins": [{ "name": "next" }]
+ },
+ "display": "Next.js",
+ "extends": "./base.json"
}
diff --git a/packages/typescript-config/package.json b/packages/tsconfig/package.json
similarity index 71%
rename from packages/typescript-config/package.json
rename to packages/tsconfig/package.json
index c18cb5c..ff8ce54 100644
--- a/packages/typescript-config/package.json
+++ b/packages/tsconfig/package.json
@@ -1,7 +1,7 @@
{
- "name": "@basango/typescript-config",
- "private": true,
"license": "PROPRIETARY",
+ "name": "@basango/tsconfig",
+ "private": true,
"publishConfig": {
"access": "public"
}
diff --git a/packages/typescript-config/react-library.json b/packages/tsconfig/react-library.json
similarity index 80%
rename from packages/typescript-config/react-library.json
rename to packages/tsconfig/react-library.json
index 44924d9..3df370d 100644
--- a/packages/typescript-config/react-library.json
+++ b/packages/tsconfig/react-library.json
@@ -1,8 +1,8 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
- "display": "React Library",
- "extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx"
- }
+ },
+ "display": "React Library",
+ "extends": "./base.json"
}
diff --git a/packages/ui/components.json b/packages/ui/components.json
index 6032395..7bb49fd 100644
--- a/packages/ui/components.json
+++ b/packages/ui/components.json
@@ -1,20 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
- "style": "new-york",
- "rsc": true,
- "tsx": true,
- "tailwind": {
- "config": "",
- "css": "src/styles/globals.css",
- "baseColor": "neutral",
- "cssVariables": true
- },
- "iconLibrary": "lucide",
"aliases": {
"components": "@basango/ui/components",
- "utils": "@basango/ui/lib/utils",
"hooks": "@basango/ui/hooks",
"lib": "@basango/ui/lib",
- "ui": "@basango/ui/components"
- }
+ "ui": "@basango/ui/components",
+ "utils": "@basango/ui/lib/utils"
+ },
+ "iconLibrary": "lucide",
+ "rsc": true,
+ "style": "new-york",
+ "tailwind": {
+ "baseColor": "neutral",
+ "config": "",
+ "css": "src/styles/globals.css",
+ "cssVariables": true
+ },
+ "tsx": true
}
diff --git a/packages/ui/postcss.config.mjs b/packages/ui/postcss.config.mjs
index 4ae682d..c15b998 100644
--- a/packages/ui/postcss.config.mjs
+++ b/packages/ui/postcss.config.mjs
@@ -1,6 +1,6 @@
/** @type {import('postcss-load-config').Config} */
const config = {
- plugins: { "@tailwindcss/postcss": {} },
+ plugins: { "@tailwindcss/postcss": {} },
};
export default config;
diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx
index 7c658fc..1aa4589 100644
--- a/packages/ui/src/components/button.tsx
+++ b/packages/ui/src/components/button.tsx
@@ -1,59 +1,55 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@basango/ui/lib/utils"
+import { cn } from "@basango/ui/lib/utils";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
+import * as React from "react";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
+ defaultVariants: {
+ size: "default",
+ variant: "default",
+ },
variants: {
- variant: {
- default:
- "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
- destructive:
- "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
- outline:
- "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
- secondary:
- "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
- ghost:
- "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
- link: "text-primary underline-offset-4 hover:underline",
- },
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
+ },
+ variant: {
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
+ link: "text-primary underline-offset-4 hover:underline",
+ outline:
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
},
},
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
+ },
+);
function Button({
- className,
- variant,
- size,
- asChild = false,
- ...props
- }: React.ComponentProps<"button"> &
+ className,
+ variant,
+ size,
+ asChild = false,
+ ...props
+}: React.ComponentProps<"button"> &
VariantProps & {
- asChild?: boolean
-}) {
- const Comp = asChild ? Slot : "button"
+ asChild?: boolean;
+ }) {
+ const Comp = asChild ? Slot : "button";
return (
- )
+ );
}
-export { Button, buttonVariants }
+export { Button, buttonVariants };
diff --git a/packages/ui/src/lib/utils.ts b/packages/ui/src/lib/utils.ts
index bd0c391..365058c 100644
--- a/packages/ui/src/lib/utils.ts
+++ b/packages/ui/src/lib/utils.ts
@@ -1,6 +1,6 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
}
diff --git a/packages/ui/src/package.json b/packages/ui/src/package.json
index 716c6f7..02bfe51 100644
--- a/packages/ui/src/package.json
+++ b/packages/ui/src/package.json
@@ -1,10 +1,4 @@
{
- "name": "@basango/ui",
- "type": "module",
- "private": true,
- "scripts": {
- "lint": "eslint . --max-warnings 0"
- },
"dependencies": {
"@radix-ui/react-slot": "^1.2.3",
"class-variance-authority": "^0.7.1",
@@ -18,20 +12,26 @@
"zod": "^3.25.76"
},
"devDependencies": {
+ "@basango/tsconfig": "workspace:*",
"@tailwindcss/postcss": "^4.1.11",
"@turbo/gen": "^2.5.5",
"@types/node": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
- "@basango/typescript-config": "workspace:*",
"tailwindcss": "^4.1.11",
"typescript": "catalog:"
},
"exports": {
- "./globals.css": "./src/styles/globals.css",
- "./postcss.config": "./postcss.config.mjs",
- "./lib/*": "./src/lib/*.ts",
"./components/*": "./src/components/*.tsx",
- "./hooks/*": "./src/hooks/*.ts"
- }
+ "./globals.css": "./src/styles/globals.css",
+ "./hooks/*": "./src/hooks/*.ts",
+ "./lib/*": "./src/lib/*.ts",
+ "./postcss.config": "./postcss.config.mjs"
+ },
+ "name": "@basango/ui",
+ "private": true,
+ "scripts": {
+ "lint": "eslint . --max-warnings 0"
+ },
+ "type": "module"
}
diff --git a/packages/ui/src/styles/global.css b/packages/ui/src/styles/global.css
index 757a8c2..9848899 100644
--- a/packages/ui/src/styles/global.css
+++ b/packages/ui/src/styles/global.css
@@ -1,127 +1,127 @@
@import "tailwindcss";
+@import "tw-animate-css";
+
@source "../../../apps/**/*.{ts,tsx}";
@source "../../../components/**/*.{ts,tsx}";
@source "../**/*.{ts,tsx}";
-@import "tw-animate-css";
-
@custom-variant dark (&:is(.dark *));
:root {
- --background: oklch(1 0 0);
- --foreground: oklch(0.145 0 0);
- --card: oklch(1 0 0);
- --card-foreground: oklch(0.145 0 0);
- --popover: oklch(1 0 0);
- --popover-foreground: oklch(0.145 0 0);
- --primary: oklch(0.205 0 0);
- --primary-foreground: oklch(0.985 0 0);
- --secondary: oklch(0.97 0 0);
- --secondary-foreground: oklch(0.205 0 0);
- --muted: oklch(0.97 0 0);
- --muted-foreground: oklch(0.556 0 0);
- --accent: oklch(0.97 0 0);
- --accent-foreground: oklch(0.205 0 0);
- --destructive: oklch(0.577 0.245 27.325);
- --destructive-foreground: oklch(0.577 0.245 27.325);
- --border: oklch(0.922 0 0);
- --input: oklch(0.922 0 0);
- --ring: oklch(0.708 0 0);
- --chart-1: oklch(0.646 0.222 41.116);
- --chart-2: oklch(0.6 0.118 184.704);
- --chart-3: oklch(0.398 0.07 227.392);
- --chart-4: oklch(0.828 0.189 84.429);
- --chart-5: oklch(0.769 0.188 70.08);
- --radius: 0.625rem;
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.145 0 0);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
+ --primary: oklch(0.205 0 0);
+ --primary-foreground: oklch(0.985 0 0);
+ --secondary: oklch(0.97 0 0);
+ --secondary-foreground: oklch(0.205 0 0);
+ --muted: oklch(0.97 0 0);
+ --muted-foreground: oklch(0.556 0 0);
+ --accent: oklch(0.97 0 0);
+ --accent-foreground: oklch(0.205 0 0);
+ --destructive: oklch(0.577 0.245 27.325);
+ --destructive-foreground: oklch(0.577 0.245 27.325);
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ --radius: 0.625rem;
+ --sidebar: oklch(0.985 0 0);
+ --sidebar-foreground: oklch(0.145 0 0);
+ --sidebar-primary: oklch(0.205 0 0);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.97 0 0);
+ --sidebar-accent-foreground: oklch(0.205 0 0);
+ --sidebar-border: oklch(0.922 0 0);
+ --sidebar-ring: oklch(0.708 0 0);
}
.dark {
- --background: oklch(0.145 0 0);
- --foreground: oklch(0.985 0 0);
- --card: oklch(0.145 0 0);
- --card-foreground: oklch(0.985 0 0);
- --popover: oklch(0.145 0 0);
- --popover-foreground: oklch(0.985 0 0);
- --primary: oklch(0.985 0 0);
- --primary-foreground: oklch(0.205 0 0);
- --secondary: oklch(0.269 0 0);
- --secondary-foreground: oklch(0.985 0 0);
- --muted: oklch(0.269 0 0);
- --muted-foreground: oklch(0.708 0 0);
- --accent: oklch(0.269 0 0);
- --accent-foreground: oklch(0.985 0 0);
- --destructive: oklch(0.396 0.141 25.723);
- --destructive-foreground: oklch(0.637 0.237 25.331);
- --border: oklch(0.269 0 0);
- --input: oklch(0.269 0 0);
- --ring: oklch(0.556 0 0);
- --chart-1: oklch(0.488 0.243 264.376);
- --chart-2: oklch(0.696 0.17 162.48);
- --chart-3: oklch(0.769 0.188 70.08);
- --chart-4: oklch(0.627 0.265 303.9);
- --chart-5: oklch(0.645 0.246 16.439);
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(0.269 0 0);
- --sidebar-ring: oklch(0.439 0 0);
+ --background: oklch(0.145 0 0);
+ --foreground: oklch(0.985 0 0);
+ --card: oklch(0.145 0 0);
+ --card-foreground: oklch(0.985 0 0);
+ --popover: oklch(0.145 0 0);
+ --popover-foreground: oklch(0.985 0 0);
+ --primary: oklch(0.985 0 0);
+ --primary-foreground: oklch(0.205 0 0);
+ --secondary: oklch(0.269 0 0);
+ --secondary-foreground: oklch(0.985 0 0);
+ --muted: oklch(0.269 0 0);
+ --muted-foreground: oklch(0.708 0 0);
+ --accent: oklch(0.269 0 0);
+ --accent-foreground: oklch(0.985 0 0);
+ --destructive: oklch(0.396 0.141 25.723);
+ --destructive-foreground: oklch(0.637 0.237 25.331);
+ --border: oklch(0.269 0 0);
+ --input: oklch(0.269 0 0);
+ --ring: oklch(0.556 0 0);
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(0.269 0 0);
+ --sidebar-ring: oklch(0.439 0 0);
}
@theme inline {
- --color-background: var(--background);
- --color-foreground: var(--foreground);
- --color-card: var(--card);
- --color-card-foreground: var(--card-foreground);
- --color-popover: var(--popover);
- --color-popover-foreground: var(--popover-foreground);
- --color-primary: var(--primary);
- --color-primary-foreground: var(--primary-foreground);
- --color-secondary: var(--secondary);
- --color-secondary-foreground: var(--secondary-foreground);
- --color-muted: var(--muted);
- --color-muted-foreground: var(--muted-foreground);
- --color-accent: var(--accent);
- --color-accent-foreground: var(--accent-foreground);
- --color-destructive: var(--destructive);
- --color-destructive-foreground: var(--destructive-foreground);
- --color-border: var(--border);
- --color-input: var(--input);
- --color-ring: var(--ring);
- --color-chart-1: var(--chart-1);
- --color-chart-2: var(--chart-2);
- --color-chart-3: var(--chart-3);
- --color-chart-4: var(--chart-4);
- --color-chart-5: var(--chart-5);
- --radius-sm: calc(var(--radius) - 4px);
- --radius-md: calc(var(--radius) - 2px);
- --radius-lg: var(--radius);
- --radius-xl: calc(var(--radius) + 4px);
- --color-sidebar: var(--sidebar);
- --color-sidebar-foreground: var(--sidebar-foreground);
- --color-sidebar-primary: var(--sidebar-primary);
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
- --color-sidebar-accent: var(--sidebar-accent);
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
- --color-sidebar-border: var(--sidebar-border);
- --color-sidebar-ring: var(--sidebar-ring);
+ --color-background: var(--background);
+ --color-foreground: var(--foreground);
+ --color-card: var(--card);
+ --color-card-foreground: var(--card-foreground);
+ --color-popover: var(--popover);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-primary: var(--primary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-secondary: var(--secondary);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-muted: var(--muted);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-accent: var(--accent);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-destructive: var(--destructive);
+ --color-destructive-foreground: var(--destructive-foreground);
+ --color-border: var(--border);
+ --color-input: var(--input);
+ --color-ring: var(--ring);
+ --color-chart-1: var(--chart-1);
+ --color-chart-2: var(--chart-2);
+ --color-chart-3: var(--chart-3);
+ --color-chart-4: var(--chart-4);
+ --color-chart-5: var(--chart-5);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
+ --color-sidebar: var(--sidebar);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
- * {
- @apply border-border outline-ring/50;
- }
- body {
- @apply bg-background text-foreground;
- }
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
}
diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json
index a437aa1..d3fb5ee 100644
--- a/packages/ui/tsconfig.json
+++ b/packages/ui/tsconfig.json
@@ -1,11 +1,11 @@
{
- "extends": "@basango/typescript-config/react-library.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@basango/ui/*": ["./src/*"]
}
},
- "include": ["."],
- "exclude": ["node_modules", "dist"]
+ "exclude": ["node_modules", "dist"],
+ "extends": "@basango/tsconfig/react-library.json",
+ "include": ["."]
}
diff --git a/packages/ui/tsconfig.lint.json b/packages/ui/tsconfig.lint.json
index 9dcade6..cba74f2 100644
--- a/packages/ui/tsconfig.lint.json
+++ b/packages/ui/tsconfig.lint.json
@@ -1,8 +1,8 @@
{
- "extends": "@basango/typescript-config/react-library.json",
"compilerOptions": {
"outDir": "dist"
},
- "include": ["src", "turbo"],
- "exclude": ["node_modules", "dist"]
+ "exclude": ["node_modules", "dist"],
+ "extends": "@basango/tsconfig/react-library.json",
+ "include": ["src", "turbo"]
}
diff --git a/tsconfig.json b/tsconfig.json
index 9cfc868..482c9c3 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,3 +1,3 @@
{
- "extends": "@basango/typescript-config/base.json"
+ "extends": "@basango/tsconfig/base.json"
}
diff --git a/turbo.json b/turbo.json
index cc73732..d66cdfc 100644
--- a/turbo.json
+++ b/turbo.json
@@ -1,11 +1,7 @@
{
"$schema": "https://turborepo.com/schema.json",
"globalDependencies": ["**/.env"],
- "ui": "tui",
"tasks": {
- "topo": {
- "dependsOn": ["^topo"]
- },
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
@@ -20,24 +16,28 @@
],
"passThroughEnv": []
},
- "start": {
- "cache": false
- },
- "test": {
- "cache": false
- },
"dev": {
- "inputs": ["$TURBO_DEFAULT$", ".env"],
"cache": false,
+ "inputs": ["$TURBO_DEFAULT$", ".env"],
"persistent": true
},
"format": {},
"lint": {
"dependsOn": ["^topo"]
},
+ "start": {
+ "cache": false
+ },
+ "test": {
+ "cache": false
+ },
+ "topo": {
+ "dependsOn": ["^topo"]
+ },
"typecheck": {
"dependsOn": ["^topo"],
"outputs": []
}
- }
+ },
+ "ui": "tui"
}