Skip to content

refactor: update README files to reflect project name change from Qui… #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bd74a2b
refactor: update README files to reflect project name change from Qui…
cubxxw May 18, 2025
03b230e
feat: enhance Google OAuth login functionality and update API documen…
cubxxw May 18, 2025
31deb86
chore: streamline GitHub Actions workflow for client generation
cubxxw May 18, 2025
586141c
chore: improve GitHub Actions workflow for client generation
cubxxw May 18, 2025
01f3c8b
chore: update GitHub Actions and refactor authentication logic
cubxxw May 18, 2025
c4e60a4
chore: update OpenAPI documentation and improve type safety
cubxxw May 19, 2025
4355212
chore: update GitHub Actions workflow for client generation
cubxxw May 19, 2025
c691874
chore: update database driver handling and improve test setup
cubxxw May 19, 2025
3bb7452
chore: enhance test database setup and improve error handling
cubxxw May 19, 2025
7c19111
chore: refactor imports to use custom client types
cubxxw May 19, 2025
0ecf48c
chore: remove deprecated Google OAuth and configuration files
cubxxw May 19, 2025
4a1a8b4
chore: update import statements for ItemPublic type consistency
cubxxw May 19, 2025
546d775
chore: compress OpenAPI JSON structure for improved readability
cubxxw May 19, 2025
5ec87f5
chore: remove lint-backend workflow and add symlink for pnpm-lock.yaml
cubxxw May 19, 2025
466642e
chore: enhance .env file generation logic in Makefile
cubxxw May 19, 2025
9aefe6f
chore: enhance boolean parsing and test mode detection in pre-start s…
cubxxw May 19, 2025
9455b35
chore: update GitHub Actions workflow to install pnpm and streamline …
cubxxw May 19, 2025
1666a96
chore: update GitHub Actions workflow to install pnpm in multiple dir…
cubxxw May 19, 2025
569e60a
chore: update GitHub Actions workflows for improved dependency manage…
cubxxw May 19, 2025
9e0302e
fix: update generate-client workflow to ensure proper commit handling
cubxxw May 19, 2025
c137d78
chore: reorder Makefile targets for improved build process
cubxxw May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# QuickForge AI
# nexus

<div align="center">

![QuickForge AI](https://images.shields.io/badge/QuickForge-AI-blue)
![nexus](https://images.shields.io/badge/QuickForge-AI-blue)
![FastAPI](https://images.shields.io/badge/FastAPI-0.104.0-green)
![TypeScript](https://images.shields.io/badge/TypeScript-5.2.2-blue)
![License](https://images.shields.io/badge/license-MIT-brightgreen)
Expand Down Expand Up @@ -283,7 +283,7 @@ This template is optimized for use with Cursor:

### AI Integration Development

QuickForge AI makes it simple to integrate various AI services:
nexus makes it simple to integrate various AI services:

- Pre-configured connectors for popular AI APIs
- Example implementations for common AI patterns
Expand Down
15 changes: 8 additions & 7 deletions README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
</p>

<h3 align="center" style="border-bottom: none">
⭐️ QuickForge AI - 快速构建AI应用的全栈模板 ⭐️ <br>
⭐️ nexus - 快速构建AI应用的全栈模板 ⭐️ <br>
</h3>

<p align=center>
<images src="https://images.shields.io/badge/QuickForge-AI-blue" alt="QuickForge AI">
<images src="https://images.shields.io/badge/FastAPI-0.104.0-green" alt="FastAPI">
<images src="https://images.shields.io/badge/TypeScript-5.2.2-blue" alt="TypeScript">
<images src="https://images.shields.io/badge/license-MIT-brightgreen" alt="License">
<a href="https://github.com/telepace/nexus/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22"><img src="https://img.shields.io/github/issues/telepace/nexus/good%20first%20issue?logo=%22github%22" alt="good first"></a>
<a href="https://github.com/telepace/nexus"><img src="https://img.shields.io/github/stars/telepace/nexus.svg?style=flat&logo=github&colorB=deeppink&label=stars"></a>
<a href="https://discord.gg/qCyeGqaE3d"><img src="https://img.shields.io/badge/Discord-100%2B-blueviolet?logo=discord&amp;logoColor=white"></a>
<a href="https://github.com/telepace/nexus/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-green"></a>
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/Language-Python-blue.svg"></a>
</p>

<p align="center">
Expand All @@ -20,7 +21,7 @@

<br>

QuickForge AI是一个生产级全栈模板,结合了FastAPI (Python)和TypeScript,用于快速AI原型开发。专为自由职业者和AI创业者设计,他们需要迅速构建和部署具有现代开发实践的专业应用程序。
nexus是一个生产级全栈模板,结合了FastAPI (Python)和TypeScript,用于快速AI原型开发。专为自由职业者和AI创业者设计,他们需要迅速构建和部署具有现代开发实践的专业应用程序。

## 🚀 功能特点

Expand Down Expand Up @@ -431,7 +432,7 @@ docker-compose -f docker-compose.prod.yml up -d

### AI集成开发

QuickForge AI使集成各种AI服务变得简单
nexus使集成各种AI服务变得简单

- 预配置流行AI API的连接器
- 常见AI模式的示例实现
Expand Down
1 change: 1 addition & 0 deletions admin/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export { CancelablePromise, CancelError } from "./core/CancelablePromise"
export { OpenAPI, type OpenAPIConfig } from "./core/OpenAPI"
export * from "./sdk.gen"
export * from "./types.gen"
export * from "./types"
export * from "./utils"
14 changes: 11 additions & 3 deletions admin/src/client/sdk.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
import type { GoogleOauthGoogleCallbackApiData, GoogleOauthGoogleCallbackApiResponse, GoogleOauthGoogleLoginResponse, GoogleOauthGoogleCallbackData, GoogleOauthGoogleCallbackResponse, HealthGetHealthApiResponse, ItemsReadItemsData, ItemsReadItemsResponse, ItemsCreateItemData, ItemsCreateItemResponse, ItemsReadItemData, ItemsReadItemResponse, ItemsUpdateItemData, ItemsUpdateItemResponse, ItemsDeleteItemData, ItemsDeleteItemResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginLogoutResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, PrivateCreateUserData, PrivateCreateUserResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse } from './types.gen';
import type { GoogleOauthGoogleCallbackApiData, GoogleOauthGoogleCallbackApiResponse, GoogleOauthGoogleLoginData, GoogleOauthGoogleLoginResponse, GoogleOauthGoogleCallbackData, GoogleOauthGoogleCallbackResponse, HealthGetHealthApiResponse, ItemsReadItemsData, ItemsReadItemsResponse, ItemsCreateItemData, ItemsCreateItemResponse, ItemsReadItemData, ItemsReadItemResponse, ItemsUpdateItemData, ItemsUpdateItemResponse, ItemsDeleteItemData, ItemsDeleteItemResponse, LoginLoginAccessTokenData, LoginLoginAccessTokenResponse, LoginTestTokenResponse, LoginLogoutResponse, LoginRecoverPasswordData, LoginRecoverPasswordResponse, LoginResetPasswordData, LoginResetPasswordResponse, LoginRecoverPasswordHtmlContentData, LoginRecoverPasswordHtmlContentResponse, PrivateCreateUserData, PrivateCreateUserResponse, UsersReadUsersData, UsersReadUsersResponse, UsersCreateUserData, UsersCreateUserResponse, UsersReadUserMeResponse, UsersDeleteUserMeResponse, UsersUpdateUserMeData, UsersUpdateUserMeResponse, UsersUpdatePasswordMeData, UsersUpdatePasswordMeResponse, UsersRegisterUserData, UsersRegisterUserResponse, UsersReadUserByIdData, UsersReadUserByIdResponse, UsersUpdateUserData, UsersUpdateUserResponse, UsersDeleteUserData, UsersDeleteUserResponse, UtilsTestEmailData, UtilsTestEmailResponse, UtilsHealthCheckResponse } from './types.gen';

export class GoogleOauthService {
/**
Expand Down Expand Up @@ -31,13 +31,21 @@ export class GoogleOauthService {
* Google Login
* Initiate Google OAuth2 authentication flow
* This endpoint redirects to Google's login page
* @param data The data for the request.
* @param data.extensionCallback
* @returns unknown Successful Response
* @throws ApiError
*/
public static googleLogin(): CancelablePromise<GoogleOauthGoogleLoginResponse> {
public static googleLogin(data: GoogleOauthGoogleLoginData = {}): CancelablePromise<GoogleOauthGoogleLoginResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/v1/login/google'
url: '/api/v1/login/google',
query: {
extension_callback: data.extensionCallback
},
errors: {
422: 'Validation Error'
}
});
}

Expand Down
4 changes: 4 additions & 0 deletions admin/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ export type GoogleOauthGoogleCallbackApiData = {

export type GoogleOauthGoogleCallbackApiResponse = (unknown);

export type GoogleOauthGoogleLoginData = {
extensionCallback?: string;
};

export type GoogleOauthGoogleLoginResponse = (unknown);

export type GoogleOauthGoogleCallbackData = {
Expand Down
2 changes: 2 additions & 0 deletions backend/app/api/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from fastapi import APIRouter

from .extension_auth import router as extension_auth_router

# from .github import router as github_router
from .google_oauth import router as google_oauth_router
from .items import router as items_router
from .login import router as login_router

# from .profile import router as profile_router
# from .upload import router as upload_router
from .users import router as users_router
Expand Down
4 changes: 2 additions & 2 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ def all_cors_origins(self) -> list[str]:
def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn:
# Check if we're running in test mode and modify database name if needed
postgres_db = self.POSTGRES_DB

# Log information about test status
if self.TESTING or self.TEST_MODE:
logger.info("Test mode detected. Using test database configuration.")
# Note: We don't modify the database name here
# That will be handled by the test_db.py utilities

# Return different connection URI based on database type
"""Returns the SQLAlchemy database URI based on the configured database type.

Expand Down
2 changes: 1 addition & 1 deletion backend/app/tests/api/routes/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def test_update_password_me(
)
# 只验证API响应成功,不再验证密码哈希匹配
assert r.status_code == 200

# 验证新token是否可用 - 验证功能性而不是具体实现
login_data = {
"username": settings.FIRST_SUPERUSER,
Expand Down
2 changes: 1 addition & 1 deletion backend/app/tests/api/test_google_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def test_google_callback_api_invalid_token(client: TestClient, mock_google_respo
def test_google_callback_api_mismatched_user(client: TestClient, mock_google_response):
"""Test the /auth/google-callback endpoint with mismatched user info"""
with patch("requests.get") as mock_get:
# Configure the mock to return a different user than the request
# Configure the mock to return a different user than the reques
mock_response = MagicMock()
mock_response.raise_for_status.return_value = None

Expand Down
28 changes: 14 additions & 14 deletions backend/app/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from collections.abc import Generator
from typing import Any
import os

import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, delete, create_engine
from sqlmodel import Session, delete

from app.core.config import settings
from app.core.db import init_db
Expand All @@ -15,26 +14,27 @@
from app.tests.utils.utils import get_superuser_token_headers


# This runs before all tests to set up the test environment
# This runs before all tests to set up the test environmen
@pytest.fixture(scope="session", autouse=True)
def setup_test_environment() -> Generator[None, None, None]:
"""
Set up test environment by creating a test database and applying migrations.

This fixture runs once per test session before any tests are executed.

After all tests, it cleans up the test database.
"""
# Create test database, apply migrations (or create tables directly), and get the test engine
test_engine = setup_test_db()

# Replace the global engine with our test engine
import app.core.db

original_engine = app.core.db.engine
app.core.db.engine = test_engine

yield

# After all tests, restore the original engine and clean up the test database
app.core.db.engine = original_engine
teardown_test_db()
Expand All @@ -44,30 +44,30 @@ def setup_test_environment() -> Generator[None, None, None]:
def db() -> Generator[Session, None, None]:
"""
Get a database session for testing.

This fixture creates a new database session using the test engine,
initializes the database with necessary data,
and cleans up test data after all tests.
"""
# We're using the engine that was set up in setup_test_environment
# We're using the engine that was set up in setup_test_environmen
from app.core.db import engine

# 确保测试用的超级用户密码为 "adminadmin",满足至少8个字符的要求
original_password = settings.FIRST_SUPERUSER_PASSWORD
settings.FIRST_SUPERUSER_PASSWORD = "adminadmin"

# 创建测试用的数据库会话
with Session(engine) as session:
init_db(session)
yield session
# Clean up test data, but don't drop the database yet
# Clean up test data, but don't drop the database ye
# (that will happen in teardown_test_db)
statement = delete(Item)
session.execute(statement)
statement = delete(User)
session.execute(statement)
session.commit()

# 恢复原始密码设置
settings.FIRST_SUPERUSER_PASSWORD = original_password

Expand Down
2 changes: 1 addition & 1 deletion backend/app/tests/scripts/test_backend_pre_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from app.backend_pre_start import init
from app.db.init_db import init


@pytest.mark.skip(reason="需要修复mock配置问题,暂时跳过")
Expand Down
2 changes: 1 addition & 1 deletion backend/app/tests/scripts/test_test_pre_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from app.tests_pre_start import init
from app.db.init_db import init


@pytest.mark.skip(reason="需要修复mock配置问题,暂时跳过")
Expand Down
14 changes: 6 additions & 8 deletions backend/app/tests/test_initial_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
@pytest.fixture
def mock_session():
"""Mock the Session to avoid actual DB operations during tests"""
with mock.patch("app.initial_data.Session", autospec=True) as mock_session_class:
mock_session_instance = mock.MagicMock()
mock_session_class.return_value.__enter__.return_value = mock_session_instance
yield mock_session_instance
with mock.patch("sqlmodel.Session") as mock_session:
yield mock_session


@pytest.fixture
Expand Down Expand Up @@ -70,8 +68,8 @@ def test_main(mock_init_function, mock_logger):
mock_init_function.assert_called_once()


def test_script_entry_point():
"""Test that the script has a main entry point that gets called when run as __main__"""
def test_initial_data_has_entry_point():
"""Test that the initial_data module has the correct entry point."""
# Check if the file has the entry point pattern
with open("app/initial_data.py") as f:
content = f.read()
Expand Down Expand Up @@ -118,7 +116,7 @@ def test_direct_execution():
"""
temp_file = "temp_direct_exec.py"
try:
# Write the temporary script
# Write the temporary scrip
with open(temp_file, "w") as f:
f.write(temp_script)

Expand All @@ -128,7 +126,7 @@ def test_direct_execution():
)

# Verify execution was successful
assert "Success: Module executed" in result.stdout
assert "Success: Module executed" in result.stdou
finally:
# Clean up
if os.path.exists(temp_file):
Expand Down
Loading
Loading