diff --git a/20260421 Coding LLMs.ods b/20260421 Coding LLMs.ods index 3d039d0..2940935 100644 Binary files a/20260421 Coding LLMs.ods and b/20260421 Coding LLMs.ods differ diff --git a/LinkSyncServer/__pycache__/app.cpython-313.pyc b/LinkSyncServer/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000..b3d67c3 Binary files /dev/null and b/LinkSyncServer/__pycache__/app.cpython-313.pyc differ diff --git a/LinkSyncServer/__pycache__/routes.cpython-313.pyc b/LinkSyncServer/__pycache__/routes.cpython-313.pyc new file mode 100644 index 0000000..cae995d Binary files /dev/null and b/LinkSyncServer/__pycache__/routes.cpython-313.pyc differ diff --git a/LinkSyncServer/api/endpoints/__pycache__/links.cpython-313.pyc b/LinkSyncServer/api/endpoints/__pycache__/links.cpython-313.pyc new file mode 100644 index 0000000..519e5a5 Binary files /dev/null and b/LinkSyncServer/api/endpoints/__pycache__/links.cpython-313.pyc differ diff --git a/LinkSyncServer/api/endpoints/collections.py b/LinkSyncServer/api/endpoints/collections.py index ece53ed..7eebcf3 100644 --- a/LinkSyncServer/api/endpoints/collections.py +++ b/LinkSyncServer/api/endpoints/collections.py @@ -1,29 +1,40 @@ """ -LinkSyncServer - Collection CRUD Endpoints +LinkSyncServer - Collection CRUD Endpoints with SQLAlchemy """ -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, Query, Request from sqlalchemy.orm import Session +from sqlalchemy import func, and_, or_, exists from typing import List, Optional import uuid +import logging + +from models.base import Base, Bookmark, Collection, AuditLog, get_engine, sessionmaker +from pydantic import BaseModel, Field +import os router = APIRouter(prefix="/api/collections", tags=["Collections"]) +# Logging +logger = logging.getLogger(__name__) + class CollectionCreate(BaseModel): - name: str - description: Optional[str] = None - query_type: str # "static" or "dynamic" - query_expression: Optional[dict] = None - is_public: bool = False + name: str = Field(..., description="Collection name") + description: Optional[str] = Field(None, max_length=1024, description="Collection description") + query_type: str = Field(default="static", description="Static or dynamic collection") + query_expression: Optional[dict] = Field(None, description="Query expression for dynamic collections") + is_public: bool = Field(default=False, description="Is collection public") + tags: Optional[List[str]] = Field(default_factory=list, description="Collection tags") class CollectionUpdate(BaseModel): - name: Optional[str] = None - description: Optional[str] = None - query_type: Optional[str] = None - query_expression: Optional[dict] = None + name: Optional[str] = Field(None, max_length=255) + description: Optional[str] = Field(None, max_length=1024) + query_type: Optional[str] = Field(None) + query_expression: Optional[dict] = Field(None) is_public: Optional[bool] = None + tags: Optional[List[str]] = Field(None) class CollectionResponse(BaseModel): @@ -35,135 +46,188 @@ class CollectionResponse(BaseModel): is_public: bool created_at: str updated_at: str + tags: List[str] -def mock_create_collection(data: CollectionCreate) -> CollectionResponse: - """Create collection (mock implementation).""" - return { - "id": str(uuid.uuid4()), - "name": data.name, - "description": data.description, - "query_type": data.query_type, - "query_expression": data.query_expression, - "is_public": data.is_public, - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z" - } +def get_db(): + """Get database session.""" + db_session = sessionmaker(get_engine())() + return db_session -def mock_get_collections() -> List[CollectionResponse]: - """Get all collections (mock implementation).""" - return [ - { - "id": str(uuid.uuid4()), - "name": "Work Links", - "description": "Links for work use", - "query_type": "dynamic", - "query_expression": {"operation": "OR", "operands": [{"operation": "TERM", "value": "work"}]}, - "is_public": False, - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z" - } - ] +def get_current_user(request: Request): + """Get current authenticated user.""" + SECRET_KEY = os.environ.get("SECRET_KEY") + + auth_header = request.headers.get("Authorization") or request.headers.get("authorization") + + if auth_header and auth_header.startswith("Bearer "): + token = auth_header[7:] + try: + import jwt + payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) + return {"username": payload.get("sub"), "id": payload.get("sub")} + except Exception: + pass + + return {"username": "guest"} -def mock_get_collection(collection_id: str) -> CollectionResponse | None: - """Get collection by ID (mock implementation).""" - if collection_id == "mock-id": - return { - "id": "mock-id", - "name": "Work Links", - "description": "Links for work use", - "query_type": "dynamic", - "query_expression": {"operation": "OR", "operands": [{"operation": "TERM", "value": "work"}]}, - "is_public": False, - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z" - } - return None - - -def mock_update_collection(collection_id: str, data: CollectionUpdate) -> CollectionResponse | None: - """Update collection.""" - return mock_get_collection(collection_id) - - -def mock_delete_collection(collection_id: str) -> bool: - """Delete collection.""" - return True - - -def mock_execute_query(query_expression: dict) -> List[dict]: - """Execute query against bookmarks (mock implementation).""" - return [ - { - "id": str(uuid.uuid4()), - "url": "https://example.com/work", - "title": "Work Example", - "description": "An example", - "notes": "", - "tags": ["work"], - "favicon_url": None, - "path": "/Work", - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z", - "visit_count": 0, - "is_bookmarked": False, - "source_set_id": None - } - ] - - -@router.get("/", response_model=List[CollectionResponse]) -async def list_collections(): - """List all collections.""" - return mock_get_collections() - - -@router.get("/{collection_id}", response_model=CollectionResponse) -async def get_collection(collection_id: str): - """Get collection by ID.""" - collection = mock_get_collection(collection_id) - if not collection: - raise HTTPException(status_code=404, detail="Collection not found") - return collection - - -@router.post("/", response_model=CollectionResponse, status_code=status.HTTP_201_CREATED) -async def create_collection(data: CollectionCreate): - """Create new collection.""" - collection = mock_create_collection(data) - return collection - - -@router.put("/{collection_id}", response_model=CollectionResponse) -async def update_collection( - collection_id: str, - data: CollectionUpdate -): - """Update collection.""" - collection = mock_update_collection(collection_id, data) - if not collection: - raise HTTPException(status_code=404, detail="Collection not found") - return collection - - -@router.delete("/{collection_id}", response_model=dict) -async def delete_collection(collection_id: str): - """Delete collection.""" - success = mock_delete_collection(collection_id) - if not success: - raise HTTPException(status_code=404, detail="Collection not found") - return {"message": "Collection deleted successfully"} - - -@router.post("/{collection_id}/refresh", response_model=dict) -async def refresh_collection(collection_id: str): - """Refresh dynamic collection (re-evaluate query).""" - return {"message": "Collection refreshed successfully"} - - -@router.post("/execute", response_model=List[dict]) -async def execute_query(query_expression: dict): - """Execute query and return result set.""" - return mock_execute_query(query_expression) \ No newline at end of file +class CollectionManager: + """Collection management helper.""" + + @staticmethod + def get_collection(collection_id: str) -> Optional[Collection]: + """Get collection by ID.""" + db = get_db() + try: + collection = db.query(Collection).filter(Collection.id == collection_id).first() + return collection + except Exception: + return None + + @staticmethod + def create_collection(data: CollectionCreate, request: Request) -> Collection: + """Create new collection.""" + db = get_db() + + collection = Collection( + name=data.name, + description=data.description, + query_type=data.query_type, + query_expression=data.query_expression, + is_public=data.is_public, + tags=TagCollection(tags=data.tags or []), + ) + + db.add(collection) + db.commit() + db.refresh(collection) + + # Create audit log + user = get_current_user(request) + try: + audit = AuditLog( + action="create", + entity_type="Collection", + entity_id=collection.id, + old_value=None, + new_value=collection.dict(), + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + + return collection + + @staticmethod + def update_collection(collection_id: str, data: CollectionUpdate, request: Request) -> Optional[Collection]: + """Update collection.""" + db = get_db() + + collection = db.query(Collection).filter(Collection.id == collection_id).first() + + if not collection: + return None + + # Update fields + for field_name, value in data.dict().items(): + if value is not None: + if hasattr(collection, field_name): + setattr(collection, field_name, value) + elif field_name == "tags": + if isinstance(value, list): + collection.tags.add(*value) + else: + collection.tags.update(str(value)) + + db.commit() + db.refresh(collection) + + # Create audit log + user = get_current_user(request) + try: + audit = AuditLog( + action="update", + entity_type="Collection", + entity_id=collection_id, + old_value=collection.dict(), + new_value=collection.dict(), + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + + return collection + + @staticmethod + def delete_collection(collection_id: str, request: Request) -> dict: + """Delete collection.""" + db = get_db() + + collection = db.query(Collection).filter(Collection.id == collection_id).first() + + if not collection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Collection not found") + + db.delete(collection) + db.commit() + + # Create audit log + user = get_current_user(request) + try: + audit = AuditLog( + action="delete", + entity_type="Collection", + entity_id=collection_id, + old_value=collection.dict(), + new_value=None, + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + + return {"message": "Collection deleted successfully", "deleted_id": collection_id} + + @staticmethod + def get_collection_tags(collection_id: str) -> List[str]: + """Get collection tags.""" + db = get_db() + + collection = db.query(Collection).filter(Collection.id == collection_id).first() + + if not collection: + return [] + + return list(collection.tags) + + @staticmethod + def get_collection_bookmarks(collection_id: str, limit: int = 50, offset: int = 0) -> List[Bookmark]: + """ + Get bookmarks for collection (static or dynamic). + + For dynamic collections with query expression: + Use query executor to parse and filter bookmarks + """ + db = get_db() + + collection = db.query(Collection).filter(Collection.id == collection_id).first() + + if not collection: + return [] + + if collection.query_type == "static": + # Static collection: get all bookmarks + bookmarks = db.query(Bookmark).filter(Bookmark.collection_id == collection_id).limit(limit).offset(offset).all() + else: + # Dynamic collection: query expression + # TODO: Use query executor to parse expression (executor module) + bookmarks = db.query(Bookmark).limit(limit).offset(offset).all() + + return bookmarks diff --git a/LinkSyncServer/api/endpoints/links.py b/LinkSyncServer/api/endpoints/links.py index e52c809..d46b0e2 100644 --- a/LinkSyncServer/api/endpoints/links.py +++ b/LinkSyncServer/api/endpoints/links.py @@ -1,36 +1,46 @@ """ -LinkSyncServer - Link CRUD Endpoints +LinkSyncServer - Link CRUD Endpoints with SQLAlchemy """ -from fastapi import APIRouter, Depends, HTTPException, status -from sqlalchemy.orm import Session +from fastapi import APIRouter, Depends, HTTPException, status, Query, Request +from sqlalchemy.orm import Session, sessionmaker +from sqlalchemy import func, or_ from typing import List, Optional import uuid +import logging +import hashlib + +from models.base import Base, Bookmark, User, AuditLog, get_engine, create_engine +from pydantic import BaseModel, Field +import os router = APIRouter(prefix="/api/links", tags=["Links"]) +# Logging +logger = logging.getLogger(__name__) + class BookmarkCreate(BaseModel): - url: str - title: str - description: Optional[str] = None - notes: Optional[str] = None - tags: Optional[List[str]] = None - favicon_url: Optional[str] = None - path: Optional[str] = None - visit_count: int = 0 - is_bookmarked: bool = False + url: str = Field(..., description="Bookmark URL") + title: str = Field(..., min_length=1, max_length=255, description="Bookmark title") + description: Optional[str] = Field(None, max_length=500, description="Optional description") + notes: Optional[str] = Field(None, max_length=2000, description="Optional notes") + tags: Optional[List[str]] = Field(default_factory=list, description="List of tag names") + favicon_url: Optional[str] = Field(None, max_length=512, description="Favicon URL") + path: Optional[str] = Field(None, max_length=512, description="Folder path") + visit_count: int = Field(ge=0, description="Visit counter") + is_bookmarked: bool = Field(default=False, description="Bookmark flag") class BookmarkUpdate(BaseModel): - url: Optional[str] = None - title: Optional[str] = None - description: Optional[str] = None - notes: Optional[str] = None - tags: Optional[List[str]] = None - favicon_url: Optional[str] = None - path: Optional[str] = None - visit_count: Optional[int] = None + url: Optional[str] = Field(None, description="New URL") + title: Optional[str] = Field(None, min_length=1, max_length=255) + description: Optional[str] = Field(None, max_length=500) + notes: Optional[str] = Field(None, max_length=2000) + tags: Optional[List[str]] = Field(None) + favicon_url: Optional[str] = Field(None, max_length=512) + path: Optional[str] = Field(None, max_length=512) + visit_count: Optional[int] = Field(None, ge=0) is_bookmarked: Optional[bool] = None @@ -48,128 +58,301 @@ class BookmarkResponse(BaseModel): visit_count: int is_bookmarked: bool source_set_id: Optional[str] + user_id: Optional[str] -def get_db(): +def get_db_session(): """Get database session.""" - from models.base import get_engine - db = get_engine() - return db + try: + return sessionmaker(get_engine())() + except Exception: + return None -def mock_create_bookmark(data: BookmarkCreate) -> dict: - """Create bookmark (mock implementation for demo).""" - bookmark = { - "id": str(uuid.uuid4()), - "url": data.url, - "title": data.title, - "description": data.description, - "notes": data.notes, - "tags": data.tags or [], - "favicon_url": data.favicon_url, - "path": data.path, - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z", - "visit_count": data.visit_count, - "is_bookmarked": data.is_bookmarked, - "source_set_id": None - } - return bookmark +def get_current_user(request: Request): + """Get current authenticated user.""" + SECRET_KEY = os.environ.get("SECRET_KEY") + + auth_header = request.headers.get("Authorization") or request.headers.get("authorization") + + if auth_header and auth_header.startswith("Bearer "): + token = auth_header[7:] + try: + import jwt + payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) + return {"username": payload.get("sub"), "id": payload.get("sub")} + except Exception: + pass - -def mock_get_bookmarks() -> List[dict]: - """Get all bookmarks (mock implementation).""" - return [ - { - "id": str(uuid.uuid4()), - "url": "https://example.com", - "title": "Example", - "description": "An example website", - "notes": "", - "tags": ["example", "demo"], - "favicon_url": None, - "path": "/Home", - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z", - "visit_count": 0, - "is_bookmarked": False, - "source_set_id": None - } - ] - - -def mock_get_bookmark(bookmark_id: str) -> dict | None: - """Get single bookmark by ID.""" - # Mock implementation - if bookmark_id == "mock-id": - return { - "id": "mock-id", - "url": "https://example.com", - "title": "Example", - "description": "An example website", - "notes": "", - "tags": ["example", "demo"], - "favicon_url": None, - "path": "/Home", - "created_at": "2026-05-11T00:00:00Z", - "updated_at": "2026-05-11T00:00:00Z", - "visit_count": 0, - "is_bookmarked": False, - "source_set_id": None - } - return None - - -def mock_update_bookmark(bookmark_id: str, data: BookmarkUpdate) -> dict | None: - """Update bookmark.""" - # Mock implementation - return mock_get_bookmark(bookmark_id) - - -def mock_delete_bookmark(bookmark_id: str) -> bool: - """Delete bookmark.""" - return True + return {"username": "guest"} @router.get("/", response_model=List[BookmarkResponse]) -async def list_bookmarks(limit: int = 20, offset: int = 0): - """List all bookmarks.""" - bookmarks = mock_get_bookmarks() - return bookmarks[offset:offset + limit] +async def list_bookmarks( + limit: int = Query(20, le=100, ge=1, description="Number of results per page"), + offset: int = Query(0, ge=0, description="Offset for pagination"), + search: Optional[str] = Query(None, description="Search query"), + tags_filter: Optional[List[str]] = Query(None, description="Filter by tags"), + path_filter: Optional[str] = Query(None, description="Filter by folder path") +): + """List all bookmarks with optional filters.""" + db = get_db_session() + if not db: + return [] + + query = Bookmark.query + + # Search filter + if search: + query = query.filter((Bookmark.title.contains(search)) | + (Bookmark.description.contains(search)) | + (Bookmark.url.contains(search))) + + # Tag filter + if tags_filter: + or_clause = or_(*[Bookmark.tags.contains(tag) for tag in tags_filter]) + query = query.filter(or_clause) + + # Path filter + if path_filter: + query = query.filter(Bookmark.path.contains(path_filter)) + + bookmarks = query.limit(limit).offset(offset).all() + return bookmarks @router.get("/{bookmark_id}", response_model=BookmarkResponse) async def get_bookmark(bookmark_id: str): """Get bookmark by ID.""" - bookmark = mock_get_bookmark(bookmark_id) + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + if not bookmark: - raise HTTPException(status_code=404, detail="Bookmark not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + return bookmark @router.post("/", response_model=BookmarkResponse, status_code=status.HTTP_201_CREATED) -async def create_bookmark(data: BookmarkCreate): +async def create_bookmark(data: BookmarkCreate, request: Request): """Create new bookmark.""" - bookmark = mock_create_bookmark(data) + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database unavailable") + + bookmark = Bookmark( + url=data.url, + title=data.title, + description=data.description, + notes=data.notes, + tags=data.tags or [], + favicon_url=data.favicon_url, + path=data.path, + visit_count=data.visit_count, + is_bookmarked=data.is_bookmarked + ) + + bookmark_id = f"{data.url[:20]}-{uuid.uuid4()[:8]}" + bookmark = db.add(bookmark) + db.commit() + db.refresh(bookmark) + + # Get user for audit log + user = get_current_user(request) + + # Create audit log (optional) + try: + audit = AuditLog( + action="create", + entity_type="Bookmark", + entity_id=bookmark_id, + old_value=None, + new_value=bookmark.dict(), + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + return bookmark @router.put("/{bookmark_id}", response_model=BookmarkResponse) async def update_bookmark( bookmark_id: str, - data: BookmarkUpdate + data: BookmarkUpdate, + request: Request ): """Update bookmark.""" - bookmark = mock_update_bookmark(bookmark_id, data) + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database unavailable") + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + if not bookmark: - raise HTTPException(status_code=404, detail="Bookmark not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + # Update fields + for field_name, value in data.dict().items(): + if value is not None: + setattr(bookmark, field_name, value) + + db.commit() + db.refresh(bookmark) + + # Get user for audit log + user = get_current_user(request) + + # Create audit log + try: + old_data = Bookmark(id=bookmark_id, url=bookmark.url, title=bookmark.title).dict() + audit = AuditLog( + action="update", + entity_type="Bookmark", + entity_id=bookmark_id, + old_value=old_data, + new_value=bookmark.dict(), + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + return bookmark @router.delete("/{bookmark_id}", response_model=dict) -async def delete_bookmark(bookmark_id: str): +async def delete_bookmark(bookmark_id: str, request: Request): """Delete bookmark.""" - success = mock_delete_bookmark(bookmark_id) - if not success: - raise HTTPException(status_code=404, detail="Bookmark not found") - return {"message": "Bookmark deleted successfully"} \ No newline at end of file + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database unavailable") + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + + if not bookmark: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + db.delete(bookmark) + db.commit() + + # Get user for audit log + user = get_current_user(request) + + # Create audit log + try: + audit = AuditLog( + action="delete", + entity_type="Bookmark", + entity_id=bookmark_id, + old_value=bookmark.dict(), + new_value=None, + user_id=user.get("id") + ) + db.add(audit) + db.commit() + except Exception: + pass + + return {"message": "Bookmark deleted successfully", "deleted_id": bookmark_id} + + +@router.post("/{bookmark_id}/tags") +async def add_tags(bookmark_id: str, tags: List[str], request: Request): + """Add tags to bookmark.""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database unavailable") + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + + if not bookmark: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + for tag in tags: + if tag.lower() not in [t.lower() for t in bookmark.tags]: + bookmark.tags.append(tag) + + db.commit() + db.refresh(bookmark) + + return bookmark + + +@router.delete("/{bookmark_id}/tags") +async def remove_tags(bookmark_id: str, tags_to_remove: List[str], request: Request): + """Remove tags from bookmark.""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database unavailable") + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + + if not bookmark: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + bookmark.tags = [t for t in bookmark.tags if t.lower() not in [tag.lower() for tag in tags_to_remove]] + + db.commit() + db.refresh(bookmark) + + return bookmark + + +@router.get("/{bookmark_id}/stats") +async def get_bookmark_stats(bookmark_id: str, request: Request): + """Get bookmark statistics.""" + db = get_db_session() + + if not db: + return {} + + bookmark = db.query(Bookmark).filter(Bookmark.id == bookmark_id).first() + + if not bookmark: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bookmark not found") + + # Get visit count + visits = db.query("SELECT COUNT(*) FROM visits WHERE bookmark_id = :bookmark_id") + visit_count = visits.execute({"bookmark_id": bookmark_id}) + + return { + "bookmark_id": bookmark_id, + "visit_count": visit_count[0][0], + "last_visited": visits.execute({"bookmark_id": bookmark_id}) + } + + +# Audit log helper (optional) +def create_audit_log(action: str, entity_type: str, entity_id: str, old_value: dict, new_value: dict): + """Create audit log entry.""" + db = get_db_session() + + if not db: + return + + try: + audit = AuditLog( + action=action, + entity_type=entity_type, + entity_id=entity_id, + old_value=old_value, + new_value=new_value, + ip_address=request.client.host if hasattr(request, 'client') and hasattr(request.client, 'host') else None + ) + db.add(audit) + db.commit() + except Exception: + pass \ No newline at end of file diff --git a/LinkSyncServer/api/endpoints/tags.py b/LinkSyncServer/api/endpoints/tags.py new file mode 100644 index 0000000..620a003 --- /dev/null +++ b/LinkSyncServer/api/endpoints/tags.py @@ -0,0 +1,188 @@ +""" +LinkSyncServer - Tag Management Endpoints +""" + +from fastapi import APIRouter, Depends, HTTPException, status, Query +from sqlalchemy.orm import Session +from typing import List, Optional +import logging +import uuid + +from models.base import Base, Tag, Bookmark, get_engine +from pydantic import BaseModel, Field + +router = APIRouter(prefix="/api/tags", tags=["Tags"]) + + +class TagCreate(BaseModel): + name: str = Field(..., min_length=1, max_length=50) + color: Optional[str] = Field(None, max_length=7) + + +class TagUpdate(BaseModel): + name: Optional[str] = Field(None) + color: Optional[str] = Field(None) + + +class TagResponse(BaseModel): + id: str + name: str + color: Optional[str] + created_at: str + updated_at: str + + +def get_db_session(): + """Get database session.""" + try: + return Session(get_engine()) + except Exception: + return None + + +def get_current_user(request): + """Get current authenticated user.""" + SECRET_KEY = None + + try: + auth_header = request.headers.get("Authorization") or request.headers.get("authorization") + + if auth_header and auth_header.startswith("Bearer "): + token = auth_header[7:] + import jwt + payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) + return {"username": payload.get("sub"), "id": payload.get("sub")} + elif not auth_header: + return {"username": "guest"} + except: + pass + + return {"username": "guest"} + + +@router.get("/", response_model=List[TagResponse]) +async def list_tags(page: int = Query(1, ge=1), per_page: int = Query(50, ge=1, le=200)): + """List tags with pagination.""" + db = get_db_session() + + if not db: + return [] + + count = db.query(Tag).count() + tags = db.query(Tag).order_by(Tag.name).offset((page - 1) * per_page).limit(per_page).all() + + return tags + + +@router.get("/count", response_model=dict) +async def tag_count(): + """Get total tag count.""" + db = get_db_session() + + if not db: + return {"count": 0} + + return {"count": db.query(Tag).count()} + + +@router.get("/{tag_id}", response_model=TagResponse) +async def get_tag(tag_id: str): + """Get tag by ID.""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=404, detail="Tag not found") + + tag = db.query(Tag).filter(Tag.id == tag_id).first() + + if not tag: + raise HTTPException(status_code=404, detail="Tag not found") + + return tag + + +@router.get("/{tag_id}/links") +async def get_tag_links(tag_id: str, limit: int = Query(50, ge=1), offset: int = Query(0, ge=0)): + """Get links for tag."""" + db = get_db_session() + + if not db: + return [] + + tag = db.query(Tag).filter(Tag.id == tag_id).first() + + if not tag: + raise HTTPException(status_code=404, detail="Tag not found") + + links = db.query(Bookmark).join(Tag).filter(Tag.id == tag_id).limit(limit).offset(offset).all() + + return links + + +@router.post("/", response_model=TagResponse, status_code=201) +async def create_tag(data: TagCreate, request): + """Create new tag.""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=500, detail="Database unavailable") + + tag = Tag( + id=f"tag-{uuid.uuid4()[:8]}", + name=data.name, + color=data.color + ) + + db.add(tag) + db.commit() + db.refresh(tag) + + return tag + + +@router.put("/{tag_id}", response_model=TagResponse) +async def update_tag(tag_id: str, data: TagUpdate): + """Update tag.""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=500, detail="Database unavailable") + + tag = db.query(Tag).filter(Tag.id == tag_id).first() + + if not tag: + raise HTTPException(status_code=404, detail="Tag not found") + + for field_name in ["name", "color"]: + if field_name in data.dict() and data.dict()[field_name] is not None: + setattr(tag, field_name, data.dict()[field_name]) + + db.commit() + db.refresh(tag) + + return tag + + +@router.delete("/{tag_id}", response_model=dict) +async def delete_tag(tag_id: str): + """Delete tag (and remove from all links).""" + db = get_db_session() + + if not db: + raise HTTPException(status_code=500, detail="Database unavailable") + + tag = db.query(Tag).filter(Tag.id == tag_id).first() + + if not tag: + raise HTTPException(status_code=404, detail="Tag not found") + + # Remove tag from all bookmarks + bookmarks = db.query(Bookmark).filter(Bookmark.tags.contains(tag.name)).all() + + for bookmark in bookmarks: + bookmark.tags = [t for t in bookmark.tags if t[0] != tag_id] + + db.delete(tag) + db.commit() + + return {"message": f"Tag '{tag.name}' deleted and removed from all links"} diff --git a/LinkSyncServer/api/v1/sync.py b/LinkSyncServer/api/v1/sync.py new file mode 100644 index 0000000..6f4c8bd --- /dev/null +++ b/LinkSyncServer/api/v1/sync.py @@ -0,0 +1,151 @@ +""" +LinkSyncServer - Sync Endpoint for Browser Extension +""" + +from fastapi import APIRouter, HTTPException, status +from typing import List, Dict +import jwt +import logging +from datetime import datetime +import json + +from models.base import Bookmark, Collection, get_engine +from api.parsers.bookmarks import BookmarkParser +from api.parsers.sync import SyncParser +import os + +router = APIRouter(prefix="/api/v1/sync", tags=["Sync"]) + +logger = logging.getLogger(__name__) + +# Get database and secrets +DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///links.db") +SECRET_KEY = os.environ.get("SECRET_KEY", "fallback-for-dev") + +# Initialize parser +bookmark_parser = BookmarkParser() +sync_parser = SyncParser() + + +def get_db_session(): + """Get database session.""" + from sqlalchemy.pool import StaticPool + from sqlalchemy.orm import Session + from sqlalchemy import create_engine + + engine = create_engine( + DATABASE_URL, + connect_args={'check_same_thread': False} + ) + return Session(engine) + + +def validate_request_token(request_token: str) -> Dict: + """ + Validate sync request token. + + Accepts: + - Token header from extension + - No auth for demo/maintenance + """ + if not request_token: + # Allow anonymous for demo + return {"type": "anonymous", "permissions": {}} + + try: + # Try to decode as JWT + payload = jwt.decode(request_token, SECRET_KEY, algorithms=["HS256"]) + + # Check permissions + permissions = { + "collections": payload.get("permissions", {}).get("collections", []), + "bookmarks": payload.get("permissions", {}).get("bookmarks", []) + } + + return { + "type": "authorized", + "permissions": permissions + } + except Exception: + # Token invalid, fall back to anonymous + return {"type": "anonymous", "permissions": {}} + + +def sync_with_github(account_id: str, collection_id: str, request_token: str) -> Dict: + """ + Sync bookmarks from GitHub to local collection. + + Args: + account_id: GitHub account ID + collection_id: LinkSync collection ID + request_token: Token from extension request + + Returns: + Sync response (JSON payload for extension) + """ + # Validate token + token_info = validate_request_token(request_token) + + if token_info["type"] != "authorized": + raise HTTPException(status_code=403, detail="Unauthorized access") + + # Get collection + db = get_db_session() + + collection = db.query(Collection).filter(Collection.id == collection_id).first() + + if not collection: + raise HTTPException(status_code=404, detail="Collection not found") + + # Make request to GitHub API (using library or requests) + try: + # GitHub API v3 + # GET /users/{user_id}/starred + # Response: list of starred repositories and Gists (links) + + github_api_base = "https://api.github.com" + starred_response = requests.get( + f"{github_api_base}/users/{account_id}/starred", + headers={ + "Accept": "application/vnd.github.v3+json" + } + ) + + if starred_response.status_code != 200: + raise HTTPException(status_code=502, detail="Failed to fetch GitHub data") + + github_links = starred_response.json() + + # Parse GitHub data + github_bookmarks = sync_parser.parse_github_links(github_links) + + # Create/update/delete based on sync + changes = bookmark_parser.parse_sync( + github_bookmarks, collection_id + ) + + # Commit changes + db.commit() + + # Build response + sync_response = { + "_links": { + "sync": { + "_links": { + "self": {} + } + } + }, + "meta": { + "account_id": account_id, + "collections": [collection_id], + "changes": changes, + "total_synced": len(github_links) + } + } + + return sync_response + + except Exception as e: + logger.error(f"Sync error: {e}") + raise HTTPException(status_code=500, detail=str(e)) diff --git a/LinkSyncServer/app.py b/LinkSyncServer/app.py index 217c742..8904aaa 100644 --- a/LinkSyncServer/app.py +++ b/LinkSyncServer/app.py @@ -1,128 +1,18 @@ """ LinkSyncServer - Main Application - -FastAPI application for bookmark management with advanced collection -and query capabilities. """ -from fastapi import FastAPI, Depends, HTTPException, status -from fastapi.middleware.cors import CORSMiddleware -from fastapi.staticfiles import StaticFiles -from fastapi.templating import Jinja2Templates -from fastapi.responses import HTML, JSONResponse -from pydantic import BaseModel -from typing import Optional -import os -import secrets -import logging +from fastapi import FastAPI +from routes import router as api_router -# Configure logging -logging.basicConfig(level=os.environ.get('LOG_LEVEL', 'INFO')) -logger = logging.getLogger(__name__) - -# Create FastAPI app app = FastAPI( title="LinkSyncServer", - description="Self-hosted bookmark server with advanced collection capabilities", + description="Self-hosted bookmark server with collections", version="1.0.0", ) -# CORS configuration -allow_origins = os.environ.get('CORS_ORIGINS', 'http://localhost:5555').split(',') +app.include_router(api_router) -app.add_middleware( - CORSMiddleware, - allow_origins=allow_origins, - allow_credentials=True, - allow_methods=['*'], - allow_headers=['*'], -) - -# Static files -app.mount("/static", StaticFiles(directory="static"), name="static") - -# Templates -app.mount( - "/templates", - StaticFiles(directory="templates"), - name="templates" -) - -# Database configuration -DATABASE_URL = os.environ.get('DATABASE_URL') -SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_urlsafe(32)) -DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true' -HOST = os.environ.get('HOST', '0.0.0.0') -PORT = int(os.environ.get('PORT', 5000)) - -# CORS origins from environment -CORS_ORIGINS = [o.strip() for o in os.environ.get('CORS_ORIGINS', 'http://localhost:5555').split(',')] - -# Add CORS middleware -app.add_middleware( - CORSMiddleware, - allow_origins=CORS_ORIGINS, - allow_credentials=True, - allow_methods=['*'], - allow_headers=['*'], -) - -# Health check endpoint @app.get("/health") -async def health_check(): - """Health check endpoint for Docker monitoring.""" - return {"status": "ok", "service": "LinkSyncServer"} - -# Root endpoint -@app.get("/") -async def root(): - """Root endpoint with redirect to web UI.""" - return HTML(""" - - - LinkSyncServer - -

LinkSyncServer

-

Web UI: Login

-

API Docs: API Documentation

- - - """) - -# Error handler -@app.exception_handler(Exception) -async def global_exception_handler(request, exc): - logger.error(f"Exception: {exc}") - return JSONResponse( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - content={"detail": "Internal server error"} - ) - -# Error handler for specific exceptions -@app.exception_handler(HTTPException) -async def http_exception_handler(request, exc): - return JSONResponse( - status_code=exc.status_code, - content={"detail": exc.detail} - ) - -def get_api_key(user): - """Get API key from database for a user.""" - return None - -async def get_current_user(token: Optional[str] = None): - """Get current authenticated user.""" - if token: - # Validate JWT token - # In production, implement proper JWT validation - pass - return None - -if __name__ == "__main__": - import uvicorn - uvicorn.run( - "app:app", - host=HOST, - port=PORT, - reload=DEBUG - ) \ No newline at end of file +def health(): + return {"status": "ok"} \ No newline at end of file diff --git a/LinkSyncServer/models/__init__.py b/LinkSyncServer/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LinkSyncServer/queries/executor.py b/LinkSyncServer/queries/executor.py new file mode 100644 index 0000000..c404e19 --- /dev/null +++ b/LinkSyncServer/queries/executor.py @@ -0,0 +1,220 @@ +""" +LinkSyncServer - Query Executor +""" + +from typing import List, Dict, Any, Optional +from sqlalchemy.orm import Session +from sqlalchemy import func, and_, or_ +import logging +import sys +sys.path.insert(0, 'models') +from base import Bookmark, User + +logger = logging.getLogger(__name__) + + +def parse_query_expression(query_expression: dict, expressions: list = None) -> Dict[str, Any]: + """ + Parse query expression in dict format. + + Example: + { + "operation": "OR", + "operands": [ + {"operation": "TERM", "value": "work"}, + {"operation": "TERM", "value": "company"} + ] + } + """ + if not query_expression: + return + + operation = query_expression.get('operation') + operands = query_expression.get('operands', []) + + if not operands: + # Top-level expression (e.g., TERM) + if operation == 'TERM': + value = query_expression.get('value', '') + if value.startswith('url:'): + search_term = value[4:] + return parse_term(search_term, 'url') + elif value.startswith('tag:'): + search_term = value[4:] + return parse_term(search_term, 'tags') + elif value.startswith('title:'): + search_term = value[6:] + return parse_term(search_term, 'title') + elif value.startswith('description:'): + search_term = value[12:] + return parse_term(search_term, 'description') + elif value.startswith('id:'): + return {'operation': 'EQUALS', 'value': value[3:]} + else: + # Default: search title and description + return {'operation': 'OR', 'operands': [ + {'operation': 'TERM', 'value': value, 'field': 'title'}, + {'operation': 'TERM', 'value': value, 'field': 'description'} + ]} + + +def parse_term(term: str, field: str): + """ + Parse field:value term. + + Returns SQLAlchemy filter clause. + """ + # Handle different field types + field_filters = { + 'tags': lambda term: and_(*[Bookmark.tags.ilike(f'%{term}%') for tag in term.split(',')]), + 'title': lambda term: Bookmark.title.ilike(f'%{term}%'), + 'description': lambda term: Bookmark.description.ilike(f'%{term}%'), + 'url': lambda term: Bookmark.url.ilike(f'%{term}%'), + 'path': lambda term: Bookmark.path.ilike(f'%{term}%') + } + + # Get filter function + filter_fn = field_filters.get(field, lambda term: Bookmark.tags.ilike(f'%{term}%')) + + # Apply filter + filter_clause = filter_fn(term) + + # Return filter clause with field + return {'field': field, 'value': term, 'clause': filter_clause} + + +def parse_or_filter(operators: list, operands: list) -> Any: + """ + Parse OR filter. + + Operators: ['AND', 'OR', 'XOR'] + """ + if not operands: + return False + + # Default to AND for safety + op_type = operators[0] if operators else 'AND' + + if op_type == 'OR': + return or_(*[parse_and_filter(operators[1:], operands[1:]) for _ in range(1)]) + elif op_type == 'AND': + return and_(*[parse_and_filter(operators[1:], operands[1:]) for _ in range(1)]) + else: + # XOR: not supported yet + raise ValueError("XOR not supported") + + +def parse_and_filter(operands: list) -> Any: + """Parse AND filter (default).""" + if not operands: + return False + + # Parse each operand + clauses = [] + for operand in operands: + if isinstance(operand, str): + clause = operand + elif isinstance(operand, dict): + if operand.get('operation') == 'EQUALS': + clause = operand['value'] + elif operand.get('operation') == 'TERM': + clauses.append(parse_term(operand.get('value', ''), operand.get('field', 'tags'))) + # Add other term types as needed + else: + clauses.append(operand) + else: + raise ValueError(f"Unknown operand type: {type(operand)}") + + if not clauses: + return False + + return clauses + + +def execute_query(query_expression: dict) -> List[Dict[str, Any]]: + """ + Execute query and return results. + + query_expression: dict from parser + returns: list of bookmarks + """ + # Default session + session = Session() + + if not query_expression: + return [] + + # Parse query expression + try: + # Handle single-term queries + if query_expression.get('operation') == 'TERM': + search_term = query_expression.get('value', '') + field = query_expression.get('field', 'title') + + if field == 'tags': + tags = search_term.split(',') + filters = [Bookmark.tags.contains(tag) for tag in tags] + result = session.query(Bookmark).filter(or_(*filters)).all() + elif field == 'title': + result = session.query(Bookmark).filter(Bookmark.title.contains(search_term)).all() + elif field == 'description': + result = session.query(Bookmark).filter(Bookmark.description.contains(search_term)).all() + elif field == 'url': + result = session.query(Bookmark).filter(Bookmark.url.contains(search_term)).all() + else: + # Default: search title and description + filters = [ + or_(Bookmark.title.contains(search_term), + Bookmark.description.contains(search_term)) + ] + result = session.query(Bookmark).filter(or_(*filters)).all() + elif query_expression.get('operation') == 'AND': + # AND clause + clauses = parse_and_filter(query_expression.get('operands', [])) + if isinstance(clauses, list): + result = session.query(Bookmark).filter(and_(*clauses)).all() + else: + result = session.query(Bookmark).filter(clauses).all() + else: + # Default: search title and description + search_term = query_expression.get('value', '') + result = session.query(Bookmark).filter( + or_(Bookmark.title.contains(search_term), + Bookmark.description.contains(search_term)) + ).all() + + except Exception as e: + logger.error(f"Query execution error: {e}") + result = [] + + return result + + +def create_bookmarks_from_sync(sync_data: dict): + """ + Create bookmarks from sync response. + + sync_data: dict from GitHub API + """ + if not sync_data: + return [] + + # Parse sync JSON + sync_info = sync_data.get('_links', {}).get('sync', {}).get('_links', {}) + + # Extract bookmarks + bookmarks = [] + if 'objects' in sync_data: + for obj in sync_data['objects']: + if 'title' in obj: + bookmarks.append({ + 'url': obj.get('url', ''), + 'title': obj.get('title', ''), + 'description': obj.get('description', ''), + 'tags': obj.get('tags', []), + 'favicon_url': obj.get('favicon_url', ''), + 'path': obj.get('path', ''), + 'visit_count': obj.get('visit_count', 0) + }) + + return bookmarks diff --git a/LinkSyncServer/queries/parser.py b/LinkSyncServer/queries/parser.py new file mode 100644 index 0000000..1dc45b9 --- /dev/null +++ b/LinkSyncServer/queries/parser.py @@ -0,0 +1,351 @@ +""" +LinkSyncServer - Query Parser for Expression Parser +""" + +import re +from typing import Union, Dict, List, Any +from enum import Enum + + +class TokenType(Enum): + OPERATOR = "OPERATOR" + TERM = "TERM" + VALUE = "VALUE" + LPAREN = "LPAREN" + RPAREN = "RPAREN" + + +class Token: + def __init__(self, token_type: TokenType, value: Any, line: int = 0, column: int = 0): + self.type = token_type + self.value = value + self.line = line + self.column = column + + def __repr__(self): + return f"Token({self.type.value}, {self.value!r})" + + +class QuerySyntaxError(Exception): + """Syntax error in query expression.""" + def __init__(self, message: str, line: int = None, column: int = None): + self.message = message + self.line = line + self.column = column + super().__init__(f"{message} at line {line}, column {column}" if line and column else message) + + +def lex(expression: str) -> List[Token]: + """ + Lexical analysis - convert string to tokens. + + Grammar: + expression := query_item (OP query_item)* + query_item := (expression) | value | term + term := OP | value + value := url:value | tag:value | title:value | description:value | id:value + """ + tokens = [] + pos = 0 + + # Operators + operators = ['AND', 'OR', 'XOR'] + + while pos < len(expression): + # Skip whitespace + if expression[pos].isspace(): + pos += 1 + continue + + # Check for parentheses + if expression[pos] == '(': + tokens.append(Token(TokenType.LPAREN, '(')) + pos += 1 + continue + + if expression[pos] == ')': + tokens.append(Token(TokenType.RPAREN, ')')) + pos += 1 + continue + + # Check for operators (AND, OR, XOR) + if expression[pos:pos+4] == 'AND': + tokens.append(Token(TokenType.OPERATOR, 'AND')) + pos += 4 + continue + + if expression[pos:pos+3] == 'OR': + tokens.append(Token(TokenType.OPERATOR, 'OR')) + pos += 3 + continue + + if expression[pos:pos+4] == 'XOR': + tokens.append(Token(TokenType.OPERATOR, 'XOR')) + pos += 4 + continue + + # Check for url: prefix + if expression[pos:pos+4] == 'url:': + pos += 4 + # Find end of URL + end = expression.find(':', pos) + if end == -1 and expression[pos] == '://': + # Find end of URL (next space or end of string) + end = expression.find(' ', pos) + if end == -1: + end = len(expression) + + tokens.append(Token(TokenType.TERM, expression[pos:end])) + pos = end + continue + + # Check for tag: prefix + if expression[pos:pos+5] == 'tag:': + pos += 5 + end = expression.find(':', pos) + if end == -1: + end = len(expression) + tokens.append(Token(TokenType.TERM, expression[pos:end])) + pos = end + continue + + # Check for title: or description: prefixes + if expression[pos:pos+6] in ['title:', 'description:']: + field = 'title' if expression[pos:pos+6] == 'title:' else 'description' + pos += 6 + end = expression.find(':', pos) + if end == -1 and expression[pos] == ':' : + end = len(expression) + + tokens.append(Token(TokenType.TERM, expression[pos:end])) + pos = end + continue + + # Check for colon (key:value) + if expression[pos] == ':': + pos += 1 + # Get field name (key) + field = expression[pos] + pos += 1 + # Get value + end = expression.find(' ', pos) + if end == -1: + end = len(expression) + token_val = expression[pos:end].strip('"\'') + tokens.append(Token(TokenType.VALUE, f'{field}:{token_val}')) + continue + + # Regular term - alphanumeric + if expression[pos].isalnum() or expression[pos] in '-_': + start = pos + while pos < len(expression) and (expression[pos].isalnum() or expression[pos] in '-_./?=?&'): + pos += 1 + tokens.append(Token(TokenType.TERM, expression[start:pos])) + continue + + # Unknown character - skip or error + pos += 1 + + return tokens + + +class ASTNode: + """Abstract Syntax Tree Node.""" + def __init__(self, operator: str, children: List[Union[ASTNode, str, dict]] = None): + self.operator = operator + self.children = children if children else [] + + def __repr__(self): + return f"AST({self.operator}, {self.children})" + + +def parse_operator(token: Token) -> str: + """Convert operator token to Python operator string.""" + if token.type != TokenType.OPERATOR: + raise QuerySyntaxError(f"Expected operator, got {token.value}") + + if token.value == 'AND': + return 'and' + elif token.value == 'OR': + return 'or' + elif token.value == 'XOR': + return 'xor' + else: + raise QuerySyntaxError(f"Unknown operator: {token.value}") + + +class QueryParser: + """Parser for query expressions.""" + + def __init__(self): + self.tokens = [] + self.pos = 0 + self.current_token = None + self.error = False + + def error(self, message: str): + """Record and return error.""" + self.error = True + return QuerySyntaxError(message) + + def parse_expression(self) -> List[ASTNode]: + """Parse top-level expression (list of clauses).""" + if not self.tokens: + return [] + + expressions = [] + + # Parse first clause + expr = self.parse_or() + if expr: + expressions.append(expr) + + # Parse remaining clauses + while self.current_token and self.current_token.value in ['AND', 'OR', 'XOR']: + operator = self.current_token.value + self.pos += 1 + expressions.append(operator) + expr2 = self.parse_or() + if expr2: + expressions.append(expr2) + + return expressions + + def parse_or(self) -> Union[ASTNode, None]: + """Parse OR clause.""" + if not self.current_token: + return None + + return self.parse_and() + + def parse_and(self) -> Union[ASTNode, None]: + """Parse AND clause.""" + left = self.parse_xor() + + while self.current_token and self.current_token.value == 'OR': + operator = self.parse_operator(self.current_token) + right = self.parse_xor() + left = ASTNode(operator, [left, right]) + + return left + + def parse_xor(self) -> Union[ASTNode, None]: + """Parse XOR clause.""" + left = self.parse_term() + + while self.current_token and self.current_token.value == 'AND': + operator = self.parse_operator(self.current_token) + right = self.parse_term() + left = ASTNode(operator, [left, right]) + + return left + + def parse_term(self): + """Parse term.""" + if self.error: + return None + + if self.pos >= len(self.tokens): + return None + + token = self.current_token + + # Check for parentheses (subexpression) + if token and token.value == '(': + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + sub_expr = self.parse_expression() + if not sub_expr and not self.error: + return None + if self.error: + return None + if self.current_token and self.current_token.value == ')': + self.pos += 1 + return sub_expr + elif token and token.value != ')': + return token + + def parse_value(self) -> Union[None, str]: + """Parse value term.""" + if self.error: + return None + + token = self.current_token + if not token or token.type != TokenType.TERM: + return None + + # Extract URL, TAG, etc. + term = token.value + + # Check for url: value + if term.startswith('url:'): + query = {'operation': 'TERM', 'value': term[4:]} + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + return query + elif term.startswith('tag:'): + query = {'operation': 'TERM', 'value': term[4:]} + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + return query + elif term.startswith('title:'): + query = {'operation': 'TERM', 'value': term[6:]} + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + return query + elif term.startswith('description:'): + query = {'operation': 'TERM', 'value': term[12:]} + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + return query + elif term.startswith('id:'): + query = {'operation': 'EQUALS', 'value': term[3:]} + self.pos += 1 + self.current_token = self.tokens[self.pos] if self.pos < len(self.tokens) else None + return query + elif term.startswith('"') or term.startswith("'"): + # Direct value + return term + else: + self.error(f"Unknown term: {term}") + return None + + def parse(self, expression: str) -> List[ASTNode]: + """Parse complete expression.""" + if not expression: + return [] + + # Check for empty expression + if not expression.strip(): + return [] + + # Lexical analysis + self.tokens = lex(expression) + self.pos = 0 + self.current_token = self.tokens[0] if self.tokens else None + + if not self.tokens: + return [] + + # Parse expression into AST + expr = self.parse_expression() + + # Return AST as dict + return [self.ast_to_dict(node) for node in expr] if expr else [] + + def ast_to_dict(self, node, indent=0): + """Convert AST node to dict representation.""" + if isinstance(node, ASTNode): + if node.children: + return { + "operation": node.operator, + "operands": [self.ast_to_dict(child, indent + 1) for child in node.children] + } + else: + return node.value + elif isinstance(node, str): + return node + elif isinstance(node, dict): + return node + else: + return str(node) \ No newline at end of file diff --git a/TicTacGaming/ministral-3-14b/vite.config.ts b/TicTacGaming/ministral-3-14b/vite.config.ts new file mode 100644 index 0000000..94b12e1 --- /dev/null +++ b/TicTacGaming/ministral-3-14b/vite.config.ts @@ -0,0 +1,20 @@ +import path from 'path' +import { defineConfig } from 'vite' + +const config = defineConfig({ + base: './', + resolve: { + alias: { + '@/game': path.resolve('./src', 'game.ts'), + '@/ui': path.resolve('./src', 'ui.ts') + }}, + build: { + outDir: 'dist', + emptyOutDir: true, + rollupOptions: { + input: { main: './index.html' }, + } + } +}) + +export default config diff --git a/TicTacToe-Compare/cogito-14b/game.js b/TicTacToe-Compare/cogito-14b/game.js new file mode 100644 index 0000000..ab105be --- /dev/null +++ b/TicTacToe-Compare/cogito-14b/game.js @@ -0,0 +1,21 @@ +/* Modern Tic Tac Toe JavaScript file + * Copyright (c) David, 2024. */ + +// Get DOM elementsconst gridContainer = document.getElementById('board'); +const squareButtons = Array.from(document.querySelectorAll('#board button')); + +class Game { + constructor() { + this.board = [ + [], [], [] + ]; + this.gameOver = false; + this.currentPlayer = ''; + this.movesCount = 0; + // Initialize game board squares + squareButtons.forEach( + (btn, idx) => ( + btn.addEventListener('click', () => { if(this.moveIsValid(idx)) + this.updateBoard({cell:btn,squareIndex:idx,mark:'X'}); + else alert("Game is over");} +))))}} \ No newline at end of file diff --git a/TicTacToe-Compare/cogito-14b/index.html b/TicTacToe-Compare/cogito-14b/index.html new file mode 100644 index 0000000..23636aa --- /dev/null +++ b/TicTacToe-Compare/cogito-14b/index.html @@ -0,0 +1,18 @@ +!> + + + Modern Tic-Tac-Toe + + + +
+ + +
+

Coin Flip...

+
+ + + +
\ No newline at end of file diff --git a/TicTacToe-Compare/cogito-14b/styles.css b/TicTacToe-Compare/cogito-14b/styles.css new file mode 100644 index 0000000..6440fbc --- /dev/null +++ b/TicTacToe-Compare/cogito-14b/styles.css @@ -0,0 +1,127 @@ +/* Modern Tic Tac Toe style sheet + * Copyright (c) David, 2024. */ + +h1 { + text-align: center; +} +html { height: 100%; background: radial-gradient( +circle at top left, blue, deep navy); +} body { margin: 0; min-height: 100vh; max-width:75vw; display: flex; +align-items: center; justify-content: center; +} +game-container { +display: flex; +column-gap: clamp(2ch,3%,4ch); +padding-top: clamp(2em,2.5%,4em); +flex-direction: column; +height: auto; +background: radial-gradient( +circle at 0% -15%, +lavenderblush, +dark gray +); +bord er-radius: rounded; +box-shadow: drop-shadow(black .3em 2vw .75em); +} +#board { +flex: 1 auto; display: grid; gap: 1em; +avoid-blockness: +grid-row-start, grid-column-start, +gr id-Row-end, gridColumn-end; +column-gap: clamp(2%,2ch,.86em); +row-gap: clamp(1.5%,1vw,.76em); border: solid .4em dark green;padding-top: 0; +padding-bottom: 0; padding-left: clamp(10px, 1%, 1.25em );padding-right: clamp(10px,1vw,1.5%); +} +td { +position:relative;height:fit-content; +min-height:.8375rem;justify-self: stretch; +padding:clamp(.375ch,4vw,.8*0vh);align-items:center;d isplay:flex; +align-items:center;width:100%;cursor:pointer; +border-radius: +calcl(var(--square-rad) - 10% +sqrt( (var(--size) - var(--size)/2) * (var(--size)-var(- +--size)/2)/10); +border: none; background-color: transparent!important; +onfocusout { border:none !important; outline:none!imp ortant} +padding: clamp(.375rem, .6*.475em,.8*3vh); box-shadow: +solid rgba(0, 0.2, 0.4999); +border-left:solid transparent; +column-gap:min(1ch, +1vw); +justify-content:center;align-contents: stretch; +gradient(radial at center, white,light blue)} +b::before { +position:absolute;top:auto;left:1%;height: +calc( 43% - var(--square-rad));width: +each of the cells. +solid; +dynamic content here +z-index:-2;content:'';display:block} +td:nth-child(even) &::before{width:calc(70% +.35em); +height:clamp( + 1ch, (var(--grid-scale)), .87142rem);top: +calc(var(--square-rad)*-0.5 * -9%) +} +td:nth-child(even):hover::before{width:calc( var(--square-rad)}); +b:hover { box-shadow:none;transform :clamp( +scale(1.3));z-index:2; +backface-visibility:auto; transition: transform .1s ease +out cubic-bezier(.68, -.61, .57,.94); +perspective:.01*2em!important;} +.square { +cursor:pointer;width: +clamp( 5vw ,4ch,40vh);height:clamp(3.59vw,9ch,3.795em) +}/*cell animations*/ +.animating-move { +anotation-transform:"translateZ(0)"; +perspective:.6em !important; +transform-origin:center center !important;}/*game status*/}#statsContainer {position:fixed bottom:2rem left: .3% +bottom: calc(.48 vw +3.57 rem);padding-bottom.calc(.1vmin+.3 vh); +padding top:calc(2px * var(--unitSize) /0.76vw)*100%; +display:fle d !important; background:radialgradient( +light coral,goldenrod) +l .5 ch .48em linear-gradient(90deg, rgba(0.35% 0%, 0% +.64% 8%) calc(.475rem),transparent calc(.211em) ); +border-radius:calc( clamp( 1vh,.4*1vw . 16 rem)); box-shadow:none +solid silver +,rgba(0,0,3%,10) 3.997px) + +z-index:clamp(100%,2em,54); transition:.8 s ease-in-out; +column-gap;calc(.5 % .66em ); row gap calc(.6* +, clamp(80px-.57*, 50vw) .66em) + +display:flex !important flex-direction:column flex-wrap wrap +align-items flex-start; +/*Game Stats & Messages*/} +game-container #status-banner { +--animate-fraction:1; position:absolute;height +x;opacity:.65 +pointer-events:none;visibility:hidden;z-index:61 +callback with a .7rem gap; padding 0.2%.4 em +margin-top:clamp(1.38v h, .62 vh, -2%) +backgrou nds:gold +/*Banner Animations */ +tic-tac animation for the coin flip banner*/ +crossfade to show winner/caller after game ends etc. +@keyframes coin-flip-anime { + only of frames 0%,100% +{ +box-shadow:none;}35% {height: calc(2.347vw .6 +9 em);margin- top:.8rem +} +37.5% transform:none +} animation coinflap-animate ease infinite 5s;}} +/*Hover effects on cells*/:hover td { +display:flex; +align-items:center !important justify-content:center; +css transition transform .2s ease-out cubic-bezier(.35, -0.71 , -.64); +box-shadow:none; +borders: solid .482px transparent; +border-radius:.9em;--square-rad:var(--defaultSquareRad +/*Grid Layout & Responsive Adjustments*/#board { +display:block!important; +grid-template_rows: repeat(3,var(--square-size))auto} +@media ( max-width :768px){html { +bord er-color:light brown; +color:pale goldenrod; height:auto; background:white !important +border:none } } \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/dist/index.html b/TicTacToe-Compare/ministral-3-14b/dist/index.html new file mode 100644 index 0000000..48a1ef2 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/dist/index.html @@ -0,0 +1,22 @@ + + + + + + Tic-Tac-Toe with AI + + + + + +
+

โœ–๏ธ Tic-Tac-Toe โœ–๏ธ

+
+
+

๐Ÿ‘ค X Player

+

๐Ÿค– O Computer

+ +
+ + + diff --git a/TicTacToe-Compare/ministral-3-14b/index.html b/TicTacToe-Compare/ministral-3-14b/index.html new file mode 100644 index 0000000..48a1ef2 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/index.html @@ -0,0 +1,22 @@ + + + + + + Tic-Tac-Toe with AI + + + + + +
+

โœ–๏ธ Tic-Tac-Toe โœ–๏ธ

+
+
+

๐Ÿ‘ค X Player

+

๐Ÿค– O Computer

+ +
+ + + diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite new file mode 100644 index 0000000..1e66929 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../create-vite/index.js" "$@" +else + exec node "$basedir/../create-vite/index.js" "$@" +fi diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.cmd b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.cmd new file mode 100644 index 0000000..b15494e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\create-vite\index.js" %* diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.ps1 b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.ps1 new file mode 100644 index 0000000..bb9096f --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/create-vite.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../create-vite/index.js" $args + } else { + & "$basedir/node$exe" "$basedir/../create-vite/index.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../create-vite/index.js" $args + } else { + & "node$exe" "$basedir/../create-vite/index.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva new file mode 100644 index 0000000..1e66929 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../create-vite/index.js" "$@" +else + exec node "$basedir/../create-vite/index.js" "$@" +fi diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.cmd b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.cmd new file mode 100644 index 0000000..b15494e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\create-vite\index.js" %* diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.ps1 b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.ps1 new file mode 100644 index 0000000..bb9096f --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/cva.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../create-vite/index.js" $args + } else { + & "$basedir/node$exe" "$basedir/../create-vite/index.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../create-vite/index.js" $args + } else { + & "node$exe" "$basedir/../create-vite/index.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid new file mode 100644 index 0000000..46220bd --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.cjs" "$@" +else + exec node "$basedir/../nanoid/bin/nanoid.cjs" "$@" +fi diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.cmd b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.cmd new file mode 100644 index 0000000..9c40107 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.cjs" %* diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.ps1 b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.ps1 new file mode 100644 index 0000000..d8a4d7a --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/nanoid.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } else { + & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } else { + & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown new file mode 100644 index 0000000..e7853ee --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../rolldown/bin/cli.mjs" "$@" +else + exec node "$basedir/../rolldown/bin/cli.mjs" "$@" +fi diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.cmd b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.cmd new file mode 100644 index 0000000..1882f3e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rolldown\bin\cli.mjs" %* diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.ps1 b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.ps1 new file mode 100644 index 0000000..145fb8e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/rolldown.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../rolldown/bin/cli.mjs" $args + } else { + & "$basedir/node$exe" "$basedir/../rolldown/bin/cli.mjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../rolldown/bin/cli.mjs" $args + } else { + & "node$exe" "$basedir/../rolldown/bin/cli.mjs" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite new file mode 100644 index 0000000..014463f --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@" +else + exec node "$basedir/../vite/bin/vite.js" "$@" +fi diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.cmd b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.cmd new file mode 100644 index 0000000..f62e966 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\vite\bin\vite.js" %* diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.ps1 b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.ps1 new file mode 100644 index 0000000..a7759bc --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.bin/vite.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/.package-lock.json b/TicTacToe-Compare/ministral-3-14b/node_modules/.package-lock.json new file mode 100644 index 0000000..c620ad7 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/.package-lock.json @@ -0,0 +1,344 @@ +{ + "name": "tictactoe", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@oxc-project/types": { + "version": "0.130.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", + "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", + "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-vite": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/create-vite/-/create-vite-9.0.7.tgz", + "integrity": "sha512-TyuOQvwX4i/QN9acJzC7wzM7FfC12/1XlH3+d05PeD7Kj5o4BObuq78fB1x84SrEoi5KcQOi+b9K3JV+PWNHvw==", + "license": "MIT", + "bin": { + "create-vite": "index.js", + "cva": "index.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rolldown": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", + "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.130.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.1", + "@rolldown/binding-darwin-arm64": "1.0.1", + "@rolldown/binding-darwin-x64": "1.0.1", + "@rolldown/binding-freebsd-x64": "1.0.1", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", + "@rolldown/binding-linux-arm64-gnu": "1.0.1", + "@rolldown/binding-linux-arm64-musl": "1.0.1", + "@rolldown/binding-linux-ppc64-gnu": "1.0.1", + "@rolldown/binding-linux-s390x-gnu": "1.0.1", + "@rolldown/binding-linux-x64-gnu": "1.0.1", + "@rolldown/binding-linux-x64-musl": "1.0.1", + "@rolldown/binding-openharmony-arm64": "1.0.1", + "@rolldown/binding-wasm32-wasi": "1.0.1", + "@rolldown/binding-win32-arm64-msvc": "1.0.1", + "@rolldown/binding-win32-x64-msvc": "1.0.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/vite": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", + "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "rolldown": "1.0.1", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.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" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/LICENSE b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/LICENSE new file mode 100644 index 0000000..444bffc --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2024-present VoidZero Inc. & Contributors +Copyright (c) 2023 Boshen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/README.md b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/README.md new file mode 100644 index 0000000..d5b248a --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/README.md @@ -0,0 +1,3 @@ +# Oxc Types + +Typescript definitions for Oxc AST nodes. diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/package.json b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/package.json new file mode 100644 index 0000000..94d442f --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/package.json @@ -0,0 +1,26 @@ +{ + "name": "@oxc-project/types", + "version": "0.130.0", + "description": "Types for Oxc AST nodes", + "keywords": [ + "AST", + "Parser" + ], + "homepage": "https://oxc.rs", + "bugs": "https://github.com/oxc-project/oxc/issues", + "license": "MIT", + "author": "Boshen and oxc contributors", + "repository": { + "type": "git", + "url": "git+https://github.com/oxc-project/oxc.git", + "directory": "npm/oxc-types" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "files": [ + "types.d.ts" + ], + "type": "module", + "types": "types.d.ts" +} \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/types.d.ts b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/types.d.ts new file mode 100644 index 0000000..c94c115 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@oxc-project/types/types.d.ts @@ -0,0 +1,1912 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/typescript.rs`. + +export interface Program extends Span { + type: "Program"; + body: Array; + sourceType: ModuleKind; + hashbang: Hashbang | null; + parent?: null; +} + +export type Expression = + | BooleanLiteral + | NullLiteral + | NumericLiteral + | BigIntLiteral + | RegExpLiteral + | StringLiteral + | TemplateLiteral + | IdentifierReference + | MetaProperty + | Super + | ArrayExpression + | ArrowFunctionExpression + | AssignmentExpression + | AwaitExpression + | BinaryExpression + | CallExpression + | ChainExpression + | Class + | ConditionalExpression + | Function + | ImportExpression + | LogicalExpression + | NewExpression + | ObjectExpression + | ParenthesizedExpression + | SequenceExpression + | TaggedTemplateExpression + | ThisExpression + | UnaryExpression + | UpdateExpression + | YieldExpression + | PrivateInExpression + | JSXElement + | JSXFragment + | TSAsExpression + | TSSatisfiesExpression + | TSTypeAssertion + | TSNonNullExpression + | TSInstantiationExpression + | V8IntrinsicExpression + | MemberExpression; + +export interface IdentifierName extends Span { + type: "Identifier"; + decorators?: []; + name: string; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface IdentifierReference extends Span { + type: "Identifier"; + decorators?: []; + name: string; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface BindingIdentifier extends Span { + type: "Identifier"; + decorators?: []; + name: string; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface LabelIdentifier extends Span { + type: "Identifier"; + decorators?: []; + name: string; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface ThisExpression extends Span { + type: "ThisExpression"; + parent?: Node; +} + +export interface ArrayExpression extends Span { + type: "ArrayExpression"; + elements: Array; + parent?: Node; +} + +export type ArrayExpressionElement = SpreadElement | null | Expression; + +export interface ObjectExpression extends Span { + type: "ObjectExpression"; + properties: Array; + parent?: Node; +} + +export type ObjectPropertyKind = ObjectProperty | SpreadElement; + +export interface ObjectProperty extends Span { + type: "Property"; + kind: PropertyKind; + key: PropertyKey; + value: Expression; + method: boolean; + shorthand: boolean; + computed: boolean; + optional?: false; + parent?: Node; +} + +export type PropertyKey = IdentifierName | PrivateIdentifier | Expression; + +export type PropertyKind = "init" | "get" | "set"; + +export interface TemplateLiteral extends Span { + type: "TemplateLiteral"; + quasis: Array; + expressions: Array; + parent?: Node; +} + +export interface TaggedTemplateExpression extends Span { + type: "TaggedTemplateExpression"; + tag: Expression; + typeArguments?: TSTypeParameterInstantiation | null; + quasi: TemplateLiteral; + parent?: Node; +} + +export interface TemplateElement extends Span { + type: "TemplateElement"; + value: TemplateElementValue; + tail: boolean; + parent?: Node; +} + +export interface TemplateElementValue { + raw: string; + cooked: string | null; +} + +export type MemberExpression = + | ComputedMemberExpression + | StaticMemberExpression + | PrivateFieldExpression; + +export interface ComputedMemberExpression extends Span { + type: "MemberExpression"; + object: Expression; + property: Expression; + optional: boolean; + computed: true; + parent?: Node; +} + +export interface StaticMemberExpression extends Span { + type: "MemberExpression"; + object: Expression; + property: IdentifierName; + optional: boolean; + computed: false; + parent?: Node; +} + +export interface PrivateFieldExpression extends Span { + type: "MemberExpression"; + object: Expression; + property: PrivateIdentifier; + optional: boolean; + computed: false; + parent?: Node; +} + +export interface CallExpression extends Span { + type: "CallExpression"; + callee: Expression; + typeArguments?: TSTypeParameterInstantiation | null; + arguments: Array; + optional: boolean; + parent?: Node; +} + +export interface NewExpression extends Span { + type: "NewExpression"; + callee: Expression; + typeArguments?: TSTypeParameterInstantiation | null; + arguments: Array; + parent?: Node; +} + +export interface MetaProperty extends Span { + type: "MetaProperty"; + meta: IdentifierName; + property: IdentifierName; + parent?: Node; +} + +export interface SpreadElement extends Span { + type: "SpreadElement"; + argument: Expression; + parent?: Node; +} + +export type Argument = SpreadElement | Expression; + +export interface UpdateExpression extends Span { + type: "UpdateExpression"; + operator: UpdateOperator; + prefix: boolean; + argument: SimpleAssignmentTarget; + parent?: Node; +} + +export interface UnaryExpression extends Span { + type: "UnaryExpression"; + operator: UnaryOperator; + argument: Expression; + prefix: true; + parent?: Node; +} + +export interface BinaryExpression extends Span { + type: "BinaryExpression"; + left: Expression; + operator: BinaryOperator; + right: Expression; + parent?: Node; +} + +export interface PrivateInExpression extends Span { + type: "BinaryExpression"; + left: PrivateIdentifier; + operator: "in"; + right: Expression; + parent?: Node; +} + +export interface LogicalExpression extends Span { + type: "LogicalExpression"; + left: Expression; + operator: LogicalOperator; + right: Expression; + parent?: Node; +} + +export interface ConditionalExpression extends Span { + type: "ConditionalExpression"; + test: Expression; + consequent: Expression; + alternate: Expression; + parent?: Node; +} + +export interface AssignmentExpression extends Span { + type: "AssignmentExpression"; + operator: AssignmentOperator; + left: AssignmentTarget; + right: Expression; + parent?: Node; +} + +export type AssignmentTarget = SimpleAssignmentTarget | AssignmentTargetPattern; + +export type SimpleAssignmentTarget = + | IdentifierReference + | TSAsExpression + | TSSatisfiesExpression + | TSNonNullExpression + | TSTypeAssertion + | MemberExpression; + +export type AssignmentTargetPattern = ArrayAssignmentTarget | ObjectAssignmentTarget; + +export interface ArrayAssignmentTarget extends Span { + type: "ArrayPattern"; + decorators?: []; + elements: Array; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface ObjectAssignmentTarget extends Span { + type: "ObjectPattern"; + decorators?: []; + properties: Array; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface AssignmentTargetRest extends Span { + type: "RestElement"; + decorators?: []; + argument: AssignmentTarget; + optional?: false; + typeAnnotation?: null; + value?: null; + parent?: Node; +} + +export type AssignmentTargetMaybeDefault = AssignmentTargetWithDefault | AssignmentTarget; + +export interface AssignmentTargetWithDefault extends Span { + type: "AssignmentPattern"; + decorators?: []; + left: AssignmentTarget; + right: Expression; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export type AssignmentTargetProperty = + | AssignmentTargetPropertyIdentifier + | AssignmentTargetPropertyProperty; + +export interface AssignmentTargetPropertyIdentifier extends Span { + type: "Property"; + kind: "init"; + key: IdentifierReference; + value: IdentifierReference | AssignmentTargetWithDefault; + method: false; + shorthand: true; + computed: false; + optional?: false; + parent?: Node; +} + +export interface AssignmentTargetPropertyProperty extends Span { + type: "Property"; + kind: "init"; + key: PropertyKey; + value: AssignmentTargetMaybeDefault; + method: false; + shorthand: false; + computed: boolean; + optional?: false; + parent?: Node; +} + +export interface SequenceExpression extends Span { + type: "SequenceExpression"; + expressions: Array; + parent?: Node; +} + +export interface Super extends Span { + type: "Super"; + parent?: Node; +} + +export interface AwaitExpression extends Span { + type: "AwaitExpression"; + argument: Expression; + parent?: Node; +} + +export interface ChainExpression extends Span { + type: "ChainExpression"; + expression: ChainElement; + parent?: Node; +} + +export type ChainElement = CallExpression | TSNonNullExpression | MemberExpression; + +export interface ParenthesizedExpression extends Span { + type: "ParenthesizedExpression"; + expression: Expression; + parent?: Node; +} + +export type Statement = + | BlockStatement + | BreakStatement + | ContinueStatement + | DebuggerStatement + | DoWhileStatement + | EmptyStatement + | ExpressionStatement + | ForInStatement + | ForOfStatement + | ForStatement + | IfStatement + | LabeledStatement + | ReturnStatement + | SwitchStatement + | ThrowStatement + | TryStatement + | WhileStatement + | WithStatement + | Declaration + | ModuleDeclaration; + +export interface Directive extends Span { + type: "ExpressionStatement"; + expression: StringLiteral; + directive: string; + parent?: Node; +} + +export interface Hashbang extends Span { + type: "Hashbang"; + value: string; + parent?: Node; +} + +export interface BlockStatement extends Span { + type: "BlockStatement"; + body: Array; + parent?: Node; +} + +export type Declaration = + | VariableDeclaration + | Function + | Class + | TSTypeAliasDeclaration + | TSInterfaceDeclaration + | TSEnumDeclaration + | TSModuleDeclaration + | TSGlobalDeclaration + | TSImportEqualsDeclaration; + +export interface VariableDeclaration extends Span { + type: "VariableDeclaration"; + kind: VariableDeclarationKind; + declarations: Array; + declare?: boolean; + parent?: Node; +} + +export type VariableDeclarationKind = "var" | "let" | "const" | "using" | "await using"; + +export interface VariableDeclarator extends Span { + type: "VariableDeclarator"; + id: BindingPattern; + init: Expression | null; + definite?: boolean; + parent?: Node; +} + +export interface EmptyStatement extends Span { + type: "EmptyStatement"; + parent?: Node; +} + +export interface ExpressionStatement extends Span { + type: "ExpressionStatement"; + expression: Expression; + directive?: string | null; + parent?: Node; +} + +export interface IfStatement extends Span { + type: "IfStatement"; + test: Expression; + consequent: Statement; + alternate: Statement | null; + parent?: Node; +} + +export interface DoWhileStatement extends Span { + type: "DoWhileStatement"; + body: Statement; + test: Expression; + parent?: Node; +} + +export interface WhileStatement extends Span { + type: "WhileStatement"; + test: Expression; + body: Statement; + parent?: Node; +} + +export interface ForStatement extends Span { + type: "ForStatement"; + init: ForStatementInit | null; + test: Expression | null; + update: Expression | null; + body: Statement; + parent?: Node; +} + +export type ForStatementInit = VariableDeclaration | Expression; + +export interface ForInStatement extends Span { + type: "ForInStatement"; + left: ForStatementLeft; + right: Expression; + body: Statement; + parent?: Node; +} + +export type ForStatementLeft = VariableDeclaration | AssignmentTarget; + +export interface ForOfStatement extends Span { + type: "ForOfStatement"; + await: boolean; + left: ForStatementLeft; + right: Expression; + body: Statement; + parent?: Node; +} + +export interface ContinueStatement extends Span { + type: "ContinueStatement"; + label: LabelIdentifier | null; + parent?: Node; +} + +export interface BreakStatement extends Span { + type: "BreakStatement"; + label: LabelIdentifier | null; + parent?: Node; +} + +export interface ReturnStatement extends Span { + type: "ReturnStatement"; + argument: Expression | null; + parent?: Node; +} + +export interface WithStatement extends Span { + type: "WithStatement"; + object: Expression; + body: Statement; + parent?: Node; +} + +export interface SwitchStatement extends Span { + type: "SwitchStatement"; + discriminant: Expression; + cases: Array; + parent?: Node; +} + +export interface SwitchCase extends Span { + type: "SwitchCase"; + test: Expression | null; + consequent: Array; + parent?: Node; +} + +export interface LabeledStatement extends Span { + type: "LabeledStatement"; + label: LabelIdentifier; + body: Statement; + parent?: Node; +} + +export interface ThrowStatement extends Span { + type: "ThrowStatement"; + argument: Expression; + parent?: Node; +} + +export interface TryStatement extends Span { + type: "TryStatement"; + block: BlockStatement; + handler: CatchClause | null; + finalizer: BlockStatement | null; + parent?: Node; +} + +export interface CatchClause extends Span { + type: "CatchClause"; + param: BindingPattern | null; + body: BlockStatement; + parent?: Node; +} + +export interface DebuggerStatement extends Span { + type: "DebuggerStatement"; + parent?: Node; +} + +export type BindingPattern = BindingIdentifier | ObjectPattern | ArrayPattern | AssignmentPattern; + +export interface AssignmentPattern extends Span { + type: "AssignmentPattern"; + decorators?: []; + left: BindingPattern; + right: Expression; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface ObjectPattern extends Span { + type: "ObjectPattern"; + decorators?: []; + properties: Array; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface BindingProperty extends Span { + type: "Property"; + kind: "init"; + key: PropertyKey; + value: BindingPattern; + method: false; + shorthand: boolean; + computed: boolean; + optional?: false; + parent?: Node; +} + +export interface ArrayPattern extends Span { + type: "ArrayPattern"; + decorators?: []; + elements: Array; + optional?: false; + typeAnnotation?: null; + parent?: Node; +} + +export interface BindingRestElement extends Span { + type: "RestElement"; + decorators?: []; + argument: BindingPattern; + optional?: false; + typeAnnotation?: null; + value?: null; + parent?: Node; +} + +export interface Function extends Span { + type: FunctionType; + id: BindingIdentifier | null; + generator: boolean; + async: boolean; + declare?: boolean; + typeParameters?: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType?: TSTypeAnnotation | null; + body: FunctionBody | null; + expression: false; + parent?: Node; +} + +export type ParamPattern = FormalParameter | TSParameterProperty | FormalParameterRest; + +export type FunctionType = + | "FunctionDeclaration" + | "FunctionExpression" + | "TSDeclareFunction" + | "TSEmptyBodyFunctionExpression"; + +export interface FormalParameterRest extends Span { + type: "RestElement"; + argument: BindingPattern; + decorators?: []; + optional?: boolean; + typeAnnotation?: TSTypeAnnotation | null; + value?: null; + parent?: Node; +} + +export type FormalParameter = { + decorators?: Array; +} & BindingPattern; + +export interface TSParameterProperty extends Span { + type: "TSParameterProperty"; + accessibility: TSAccessibility | null; + decorators: Array; + override: boolean; + parameter: FormalParameter; + readonly: boolean; + static: boolean; + parent?: Node; +} + +export interface FunctionBody extends Span { + type: "BlockStatement"; + body: Array; + parent?: Node; +} + +export interface ArrowFunctionExpression extends Span { + type: "ArrowFunctionExpression"; + expression: boolean; + async: boolean; + typeParameters?: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType?: TSTypeAnnotation | null; + body: FunctionBody | Expression; + id: null; + generator: false; + parent?: Node; +} + +export interface YieldExpression extends Span { + type: "YieldExpression"; + delegate: boolean; + argument: Expression | null; + parent?: Node; +} + +export interface Class extends Span { + type: ClassType; + decorators: Array; + id: BindingIdentifier | null; + typeParameters?: TSTypeParameterDeclaration | null; + superClass: Expression | null; + superTypeArguments?: TSTypeParameterInstantiation | null; + implements?: Array; + body: ClassBody; + abstract?: boolean; + declare?: boolean; + parent?: Node; +} + +export type ClassType = "ClassDeclaration" | "ClassExpression"; + +export interface ClassBody extends Span { + type: "ClassBody"; + body: Array; + parent?: Node; +} + +export type ClassElement = + | StaticBlock + | MethodDefinition + | PropertyDefinition + | AccessorProperty + | TSIndexSignature; + +export interface MethodDefinition extends Span { + type: MethodDefinitionType; + decorators: Array; + key: PropertyKey; + value: Function; + kind: MethodDefinitionKind; + computed: boolean; + static: boolean; + override?: boolean; + optional?: boolean; + accessibility?: TSAccessibility | null; + parent?: Node; +} + +export type MethodDefinitionType = "MethodDefinition" | "TSAbstractMethodDefinition"; + +export interface PropertyDefinition extends Span { + type: PropertyDefinitionType; + decorators: Array; + key: PropertyKey; + typeAnnotation?: TSTypeAnnotation | null; + value: Expression | null; + computed: boolean; + static: boolean; + declare?: boolean; + override?: boolean; + optional?: boolean; + definite?: boolean; + readonly?: boolean; + accessibility?: TSAccessibility | null; + parent?: Node; +} + +export type PropertyDefinitionType = "PropertyDefinition" | "TSAbstractPropertyDefinition"; + +export type MethodDefinitionKind = "constructor" | "method" | "get" | "set"; + +export interface PrivateIdentifier extends Span { + type: "PrivateIdentifier"; + name: string; + parent?: Node; +} + +export interface StaticBlock extends Span { + type: "StaticBlock"; + body: Array; + parent?: Node; +} + +export type ModuleDeclaration = + | ImportDeclaration + | ExportAllDeclaration + | ExportDefaultDeclaration + | ExportNamedDeclaration + | TSExportAssignment + | TSNamespaceExportDeclaration; + +export type AccessorPropertyType = "AccessorProperty" | "TSAbstractAccessorProperty"; + +export interface AccessorProperty extends Span { + type: AccessorPropertyType; + decorators: Array; + key: PropertyKey; + typeAnnotation?: TSTypeAnnotation | null; + value: Expression | null; + computed: boolean; + static: boolean; + override?: boolean; + definite?: boolean; + accessibility?: TSAccessibility | null; + declare?: false; + optional?: false; + readonly?: false; + parent?: Node; +} + +export interface ImportExpression extends Span { + type: "ImportExpression"; + source: Expression; + options: Expression | null; + phase: ImportPhase | null; + parent?: Node; +} + +export interface ImportDeclaration extends Span { + type: "ImportDeclaration"; + specifiers: Array; + source: StringLiteral; + phase: ImportPhase | null; + attributes: Array; + importKind?: ImportOrExportKind; + parent?: Node; +} + +export type ImportPhase = "source" | "defer"; + +export type ImportDeclarationSpecifier = + | ImportSpecifier + | ImportDefaultSpecifier + | ImportNamespaceSpecifier; + +export interface ImportSpecifier extends Span { + type: "ImportSpecifier"; + imported: ModuleExportName; + local: BindingIdentifier; + importKind?: ImportOrExportKind; + parent?: Node; +} + +export interface ImportDefaultSpecifier extends Span { + type: "ImportDefaultSpecifier"; + local: BindingIdentifier; + parent?: Node; +} + +export interface ImportNamespaceSpecifier extends Span { + type: "ImportNamespaceSpecifier"; + local: BindingIdentifier; + parent?: Node; +} + +export interface ImportAttribute extends Span { + type: "ImportAttribute"; + key: ImportAttributeKey; + value: StringLiteral; + parent?: Node; +} + +export type ImportAttributeKey = IdentifierName | StringLiteral; + +export interface ExportNamedDeclaration extends Span { + type: "ExportNamedDeclaration"; + declaration: Declaration | null; + specifiers: Array; + source: StringLiteral | null; + exportKind?: ImportOrExportKind; + attributes: Array; + parent?: Node; +} + +export interface ExportDefaultDeclaration extends Span { + type: "ExportDefaultDeclaration"; + declaration: ExportDefaultDeclarationKind; + exportKind?: "value"; + parent?: Node; +} + +export interface ExportAllDeclaration extends Span { + type: "ExportAllDeclaration"; + exported: ModuleExportName | null; + source: StringLiteral; + attributes: Array; + exportKind?: ImportOrExportKind; + parent?: Node; +} + +export interface ExportSpecifier extends Span { + type: "ExportSpecifier"; + local: ModuleExportName; + exported: ModuleExportName; + exportKind?: ImportOrExportKind; + parent?: Node; +} + +export type ExportDefaultDeclarationKind = Function | Class | TSInterfaceDeclaration | Expression; + +export type ModuleExportName = IdentifierName | IdentifierReference | StringLiteral; + +export interface V8IntrinsicExpression extends Span { + type: "V8IntrinsicExpression"; + name: IdentifierName; + arguments: Array; + parent?: Node; +} + +export interface BooleanLiteral extends Span { + type: "Literal"; + value: boolean; + raw: string | null; + parent?: Node; +} + +export interface NullLiteral extends Span { + type: "Literal"; + value: null; + raw: "null" | null; + parent?: Node; +} + +export interface NumericLiteral extends Span { + type: "Literal"; + value: number; + raw: string | null; + parent?: Node; +} + +export interface StringLiteral extends Span { + type: "Literal"; + value: string; + raw: string | null; + parent?: Node; +} + +export interface BigIntLiteral extends Span { + type: "Literal"; + value: bigint; + raw: string | null; + bigint: string; + parent?: Node; +} + +export interface RegExpLiteral extends Span { + type: "Literal"; + value: RegExp | null; + raw: string | null; + regex: { pattern: string; flags: string }; + parent?: Node; +} + +export interface JSXElement extends Span { + type: "JSXElement"; + openingElement: JSXOpeningElement; + children: Array; + closingElement: JSXClosingElement | null; + parent?: Node; +} + +export interface JSXOpeningElement extends Span { + type: "JSXOpeningElement"; + name: JSXElementName; + typeArguments?: TSTypeParameterInstantiation | null; + attributes: Array; + selfClosing: boolean; + parent?: Node; +} + +export interface JSXClosingElement extends Span { + type: "JSXClosingElement"; + name: JSXElementName; + parent?: Node; +} + +export interface JSXFragment extends Span { + type: "JSXFragment"; + openingFragment: JSXOpeningFragment; + children: Array; + closingFragment: JSXClosingFragment; + parent?: Node; +} + +export interface JSXOpeningFragment extends Span { + type: "JSXOpeningFragment"; + attributes?: []; + selfClosing?: false; + parent?: Node; +} + +export interface JSXClosingFragment extends Span { + type: "JSXClosingFragment"; + parent?: Node; +} + +export type JSXElementName = JSXIdentifier | JSXNamespacedName | JSXMemberExpression; + +export interface JSXNamespacedName extends Span { + type: "JSXNamespacedName"; + namespace: JSXIdentifier; + name: JSXIdentifier; + parent?: Node; +} + +export interface JSXMemberExpression extends Span { + type: "JSXMemberExpression"; + object: JSXMemberExpressionObject; + property: JSXIdentifier; + parent?: Node; +} + +export type JSXMemberExpressionObject = JSXIdentifier | JSXMemberExpression; + +export interface JSXExpressionContainer extends Span { + type: "JSXExpressionContainer"; + expression: JSXExpression; + parent?: Node; +} + +export type JSXExpression = JSXEmptyExpression | Expression; + +export interface JSXEmptyExpression extends Span { + type: "JSXEmptyExpression"; + parent?: Node; +} + +export type JSXAttributeItem = JSXAttribute | JSXSpreadAttribute; + +export interface JSXAttribute extends Span { + type: "JSXAttribute"; + name: JSXAttributeName; + value: JSXAttributeValue | null; + parent?: Node; +} + +export interface JSXSpreadAttribute extends Span { + type: "JSXSpreadAttribute"; + argument: Expression; + parent?: Node; +} + +export type JSXAttributeName = JSXIdentifier | JSXNamespacedName; + +export type JSXAttributeValue = StringLiteral | JSXExpressionContainer | JSXElement | JSXFragment; + +export interface JSXIdentifier extends Span { + type: "JSXIdentifier"; + name: string; + parent?: Node; +} + +export type JSXChild = JSXText | JSXElement | JSXFragment | JSXExpressionContainer | JSXSpreadChild; + +export interface JSXSpreadChild extends Span { + type: "JSXSpreadChild"; + expression: Expression; + parent?: Node; +} + +export interface JSXText extends Span { + type: "JSXText"; + value: string; + raw: string | null; + parent?: Node; +} + +export interface TSThisParameter extends Span { + type: "Identifier"; + decorators: []; + name: "this"; + optional: false; + typeAnnotation: TSTypeAnnotation | null; + parent?: Node; +} + +export interface TSEnumDeclaration extends Span { + type: "TSEnumDeclaration"; + id: BindingIdentifier; + body: TSEnumBody; + const: boolean; + declare: boolean; + parent?: Node; +} + +export interface TSEnumBody extends Span { + type: "TSEnumBody"; + members: Array; + parent?: Node; +} + +export interface TSEnumMember extends Span { + type: "TSEnumMember"; + id: TSEnumMemberName; + initializer: Expression | null; + computed: boolean; + parent?: Node; +} + +export type TSEnumMemberName = IdentifierName | StringLiteral | TemplateLiteral; + +export interface TSTypeAnnotation extends Span { + type: "TSTypeAnnotation"; + typeAnnotation: TSType; + parent?: Node; +} + +export interface TSLiteralType extends Span { + type: "TSLiteralType"; + literal: TSLiteral; + parent?: Node; +} + +export type TSLiteral = + | BooleanLiteral + | NumericLiteral + | BigIntLiteral + | StringLiteral + | TemplateLiteral + | UnaryExpression; + +export type TSType = + | TSAnyKeyword + | TSBigIntKeyword + | TSBooleanKeyword + | TSIntrinsicKeyword + | TSNeverKeyword + | TSNullKeyword + | TSNumberKeyword + | TSObjectKeyword + | TSStringKeyword + | TSSymbolKeyword + | TSUndefinedKeyword + | TSUnknownKeyword + | TSVoidKeyword + | TSArrayType + | TSConditionalType + | TSConstructorType + | TSFunctionType + | TSImportType + | TSIndexedAccessType + | TSInferType + | TSIntersectionType + | TSLiteralType + | TSMappedType + | TSNamedTupleMember + | TSTemplateLiteralType + | TSThisType + | TSTupleType + | TSTypeLiteral + | TSTypeOperator + | TSTypePredicate + | TSTypeQuery + | TSTypeReference + | TSUnionType + | TSParenthesizedType + | JSDocNullableType + | JSDocNonNullableType + | JSDocUnknownType; + +export interface TSConditionalType extends Span { + type: "TSConditionalType"; + checkType: TSType; + extendsType: TSType; + trueType: TSType; + falseType: TSType; + parent?: Node; +} + +export interface TSUnionType extends Span { + type: "TSUnionType"; + types: Array; + parent?: Node; +} + +export interface TSIntersectionType extends Span { + type: "TSIntersectionType"; + types: Array; + parent?: Node; +} + +export interface TSParenthesizedType extends Span { + type: "TSParenthesizedType"; + typeAnnotation: TSType; + parent?: Node; +} + +export interface TSTypeOperator extends Span { + type: "TSTypeOperator"; + operator: TSTypeOperatorOperator; + typeAnnotation: TSType; + parent?: Node; +} + +export type TSTypeOperatorOperator = "keyof" | "unique" | "readonly"; + +export interface TSArrayType extends Span { + type: "TSArrayType"; + elementType: TSType; + parent?: Node; +} + +export interface TSIndexedAccessType extends Span { + type: "TSIndexedAccessType"; + objectType: TSType; + indexType: TSType; + parent?: Node; +} + +export interface TSTupleType extends Span { + type: "TSTupleType"; + elementTypes: Array; + parent?: Node; +} + +export interface TSNamedTupleMember extends Span { + type: "TSNamedTupleMember"; + label: IdentifierName; + elementType: TSTupleElement; + optional: boolean; + parent?: Node; +} + +export interface TSOptionalType extends Span { + type: "TSOptionalType"; + typeAnnotation: TSType; + parent?: Node; +} + +export interface TSRestType extends Span { + type: "TSRestType"; + typeAnnotation: TSType; + parent?: Node; +} + +export type TSTupleElement = TSOptionalType | TSRestType | TSType; + +export interface TSAnyKeyword extends Span { + type: "TSAnyKeyword"; + parent?: Node; +} + +export interface TSStringKeyword extends Span { + type: "TSStringKeyword"; + parent?: Node; +} + +export interface TSBooleanKeyword extends Span { + type: "TSBooleanKeyword"; + parent?: Node; +} + +export interface TSNumberKeyword extends Span { + type: "TSNumberKeyword"; + parent?: Node; +} + +export interface TSNeverKeyword extends Span { + type: "TSNeverKeyword"; + parent?: Node; +} + +export interface TSIntrinsicKeyword extends Span { + type: "TSIntrinsicKeyword"; + parent?: Node; +} + +export interface TSUnknownKeyword extends Span { + type: "TSUnknownKeyword"; + parent?: Node; +} + +export interface TSNullKeyword extends Span { + type: "TSNullKeyword"; + parent?: Node; +} + +export interface TSUndefinedKeyword extends Span { + type: "TSUndefinedKeyword"; + parent?: Node; +} + +export interface TSVoidKeyword extends Span { + type: "TSVoidKeyword"; + parent?: Node; +} + +export interface TSSymbolKeyword extends Span { + type: "TSSymbolKeyword"; + parent?: Node; +} + +export interface TSThisType extends Span { + type: "TSThisType"; + parent?: Node; +} + +export interface TSObjectKeyword extends Span { + type: "TSObjectKeyword"; + parent?: Node; +} + +export interface TSBigIntKeyword extends Span { + type: "TSBigIntKeyword"; + parent?: Node; +} + +export interface TSTypeReference extends Span { + type: "TSTypeReference"; + typeName: TSTypeName; + typeArguments: TSTypeParameterInstantiation | null; + parent?: Node; +} + +export type TSTypeName = IdentifierReference | TSQualifiedName | ThisExpression; + +export interface TSQualifiedName extends Span { + type: "TSQualifiedName"; + left: TSTypeName; + right: IdentifierName; + parent?: Node; +} + +export interface TSTypeParameterInstantiation extends Span { + type: "TSTypeParameterInstantiation"; + params: Array; + parent?: Node; +} + +export interface TSTypeParameter extends Span { + type: "TSTypeParameter"; + name: BindingIdentifier; + constraint: TSType | null; + default: TSType | null; + in: boolean; + out: boolean; + const: boolean; + parent?: Node; +} + +export interface TSTypeParameterDeclaration extends Span { + type: "TSTypeParameterDeclaration"; + params: Array; + parent?: Node; +} + +export interface TSTypeAliasDeclaration extends Span { + type: "TSTypeAliasDeclaration"; + id: BindingIdentifier; + typeParameters: TSTypeParameterDeclaration | null; + typeAnnotation: TSType; + declare: boolean; + parent?: Node; +} + +export type TSAccessibility = "private" | "protected" | "public"; + +export interface TSClassImplements extends Span { + type: "TSClassImplements"; + expression: IdentifierReference | ThisExpression | MemberExpression; + typeArguments: TSTypeParameterInstantiation | null; + parent?: Node; +} + +export interface TSInterfaceDeclaration extends Span { + type: "TSInterfaceDeclaration"; + id: BindingIdentifier; + typeParameters: TSTypeParameterDeclaration | null; + extends: Array; + body: TSInterfaceBody; + declare: boolean; + parent?: Node; +} + +export interface TSInterfaceBody extends Span { + type: "TSInterfaceBody"; + body: Array; + parent?: Node; +} + +export interface TSPropertySignature extends Span { + type: "TSPropertySignature"; + computed: boolean; + optional: boolean; + readonly: boolean; + key: PropertyKey; + typeAnnotation: TSTypeAnnotation | null; + accessibility: null; + static: false; + parent?: Node; +} + +export type TSSignature = + | TSIndexSignature + | TSPropertySignature + | TSCallSignatureDeclaration + | TSConstructSignatureDeclaration + | TSMethodSignature; + +export interface TSIndexSignature extends Span { + type: "TSIndexSignature"; + parameters: Array; + typeAnnotation: TSTypeAnnotation; + readonly: boolean; + static: boolean; + accessibility: null; + parent?: Node; +} + +export interface TSCallSignatureDeclaration extends Span { + type: "TSCallSignatureDeclaration"; + typeParameters: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType: TSTypeAnnotation | null; + parent?: Node; +} + +export type TSMethodSignatureKind = "method" | "get" | "set"; + +export interface TSMethodSignature extends Span { + type: "TSMethodSignature"; + key: PropertyKey; + computed: boolean; + optional: boolean; + kind: TSMethodSignatureKind; + typeParameters: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType: TSTypeAnnotation | null; + accessibility: null; + readonly: false; + static: false; + parent?: Node; +} + +export interface TSConstructSignatureDeclaration extends Span { + type: "TSConstructSignatureDeclaration"; + typeParameters: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType: TSTypeAnnotation | null; + parent?: Node; +} + +export interface TSIndexSignatureName extends Span { + type: "Identifier"; + decorators: []; + name: string; + optional: false; + typeAnnotation: TSTypeAnnotation; + parent?: Node; +} + +export interface TSInterfaceHeritage extends Span { + type: "TSInterfaceHeritage"; + expression: Expression; + typeArguments: TSTypeParameterInstantiation | null; + parent?: Node; +} + +export interface TSTypePredicate extends Span { + type: "TSTypePredicate"; + parameterName: TSTypePredicateName; + asserts: boolean; + typeAnnotation: TSTypeAnnotation | null; + parent?: Node; +} + +export type TSTypePredicateName = IdentifierName | TSThisType; + +export interface TSModuleDeclaration extends Span { + type: "TSModuleDeclaration"; + id: BindingIdentifier | StringLiteral | TSQualifiedName; + body: TSModuleBlock | null; + kind: TSModuleDeclarationKind; + declare: boolean; + global: false; + parent?: Node; +} + +export type TSModuleDeclarationKind = "module" | "namespace"; + +export interface TSGlobalDeclaration extends Span { + type: "TSModuleDeclaration"; + id: IdentifierName; + body: TSModuleBlock; + kind: "global"; + declare: boolean; + global: true; + parent?: Node; +} + +export interface TSModuleBlock extends Span { + type: "TSModuleBlock"; + body: Array; + parent?: Node; +} + +export interface TSTypeLiteral extends Span { + type: "TSTypeLiteral"; + members: Array; + parent?: Node; +} + +export interface TSInferType extends Span { + type: "TSInferType"; + typeParameter: TSTypeParameter; + parent?: Node; +} + +export interface TSTypeQuery extends Span { + type: "TSTypeQuery"; + exprName: TSTypeQueryExprName; + typeArguments: TSTypeParameterInstantiation | null; + parent?: Node; +} + +export type TSTypeQueryExprName = TSImportType | TSTypeName; + +export interface TSImportType extends Span { + type: "TSImportType"; + source: StringLiteral; + options: ObjectExpression | null; + qualifier: TSImportTypeQualifier | null; + typeArguments: TSTypeParameterInstantiation | null; + parent?: Node; +} + +export type TSImportTypeQualifier = IdentifierName | TSImportTypeQualifiedName; + +export interface TSImportTypeQualifiedName extends Span { + type: "TSQualifiedName"; + left: TSImportTypeQualifier; + right: IdentifierName; + parent?: Node; +} + +export interface TSFunctionType extends Span { + type: "TSFunctionType"; + typeParameters: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType: TSTypeAnnotation; + parent?: Node; +} + +export interface TSConstructorType extends Span { + type: "TSConstructorType"; + abstract: boolean; + typeParameters: TSTypeParameterDeclaration | null; + params: ParamPattern[]; + returnType: TSTypeAnnotation; + parent?: Node; +} + +export interface TSMappedType extends Span { + type: "TSMappedType"; + key: BindingIdentifier; + constraint: TSType; + nameType: TSType | null; + typeAnnotation: TSType | null; + optional: TSMappedTypeModifierOperator | false; + readonly: TSMappedTypeModifierOperator | null; + parent?: Node; +} + +export type TSMappedTypeModifierOperator = true | "+" | "-"; + +export interface TSTemplateLiteralType extends Span { + type: "TSTemplateLiteralType"; + quasis: Array; + types: Array; + parent?: Node; +} + +export interface TSAsExpression extends Span { + type: "TSAsExpression"; + expression: Expression; + typeAnnotation: TSType; + parent?: Node; +} + +export interface TSSatisfiesExpression extends Span { + type: "TSSatisfiesExpression"; + expression: Expression; + typeAnnotation: TSType; + parent?: Node; +} + +export interface TSTypeAssertion extends Span { + type: "TSTypeAssertion"; + typeAnnotation: TSType; + expression: Expression; + parent?: Node; +} + +export interface TSImportEqualsDeclaration extends Span { + type: "TSImportEqualsDeclaration"; + id: BindingIdentifier; + moduleReference: TSModuleReference; + importKind: ImportOrExportKind; + parent?: Node; +} + +export type TSModuleReference = TSExternalModuleReference | IdentifierReference | TSQualifiedName; + +export interface TSExternalModuleReference extends Span { + type: "TSExternalModuleReference"; + expression: StringLiteral; + parent?: Node; +} + +export interface TSNonNullExpression extends Span { + type: "TSNonNullExpression"; + expression: Expression; + parent?: Node; +} + +export interface Decorator extends Span { + type: "Decorator"; + expression: Expression; + parent?: Node; +} + +export interface TSExportAssignment extends Span { + type: "TSExportAssignment"; + expression: Expression; + parent?: Node; +} + +export interface TSNamespaceExportDeclaration extends Span { + type: "TSNamespaceExportDeclaration"; + id: IdentifierName; + parent?: Node; +} + +export interface TSInstantiationExpression extends Span { + type: "TSInstantiationExpression"; + expression: Expression; + typeArguments: TSTypeParameterInstantiation; + parent?: Node; +} + +export type ImportOrExportKind = "value" | "type"; + +export interface JSDocNullableType extends Span { + type: "TSJSDocNullableType"; + typeAnnotation: TSType; + postfix: boolean; + parent?: Node; +} + +export interface JSDocNonNullableType extends Span { + type: "TSJSDocNonNullableType"; + typeAnnotation: TSType; + postfix: boolean; + parent?: Node; +} + +export interface JSDocUnknownType extends Span { + type: "TSJSDocUnknownType"; + parent?: Node; +} + +export type ModuleKind = "script" | "module" | "commonjs"; + +export interface Span { + start: number; + end: number; + range?: [number, number]; +} + +export type AssignmentOperator = + | "=" + | "+=" + | "-=" + | "*=" + | "/=" + | "%=" + | "**=" + | "<<=" + | ">>=" + | ">>>=" + | "|=" + | "^=" + | "&=" + | "||=" + | "&&=" + | "??="; + +export type BinaryOperator = + | "==" + | "!=" + | "===" + | "!==" + | "<" + | "<=" + | ">" + | ">=" + | "+" + | "-" + | "*" + | "/" + | "%" + | "**" + | "<<" + | ">>" + | ">>>" + | "|" + | "^" + | "&" + | "in" + | "instanceof"; + +export type LogicalOperator = "||" | "&&" | "??"; + +export type UnaryOperator = "+" | "-" | "!" | "~" | "typeof" | "void" | "delete"; + +export type UpdateOperator = "++" | "--"; + +export type Node = + | Program + | IdentifierName + | IdentifierReference + | BindingIdentifier + | LabelIdentifier + | ThisExpression + | ArrayExpression + | ObjectExpression + | ObjectProperty + | TemplateLiteral + | TaggedTemplateExpression + | TemplateElement + | ComputedMemberExpression + | StaticMemberExpression + | PrivateFieldExpression + | CallExpression + | NewExpression + | MetaProperty + | SpreadElement + | UpdateExpression + | UnaryExpression + | BinaryExpression + | PrivateInExpression + | LogicalExpression + | ConditionalExpression + | AssignmentExpression + | ArrayAssignmentTarget + | ObjectAssignmentTarget + | AssignmentTargetRest + | AssignmentTargetWithDefault + | AssignmentTargetPropertyIdentifier + | AssignmentTargetPropertyProperty + | SequenceExpression + | Super + | AwaitExpression + | ChainExpression + | ParenthesizedExpression + | Directive + | Hashbang + | BlockStatement + | VariableDeclaration + | VariableDeclarator + | EmptyStatement + | ExpressionStatement + | IfStatement + | DoWhileStatement + | WhileStatement + | ForStatement + | ForInStatement + | ForOfStatement + | ContinueStatement + | BreakStatement + | ReturnStatement + | WithStatement + | SwitchStatement + | SwitchCase + | LabeledStatement + | ThrowStatement + | TryStatement + | CatchClause + | DebuggerStatement + | AssignmentPattern + | ObjectPattern + | BindingProperty + | ArrayPattern + | BindingRestElement + | Function + | FunctionBody + | ArrowFunctionExpression + | YieldExpression + | Class + | ClassBody + | MethodDefinition + | PropertyDefinition + | PrivateIdentifier + | StaticBlock + | AccessorProperty + | ImportExpression + | ImportDeclaration + | ImportSpecifier + | ImportDefaultSpecifier + | ImportNamespaceSpecifier + | ImportAttribute + | ExportNamedDeclaration + | ExportDefaultDeclaration + | ExportAllDeclaration + | ExportSpecifier + | V8IntrinsicExpression + | BooleanLiteral + | NullLiteral + | NumericLiteral + | StringLiteral + | BigIntLiteral + | RegExpLiteral + | JSXElement + | JSXOpeningElement + | JSXClosingElement + | JSXFragment + | JSXOpeningFragment + | JSXClosingFragment + | JSXNamespacedName + | JSXMemberExpression + | JSXExpressionContainer + | JSXEmptyExpression + | JSXAttribute + | JSXSpreadAttribute + | JSXIdentifier + | JSXSpreadChild + | JSXText + | TSThisParameter + | TSEnumDeclaration + | TSEnumBody + | TSEnumMember + | TSTypeAnnotation + | TSLiteralType + | TSConditionalType + | TSUnionType + | TSIntersectionType + | TSParenthesizedType + | TSTypeOperator + | TSArrayType + | TSIndexedAccessType + | TSTupleType + | TSNamedTupleMember + | TSOptionalType + | TSRestType + | TSAnyKeyword + | TSStringKeyword + | TSBooleanKeyword + | TSNumberKeyword + | TSNeverKeyword + | TSIntrinsicKeyword + | TSUnknownKeyword + | TSNullKeyword + | TSUndefinedKeyword + | TSVoidKeyword + | TSSymbolKeyword + | TSThisType + | TSObjectKeyword + | TSBigIntKeyword + | TSTypeReference + | TSQualifiedName + | TSTypeParameterInstantiation + | TSTypeParameter + | TSTypeParameterDeclaration + | TSTypeAliasDeclaration + | TSClassImplements + | TSInterfaceDeclaration + | TSInterfaceBody + | TSPropertySignature + | TSIndexSignature + | TSCallSignatureDeclaration + | TSMethodSignature + | TSConstructSignatureDeclaration + | TSIndexSignatureName + | TSInterfaceHeritage + | TSTypePredicate + | TSModuleDeclaration + | TSGlobalDeclaration + | TSModuleBlock + | TSTypeLiteral + | TSInferType + | TSTypeQuery + | TSImportType + | TSImportTypeQualifiedName + | TSFunctionType + | TSConstructorType + | TSMappedType + | TSTemplateLiteralType + | TSAsExpression + | TSSatisfiesExpression + | TSTypeAssertion + | TSImportEqualsDeclaration + | TSExternalModuleReference + | TSNonNullExpression + | Decorator + | TSExportAssignment + | TSNamespaceExportDeclaration + | TSInstantiationExpression + | JSDocNullableType + | JSDocNonNullableType + | JSDocUnknownType + | ParamPattern; diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/README.md b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/README.md new file mode 100644 index 0000000..ce38f8e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/README.md @@ -0,0 +1,3 @@ +# `@rolldown/binding-win32-x64-msvc` + +This is the **x86_64-pc-windows-msvc** binary for `@rolldown/binding` diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/package.json b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/package.json new file mode 100644 index 0000000..a28cc93 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/package.json @@ -0,0 +1,37 @@ +{ + "name": "@rolldown/binding-win32-x64-msvc", + "version": "1.0.1", + "cpu": [ + "x64" + ], + "main": "rolldown-binding.win32-x64-msvc.node", + "files": [ + "rolldown-binding.win32-x64-msvc.node" + ], + "description": "Fast JavaScript/TypeScript bundler in Rust with Rollup-compatible API.", + "keywords": [ + "bundler", + "esbuild", + "parcel", + "rolldown", + "rollup", + "webpack" + ], + "homepage": "https://rolldown.rs/", + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rolldown/rolldown.git", + "directory": "packages/rolldown" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "os": [ + "win32" + ] +} \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/rolldown-binding.win32-x64-msvc.node b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/rolldown-binding.win32-x64-msvc.node new file mode 100644 index 0000000..55408f5 Binary files /dev/null and b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/binding-win32-x64-msvc/rolldown-binding.win32-x64-msvc.node differ diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/LICENSE b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/LICENSE new file mode 100644 index 0000000..708388c --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026-present, rolldown/plugins repository contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/README.md b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/README.md new file mode 100644 index 0000000..7d4d5a5 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/README.md @@ -0,0 +1,145 @@ +# @rolldown/pluginutils [![npm](https://img.shields.io/npm/v/@rolldown/pluginutils.svg)](https://npmx.dev/package/@rolldown/pluginutils) + +Plugin utilities for [Rolldown](https://rolldown.rs). + +Includes regex helpers for plugin hook filters, composable filter expressions, and a helper for filtering out Vite-serve-only plugins. + +## Install + +```bash +pnpm add -D @rolldown/pluginutils +``` + +## Usage + +```ts +import { exactRegex, prefixRegex, makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils' +``` + +All filter helpers are also exposed via the `/filter` subpath: + +```ts +import { and, or, id, include } from '@rolldown/pluginutils/filter' +``` + +## Regex helpers + +### `exactRegex` + +- **Type:** `(str: string, flags?: string) => RegExp` + +Constructs a `RegExp` that matches the exact string specified. Useful as a plugin hook filter. + +```ts +import { exactRegex } from '@rolldown/pluginutils' + +const plugin = { + name: 'plugin', + resolveId: { + filter: { id: exactRegex('foo') }, + handler(id) {}, // only called for `foo` + }, +} +``` + +### `prefixRegex` + +- **Type:** `(str: string, flags?: string) => RegExp` + +Constructs a `RegExp` that matches values starting with the specified prefix. + +```ts +import { prefixRegex } from '@rolldown/pluginutils' + +const plugin = { + name: 'plugin', + resolveId: { + filter: { id: prefixRegex('foo') }, + handler(id) {}, // called for IDs starting with `foo` + }, +} +``` + +### `makeIdFiltersToMatchWithQuery` + +- **Type:** `(input: string | RegExp | (string | RegExp)[]) => string | RegExp | (string | RegExp)[]` + +Converts an id filter so that it also matches ids that include a query string. + +```ts +import { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils' + +const plugin = { + name: 'plugin', + transform: { + filter: { id: makeIdFiltersToMatchWithQuery(['**/*.js', /\.ts$/]) }, + // Matches: + // foo.js, foo.js?foo, foo.txt?foo.js, + // foo.ts, foo.ts?foo, foo.txt?foo.ts + handler(code, id) {}, + }, +} +``` + +## Composable filters + +[Composable filter expressions](https://rolldown.rs/apis/plugin-api/hook-filters#composable-filters) for use cases where a simple `id`/`include`/`exclude` is not enough. For example, when a plugin needs to combine `id`, `moduleType`, `code`, and `query` conditions. + +```ts +import { and, code, id, include, interpreter, moduleType, or } from '@rolldown/pluginutils' + +const expr = include(and(or(id(/\.tsx?$/), id(/\.jsx?$/)), moduleType('tsx'), code(/import React/))) + +interpreter(expr, sourceCode, sourceId, 'tsx') // boolean +``` + +### Builders + +| Builder | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `and(...exprs)` | All operands must match. | +| `or(...exprs)` | At least one operand must match. | +| `not(expr)` | Negates the operand. | +| `id(pattern, params?)` | Match the module id. `pattern` is `string` or `RegExp`. `params.cleanUrl` strips the query/hash before matching. | +| `importerId(pattern, params?)` | Match the importer's id. Same shape as `id`. | +| `moduleType(type)` | Match Rolldown's module type (`'js'`, `'jsx'`, `'ts'`, `'tsx'`, `'json'`, `'text'`, `'base64'`, `'dataurl'`, `'binary'`, `'empty'`, or a custom string). | +| `code(pattern)` | Match the module source. `string` matches with `includes`; `RegExp` with `test`. | +| `query(key, pattern)` | Match a single query parameter. `pattern` is `boolean` (key presence/truthiness), `string` (exact value), or `RegExp` (value pattern). | +| `queries(obj)` | Shorthand for `and(...)` over multiple `query` entries. | +| `include(expr)` | Top-level wrapper marking `expr` as an inclusion rule. | +| `exclude(expr)` | Top-level wrapper marking `expr` as an exclusion rule. | + +### `interpreter` + +- **Type:** `(exprs, code?, id?, moduleType?, importerId?) => boolean` + +Evaluates one or more top-level expressions against the given inputs. Returns `true` when at least one `include` matches and no `exclude` matches; when no `include` is present, defaults to `true` unless an `exclude` matches. + +The argument required by each expression must be provided. For example, evaluating an `id(...)` expression without passing `id` will throw. + +## `filterVitePlugins` + +- **Type:** `(plugins: T | T[] | null | undefined | false) => T[]` + +Removes Vite plugins that target the dev server (`apply: 'serve'`) from a (possibly nested) plugin array. Plugins whose `apply` is a function are invoked with a `command: 'build'` context to decide. Useful when reusing a Vite plugin array inside a Rolldown config. + +```ts +import { defineConfig } from 'rolldown' +import { filterVitePlugins } from '@rolldown/pluginutils' +import viteReact from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: filterVitePlugins([ + viteReact(), + { + name: 'dev-only', + apply: 'serve', // filtered out + // ... + }, + ]), +}) +``` + +## License + +MIT diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter-B_mD-HGz.mjs b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter-B_mD-HGz.mjs new file mode 100644 index 0000000..e3bba27 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter-B_mD-HGz.mjs @@ -0,0 +1,323 @@ +//#region src/utils.ts +const postfixRE = /[?#].*$/; +function cleanUrl(url) { + return url.replace(postfixRE, ""); +} +function extractQueryWithoutFragment(url) { + const questionMarkIndex = url.indexOf("?"); + if (questionMarkIndex === -1) return ""; + const fragmentIndex = url.indexOf("#", questionMarkIndex); + if (fragmentIndex === -1) return url.substring(questionMarkIndex); + else return url.substring(questionMarkIndex, fragmentIndex); +} +//#endregion +//#region src/filter/composable-filters.ts +var And = class { + kind; + args; + constructor(...args) { + if (args.length === 0) throw new Error("`And` expects at least one operand"); + this.args = args; + this.kind = "and"; + } +}; +var Or = class { + kind; + args; + constructor(...args) { + if (args.length === 0) throw new Error("`Or` expects at least one operand"); + this.args = args; + this.kind = "or"; + } +}; +var Not = class { + kind; + expr; + constructor(expr) { + this.expr = expr; + this.kind = "not"; + } +}; +var Id = class { + kind; + pattern; + params; + constructor(pattern, params) { + this.pattern = pattern; + this.kind = "id"; + this.params = params ?? { cleanUrl: false }; + } +}; +var ImporterId = class { + kind; + pattern; + params; + constructor(pattern, params) { + this.pattern = pattern; + this.kind = "importerId"; + this.params = params ?? { cleanUrl: false }; + } +}; +var ModuleType = class { + kind; + pattern; + constructor(pattern) { + this.pattern = pattern; + this.kind = "moduleType"; + } +}; +var Code = class { + kind; + pattern; + constructor(expr) { + this.pattern = expr; + this.kind = "code"; + } +}; +var Query = class { + kind; + key; + pattern; + constructor(key, pattern) { + this.pattern = pattern; + this.key = key; + this.kind = "query"; + } +}; +var Include = class { + kind; + expr; + constructor(expr) { + this.expr = expr; + this.kind = "include"; + } +}; +var Exclude = class { + kind; + expr; + constructor(expr) { + this.expr = expr; + this.kind = "exclude"; + } +}; +function and(...args) { + return new And(...args); +} +function or(...args) { + return new Or(...args); +} +function not(expr) { + return new Not(expr); +} +function id(pattern, params) { + return new Id(pattern, params); +} +function importerId(pattern, params) { + return new ImporterId(pattern, params); +} +function moduleType(pattern) { + return new ModuleType(pattern); +} +function code(pattern) { + return new Code(pattern); +} +function query(key, pattern) { + return new Query(key, pattern); +} +function include(expr) { + return new Include(expr); +} +function exclude(expr) { + return new Exclude(expr); +} +/** +* convert a queryObject to FilterExpression like +* ```js +* and(query(k1, v1), query(k2, v2)) +* ``` +* @param queryFilterObject The query filter object needs to be matched. +* @returns a `And` FilterExpression +*/ +function queries(queryFilter) { + return and(...Object.entries(queryFilter).map(([key, value]) => { + return new Query(key, value); + })); +} +function interpreter(exprs, code, id, moduleType, importerId) { + let arr = []; + if (Array.isArray(exprs)) arr = exprs; + else arr = [exprs]; + return interpreterImpl(arr, code, id, moduleType, importerId); +} +function interpreterImpl(expr, code, id, moduleType, importerId, ctx = {}) { + let hasInclude = false; + for (const e of expr) switch (e.kind) { + case "include": + hasInclude = true; + if (exprInterpreter(e.expr, code, id, moduleType, importerId, ctx)) return true; + break; + case "exclude": + if (exprInterpreter(e.expr, code, id, moduleType, importerId, ctx)) return false; + break; + } + return !hasInclude; +} +function exprInterpreter(expr, code, id, moduleType, importerId, ctx = {}) { + switch (expr.kind) { + case "and": return expr.args.every((e) => exprInterpreter(e, code, id, moduleType, importerId, ctx)); + case "or": return expr.args.some((e) => exprInterpreter(e, code, id, moduleType, importerId, ctx)); + case "not": return !exprInterpreter(expr.expr, code, id, moduleType, importerId, ctx); + case "id": { + if (id === void 0) throw new Error("`id` is required for `id` expression"); + let idToMatch = id; + if (expr.params.cleanUrl) idToMatch = cleanUrl(idToMatch); + return typeof expr.pattern === "string" ? idToMatch === expr.pattern : expr.pattern.test(idToMatch); + } + case "importerId": { + if (importerId === void 0) return false; + let importerIdToMatch = importerId; + if (expr.params.cleanUrl) importerIdToMatch = cleanUrl(importerIdToMatch); + return typeof expr.pattern === "string" ? importerIdToMatch === expr.pattern : expr.pattern.test(importerIdToMatch); + } + case "moduleType": + if (moduleType === void 0) throw new Error("`moduleType` is required for `moduleType` expression"); + return moduleType === expr.pattern; + case "code": + if (code === void 0) throw new Error("`code` is required for `code` expression"); + return typeof expr.pattern === "string" ? code.includes(expr.pattern) : expr.pattern.test(code); + case "query": { + if (id === void 0) throw new Error("`id` is required for `Query` expression"); + if (!ctx.urlSearchParamsCache) { + let queryString = extractQueryWithoutFragment(id); + ctx.urlSearchParamsCache = new URLSearchParams(queryString); + } + let urlParams = ctx.urlSearchParamsCache; + if (typeof expr.pattern === "boolean") if (expr.pattern) return urlParams.has(expr.key); + else return !urlParams.has(expr.key); + else if (typeof expr.pattern === "string") return urlParams.get(expr.key) === expr.pattern; + else return expr.pattern.test(urlParams.get(expr.key) ?? ""); + } + default: throw new Error(`Expression ${JSON.stringify(expr)} is not expected.`); + } +} +//#endregion +//#region src/filter/filter-vite-plugins.ts +/** +* Filters out Vite plugins that have `apply: 'serve'` set. +* +* Since Rolldown operates in build mode, plugins marked with `apply: 'serve'` +* are intended only for Vite's dev server and should be excluded from the build process. +* +* @param plugins - Array of plugins (can include nested arrays) +* @returns Filtered array with serve-only plugins removed +* +* @example +* ```ts +* import { defineConfig } from 'rolldown'; +* import { filterVitePlugins } from '@rolldown/pluginutils'; +* import viteReact from '@vitejs/plugin-react'; +* +* export default defineConfig({ +* plugins: filterVitePlugins([ +* viteReact(), +* { +* name: 'dev-only', +* apply: 'serve', // This will be filtered out +* // ... +* } +* ]) +* }); +* ``` +*/ +function filterVitePlugins(plugins) { + if (!plugins) return []; + const pluginArray = Array.isArray(plugins) ? plugins : [plugins]; + const result = []; + for (const plugin of pluginArray) { + if (!plugin) continue; + if (Array.isArray(plugin)) { + result.push(...filterVitePlugins(plugin)); + continue; + } + const pluginWithApply = plugin; + if ("apply" in pluginWithApply) { + const applyValue = pluginWithApply.apply; + if (typeof applyValue === "function") try { + if (applyValue({}, { + command: "build", + mode: "production" + })) result.push(plugin); + } catch { + result.push(plugin); + } + else if (applyValue === "serve") continue; + else result.push(plugin); + } else result.push(plugin); + } + return result; +} +//#endregion +//#region src/filter/simple-filters.ts +/** +* Constructs a RegExp that matches the exact string specified. +* +* This is useful for plugin hook filters. +* +* @param str the string to match. +* @param flags flags for the RegExp. +* +* @example +* ```ts +* import { exactRegex } from '@rolldown/pluginutils'; +* const plugin = { +* name: 'plugin', +* resolveId: { +* filter: { id: exactRegex('foo') }, +* handler(id) {} // will only be called for `foo` +* } +* } +* ``` +*/ +function exactRegex(str, flags) { + return new RegExp(`^${escapeRegex(str)}$`, flags); +} +/** +* Constructs a RegExp that matches a value that has the specified prefix. +* +* This is useful for plugin hook filters. +* +* @param str the string to match. +* @param flags flags for the RegExp. +* +* @example +* ```ts +* import { prefixRegex } from '@rolldown/pluginutils'; +* const plugin = { +* name: 'plugin', +* resolveId: { +* filter: { id: prefixRegex('foo') }, +* handler(id) {} // will only be called for IDs starting with `foo` +* } +* } +* ``` +*/ +function prefixRegex(str, flags) { + return new RegExp(`^${escapeRegex(str)}`, flags); +} +const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g; +function escapeRegex(str) { + return str.replace(escapeRegexRE, "\\$&"); +} +function makeIdFiltersToMatchWithQuery(input) { + if (!Array.isArray(input)) return makeIdFilterToMatchWithQuery(input); + return input.map((i) => makeIdFilterToMatchWithQuery(i)); +} +function makeIdFilterToMatchWithQuery(input) { + if (typeof input === "string") return `${input}{?*,}`; + return makeRegexIdFilterToMatchWithQuery(input); +} +function makeRegexIdFilterToMatchWithQuery(input) { + return new RegExp(input.source.replace(/(?(plugins: T | T[] | null | undefined | false): T[]; +//#endregion +//#region src/filter/simple-filters.d.ts +/** + * Constructs a RegExp that matches the exact string specified. + * + * This is useful for plugin hook filters. + * + * @param str the string to match. + * @param flags flags for the RegExp. + * + * @example + * ```ts + * import { exactRegex } from '@rolldown/pluginutils'; + * const plugin = { + * name: 'plugin', + * resolveId: { + * filter: { id: exactRegex('foo') }, + * handler(id) {} // will only be called for `foo` + * } + * } + * ``` + */ +declare function exactRegex(str: string, flags?: string): RegExp; +/** + * Constructs a RegExp that matches a value that has the specified prefix. + * + * This is useful for plugin hook filters. + * + * @param str the string to match. + * @param flags flags for the RegExp. + * + * @example + * ```ts + * import { prefixRegex } from '@rolldown/pluginutils'; + * const plugin = { + * name: 'plugin', + * resolveId: { + * filter: { id: prefixRegex('foo') }, + * handler(id) {} // will only be called for IDs starting with `foo` + * } + * } + * ``` + */ +declare function prefixRegex(str: string, flags?: string): RegExp; +type WidenString = T extends string ? string : T; +/** + * Converts a id filter to match with an id with a query. + * + * @param input the id filters to convert. + * + * @example + * ```ts + * import { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils'; + * const plugin = { + * name: 'plugin', + * transform: { + * filter: { id: makeIdFiltersToMatchWithQuery(['**' + '/*.js', /\.ts$/]) }, + * // The handler will be called for IDs like: + * // - foo.js + * // - foo.js?foo + * // - foo.txt?foo.js + * // - foo.ts + * // - foo.ts?foo + * // - foo.txt?foo.ts + * handler(code, id) {} + * } + * } + * ``` + */ +declare function makeIdFiltersToMatchWithQuery(input: T): WidenString; +declare function makeIdFiltersToMatchWithQuery(input: readonly T[]): WidenString[]; +declare function makeIdFiltersToMatchWithQuery(input: string | RegExp | readonly (string | RegExp)[]): string | RegExp | (string | RegExp)[]; +//#endregion +export { FilterExpression, FilterExpressionKind, QueryFilterObject, TopLevelFilterExpression, and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query }; \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter/index.mjs b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter/index.mjs new file mode 100644 index 0000000..c197199 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/filter/index.mjs @@ -0,0 +1,2 @@ +import { _ as queries, a as and, c as exprInterpreter, d as include, f as interpreter, g as or, h as not, i as filterVitePlugins, l as id, m as moduleType, n as makeIdFiltersToMatchWithQuery, o as code, p as interpreterImpl, r as prefixRegex, s as exclude, t as exactRegex, u as importerId, v as query } from "../filter-B_mD-HGz.mjs"; +export { and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query }; diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.d.mts b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.d.mts new file mode 100644 index 0000000..91d7daa --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.d.mts @@ -0,0 +1,2 @@ +import { FilterExpression, FilterExpressionKind, QueryFilterObject, TopLevelFilterExpression, and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query } from "./filter/index.mjs"; +export { FilterExpression, FilterExpressionKind, QueryFilterObject, TopLevelFilterExpression, and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query }; \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.mjs b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.mjs new file mode 100644 index 0000000..2b584aa --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/dist/index.mjs @@ -0,0 +1,2 @@ +import { _ as queries, a as and, c as exprInterpreter, d as include, f as interpreter, g as or, h as not, i as filterVitePlugins, l as id, m as moduleType, n as makeIdFiltersToMatchWithQuery, o as code, p as interpreterImpl, r as prefixRegex, s as exclude, t as exactRegex, u as importerId, v as query } from "./filter-B_mD-HGz.mjs"; +export { and, code, exactRegex, exclude, exprInterpreter, filterVitePlugins, id, importerId, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query }; diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/package.json b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/package.json new file mode 100644 index 0000000..0ab8733 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/@rolldown/pluginutils/package.json @@ -0,0 +1,40 @@ +{ + "name": "@rolldown/pluginutils", + "version": "1.0.1", + "description": "Plugin utilities for Rolldown", + "keywords": [ + "filter", + "plugin", + "rolldown" + ], + "homepage": "https://github.com/rolldown/plugins/tree/main/packages/pluginutils#readme", + "bugs": { + "url": "https://github.com/rolldown/plugins/issues" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/rolldown/plugins.git", + "directory": "packages/pluginutils" + }, + "files": [ + "dist" + ], + "type": "module", + "exports": { + ".": "./dist/index.mjs", + "./filter": "./dist/filter/index.mjs", + "./package.json": "./package.json" + }, + "devDependencies": { + "@types/picomatch": "^4.0.3", + "picomatch": "^4.0.4", + "typescript": "^5.9.3" + }, + "scripts": { + "dev": "tsdown --watch", + "build": "tsdown", + "test": "vitest --project pluginutils", + "test:types": "vitest --project pluginutils --typecheck.only" + } +} \ No newline at end of file diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/LICENSE b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/LICENSE new file mode 100644 index 0000000..e751674 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/LICENSE @@ -0,0 +1,577 @@ +# create-vite license +create-vite is released under the MIT license: + +MIT License + +Copyright (c) 2019-present, VoidZero Inc. and Vite contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +# License of the files in the directories starting with "template-" in create-vite +The files in the directories starting with "template-" in create-vite and files +generated from those files are licensed under the CC0 1.0 Universal license: + +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + + +# Licenses of bundled dependencies +The published create-vite artifact additionally contains code with the following licenses: +Apache-2.0, ISC, MIT + +# Bundled dependencies: +## @clack/core, @clack/prompts +License: MIT +By: Nate Moore +Repositories: https://github.com/bombshell-dev/clack, https://github.com/bombshell-dev/clack + +> MIT License +> +> Copyright (c) Nate Moore +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## @vercel/detect-agent +License: Apache-2.0 +By: Vercel +Repository: https://github.com/vercel/vercel + +> Apache License +> Version 2.0, January 2004 +> http://www.apache.org/licenses/ +> +> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +> +> 1. Definitions. +> +> "License" shall mean the terms and conditions for use, reproduction, +> and distribution as defined by Sections 1 through 9 of this document. +> +> "Licensor" shall mean the copyright owner or entity authorized by +> the copyright owner that is granting the License. +> +> "Legal Entity" shall mean the union of the acting entity and all +> other entities that control, are controlled by, or are under common +> control with that entity. For the purposes of this definition, +> "control" means (i) the power, direct or indirect, to cause the +> direction or management of such entity, whether by contract or +> otherwise, or (ii) ownership of fifty percent (50%) or more of the +> outstanding shares, or (iii) beneficial ownership of such entity. +> +> "You" (or "Your") shall mean an individual or Legal Entity +> exercising permissions granted by this License. +> +> "Source" form shall mean the preferred form for making modifications, +> including but not limited to software source code, documentation +> source, and configuration files. +> +> "Object" form shall mean any form resulting from mechanical +> transformation or translation of a Source form, including but +> not limited to compiled object code, generated documentation, +> and conversions to other media types. +> +> "Work" shall mean the work of authorship, whether in Source or +> Object form, made available under the License, as indicated by a +> copyright notice that is included in or attached to the work +> (an example is provided in the Appendix below). +> +> "Derivative Works" shall mean any work, whether in Source or Object +> form, that is based on (or derived from) the Work and for which the +> editorial revisions, annotations, elaborations, or other modifications +> represent, as a whole, an original work of authorship. For the purposes +> of this License, Derivative Works shall not include works that remain +> separable from, or merely link (or bind by name) to the interfaces of, +> the Work and Derivative Works thereof. +> +> "Contribution" shall mean any work of authorship, including +> the original version of the Work and any modifications or additions +> to that Work or Derivative Works thereof, that is intentionally +> submitted to Licensor for inclusion in the Work by the copyright owner +> or by an individual or Legal Entity authorized to submit on behalf of +> the copyright owner. For the purposes of this definition, "submitted" +> means any form of electronic, verbal, or written communication sent +> to the Licensor or its representatives, including but not limited to +> communication on electronic mailing lists, source code control systems, +> and issue tracking systems that are managed by, or on behalf of, the +> Licensor for the purpose of discussing and improving the Work, but +> excluding communication that is conspicuously marked or otherwise +> designated in writing by the copyright owner as "Not a Contribution." +> +> "Contributor" shall mean Licensor and any individual or Legal Entity +> on behalf of whom a Contribution has been received by Licensor and +> subsequently incorporated within the Work. +> +> 2. Grant of Copyright License. Subject to the terms and conditions of +> this License, each Contributor hereby grants to You a perpetual, +> worldwide, non-exclusive, no-charge, royalty-free, irrevocable +> copyright license to reproduce, prepare Derivative Works of, +> publicly display, publicly perform, sublicense, and distribute the +> Work and such Derivative Works in Source or Object form. +> +> 3. Grant of Patent License. Subject to the terms and conditions of +> this License, each Contributor hereby grants to You a perpetual, +> worldwide, non-exclusive, no-charge, royalty-free, irrevocable +> (except as stated in this section) patent license to make, have made, +> use, offer to sell, sell, import, and otherwise transfer the Work, +> where such license applies only to those patent claims licensable +> by such Contributor that are necessarily infringed by their +> Contribution(s) alone or by combination of their Contribution(s) +> with the Work to which such Contribution(s) was submitted. If You +> institute patent litigation against any entity (including a +> cross-claim or counterclaim in a lawsuit) alleging that the Work +> or a Contribution incorporated within the Work constitutes direct +> or contributory patent infringement, then any patent licenses +> granted to You under this License for that Work shall terminate +> as of the date such litigation is filed. +> +> 4. Redistribution. You may reproduce and distribute copies of the +> Work or Derivative Works thereof in any medium, with or without +> modifications, and in Source or Object form, provided that You +> meet the following conditions: +> +> (a) You must give any other recipients of the Work or +> Derivative Works a copy of this License; and +> +> (b) You must cause any modified files to carry prominent notices +> stating that You changed the files; and +> +> (c) You must retain, in the Source form of any Derivative Works +> that You distribute, all copyright, patent, trademark, and +> attribution notices from the Source form of the Work, +> excluding those notices that do not pertain to any part of +> the Derivative Works; and +> +> (d) If the Work includes a "NOTICE" text file as part of its +> distribution, then any Derivative Works that You distribute must +> include a readable copy of the attribution notices contained +> within such NOTICE file, excluding those notices that do not +> pertain to any part of the Derivative Works, in at least one +> of the following places: within a NOTICE text file distributed +> as part of the Derivative Works; within the Source form or +> documentation, if provided along with the Derivative Works; or, +> within a display generated by the Derivative Works, if and +> wherever such third-party notices normally appear. The contents +> of the NOTICE file are for informational purposes only and +> do not modify the License. You may add Your own attribution +> notices within Derivative Works that You distribute, alongside +> or as an addendum to the NOTICE text from the Work, provided +> that such additional attribution notices cannot be construed +> as modifying the License. +> +> You may add Your own copyright statement to Your modifications and +> may provide additional or different license terms and conditions +> for use, reproduction, or distribution of Your modifications, or +> for any such Derivative Works as a whole, provided Your use, +> reproduction, and distribution of the Work otherwise complies with +> the conditions stated in this License. +> +> 5. Submission of Contributions. Unless You explicitly state otherwise, +> any Contribution intentionally submitted for inclusion in the Work +> by You to the Licensor shall be under the terms and conditions of +> this License, without any additional terms or conditions. +> Notwithstanding the above, nothing herein shall supersede or modify +> the terms of any separate license agreement you may have executed +> with Licensor regarding such Contributions. +> +> 6. Trademarks. This License does not grant permission to use the trade +> names, trademarks, service marks, or product names of the Licensor, +> except as required for reasonable and customary use in describing the +> origin of the Work and reproducing the content of the NOTICE file. +> +> 7. Disclaimer of Warranty. Unless required by applicable law or +> agreed to in writing, Licensor provides the Work (and each +> Contributor provides its Contributions) on an "AS IS" BASIS, +> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +> implied, including, without limitation, any warranties or conditions +> of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +> PARTICULAR PURPOSE. You are solely responsible for determining the +> appropriateness of using or redistributing the Work and assume any +> risks associated with Your exercise of permissions under this License. +> +> 8. Limitation of Liability. In no event and under no legal theory, +> whether in tort (including negligence), contract, or otherwise, +> unless required by applicable law (such as deliberate and grossly +> negligent acts) or agreed to in writing, shall any Contributor be +> liable to You for damages, including any direct, indirect, special, +> incidental, or consequential damages of any character arising as a +> result of this License or out of the use or inability to use the +> Work (including but not limited to damages for loss of goodwill, +> work stoppage, computer failure or malfunction, or any and all +> other commercial damages or losses), even if such Contributor +> has been advised of the possibility of such damages. +> +> 9. Accepting Warranty or Additional Liability. While redistributing +> the Work or Derivative Works thereof, You may choose to offer, +> and charge a fee for, acceptance of support, warranty, indemnity, +> or other liability obligations and/or rights consistent with this +> License. However, in accepting such obligations, You may act only +> on Your own behalf and on Your sole responsibility, not on behalf +> of any other Contributor, and only if You agree to indemnify, +> defend, and hold each Contributor harmless for any liability +> incurred by, or claims asserted against, such Contributor by reason +> of your accepting any such warranty or additional liability. +> +> END OF TERMS AND CONDITIONS +> +> APPENDIX: How to apply the Apache License to your work. +> +> To apply the Apache License to your work, attach the following +> boilerplate notice, with the fields enclosed by brackets "[]" +> replaced with your own identifying information. (Don't include +> the brackets!) The text should be enclosed in the appropriate +> comment syntax for the file format. We also recommend that a +> file or class name and description of purpose be included on the +> same "printed page" as the copyright notice for easier +> identification within third-party archives. +> +> Copyright 2017 Vercel, Inc. +> +> Licensed under the Apache License, Version 2.0 (the "License"); +> you may not use this file except in compliance with the License. +> You may obtain a copy of the License at +> +> http://www.apache.org/licenses/LICENSE-2.0 +> +> Unless required by applicable law or agreed to in writing, software +> distributed under the License is distributed on an "AS IS" BASIS, +> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +> See the License for the specific language governing permissions and +> limitations under the License. + +--------------------------------------- + +## cross-spawn +License: MIT +By: Andrรฉ Cruz +Repository: https://github.com/moxystudio/node-cross-spawn + +> The MIT License (MIT) +> +> Copyright (c) 2018 Made With MOXY Lda +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## fast-string-truncated-width, fast-string-width +License: MIT +Repositories: https://github.com/fabiospampinato/fast-string-truncated-width, https://github.com/fabiospampinato/fast-string-width + +> The MIT License (MIT) +> +> Copyright (c) 2024-present Fabio Spampinato +> +> Permission is hereby granted, free of charge, to any person obtaining a +> copy of this software and associated documentation files (the "Software"), +> to deal in the Software without restriction, including without limitation +> the rights to use, copy, modify, merge, publish, distribute, sublicense, +> and/or sell copies of the Software, and to permit persons to whom the +> Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +> DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## fast-wrap-ansi +License: MIT +By: James Garbutt +Repository: https://github.com/43081j/fast-wrap-ansi + +> MIT License +> +> Copyright (c) 2025 James Garbutt +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + +--------------------------------------- + +## isexe, which +License: ISC +By: Isaac Z. Schlueter +Repositories: https://github.com/isaacs/isexe, https://github.com/isaacs/node-which + +> The ISC License +> +> Copyright (c) Isaac Z. Schlueter and Contributors +> +> Permission to use, copy, modify, and/or distribute this software for any +> purpose with or without fee is hereby granted, provided that the above +> copyright notice and this permission notice appear in all copies. +> +> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--------------------------------------- + +## mri +License: MIT +By: Luke Edwards +Repository: https://github.com/lukeed/mri + +> The MIT License (MIT) +> +> Copyright (c) Luke Edwards (lukeed.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## path-key, shebang-regex +License: MIT +By: Sindre Sorhus +Repositories: https://github.com/sindresorhus/path-key, https://github.com/sindresorhus/shebang-regex + +> MIT License +> +> Copyright (c) Sindre Sorhus (sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## shebang-command +License: MIT +By: Kevin Mรฅrtensson +Repository: https://github.com/kevva/shebang-command + +> MIT License +> +> Copyright (c) Kevin Mรฅrtensson (github.com/kevva) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## sisteransi +License: MIT +By: Terkel Gjervig +Repository: https://github.com/terkelg/sisteransi + +> MIT License +> +> Copyright (c) 2018 Terkel Gjervig Nielsen +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/README.md b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/README.md new file mode 100644 index 0000000..2efc921 --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/README.md @@ -0,0 +1,92 @@ +# create-vite npm package + +## Scaffolding Your First Vite Project + +> **Compatibility Note:** +> Vite requires [Node.js](https://nodejs.org/en/) version 20.19+, 22.12+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it. + +With NPM: + +```bash +npm create vite@latest +``` + +With Yarn: + +```bash +yarn create vite +``` + +With PNPM: + +```bash +pnpm create vite +``` + +With Bun: + +```bash +bun create vite +``` + +With Deno: + +```bash +deno init --npm vite +``` + +Then follow the prompts! + +You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run: + +```bash +# npm 7+, extra double-dash is needed: +npm create vite@latest my-vue-app -- --template vue + +# yarn +yarn create vite my-vue-app --template vue + +# pnpm +pnpm create vite my-vue-app --template vue + +# Bun +bun create vite my-vue-app --template vue + +# Deno +deno init --npm vite my-vue-app --template vue +``` + +Currently supported template presets include: + +- `vanilla` +- `vanilla-ts` +- `vue` +- `vue-ts` +- `react` +- `react-compiler` +- `react-ts` +- `react-compiler-ts` +- `preact` +- `preact-ts` +- `lit` +- `lit-ts` +- `svelte` +- `svelte-ts` +- `solid` +- `solid-ts` +- `qwik` +- `qwik-ts` + +You can use `.` for the project name to scaffold in the current directory. + +## Community Templates + +create-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for [community maintained templates](https://github.com/vitejs/awesome-vite#templates) that include other tools or target different frameworks. You can use a tool like [tiged](https://github.com/tiged/tiged) to scaffold your project with one of the templates. + +```bash +npx tiged user/project my-project +cd my-project + +npm install +npm run dev +``` diff --git a/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/dist/index.js b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/dist/index.js new file mode 100644 index 0000000..3d1c05e --- /dev/null +++ b/TicTacToe-Compare/ministral-3-14b/node_modules/create-vite/dist/index.js @@ -0,0 +1,89 @@ +import{createRequire as e}from"node:module";import t from"node:fs";import n from"node:path";import{fileURLToPath as r}from"node:url";import i,{stripVTControlCharacters as a,styleText as o}from"node:util";import s,{stdin as c,stdout as l}from"node:process";import"node:readline";import u from"node:readline";import"node:tty";var d=Object.create,f=Object.defineProperty,p=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,h=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,_=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),v=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=m(t),a=0,o=i.length,s;at[e]).bind(null,s),enumerable:!(r=p(t,s))||r.enumerable});return e},y=(e,t,n)=>(n=e==null?{}:d(h(e)),v(t||!e||!e.__esModule?f(n,`default`,{value:e,enumerable:!0}):n,e)),b=e(import.meta.url),x=_(((e,t)=>{t.exports=a,a.sync=o;var n=b(`fs`);function r(e,t){var n=t.pathExt===void 0?process.env.PATHEXT:t.pathExt;if(!n||(n=n.split(`;`),n.indexOf(``)!==-1))return!0;for(var r=0;r{t.exports=r,r.sync=i;var n=b(`fs`);function r(e,t,r){n.stat(e,function(e,n){r(e,e?!1:a(n,t))})}function i(e,t){return a(n.statSync(e),t)}function a(e,t){return e.isFile()&&o(e,t)}function o(e,t){var n=e.mode,r=e.uid,i=e.gid,a=t.uid===void 0?process.getuid&&process.getuid():t.uid,o=t.gid===void 0?process.getgid&&process.getgid():t.gid,s=64,c=8,l=1,u=s|c;return n&l||n&c&&i===o||n&s&&r===a||n&u&&a===0}})),C=_(((e,t)=>{b(`fs`);var n=process.platform===`win32`||global.TESTING_WINDOWS?x():S();t.exports=r,r.sync=i;function r(e,t,i){if(typeof t==`function`&&(i=t,t={}),!i){if(typeof Promise!=`function`)throw TypeError(`callback not provided`);return new Promise(function(n,i){r(e,t||{},function(e,t){e?i(e):n(t)})})}n(e,t||{},function(e,n){e&&(e.code===`EACCES`||t&&t.ignoreErrors)&&(e=null,n=!1),i(e,n)})}function i(e,t){try{return n.sync(e,t||{})}catch(e){if(t&&t.ignoreErrors||e.code===`EACCES`)return!1;throw e}}})),w=_(((e,t)=>{let n=process.platform===`win32`||process.env.OSTYPE===`cygwin`||process.env.OSTYPE===`msys`,r=b(`path`),i=n?`;`:`:`,a=C(),o=e=>Object.assign(Error(`not found: ${e}`),{code:`ENOENT`}),s=(e,t)=>{let r=t.colon||i,a=e.match(/\//)||n&&e.match(/\\/)?[``]:[...n?[process.cwd()]:[],...(t.path||process.env.PATH||``).split(r)],o=n?t.pathExt||process.env.PATHEXT||`.EXE;.CMD;.BAT;.COM`:``,s=n?o.split(r):[``];return n&&e.indexOf(`.`)!==-1&&s[0]!==``&&s.unshift(``),{pathEnv:a,pathExt:s,pathExtExe:o}},c=(e,t,n)=>{typeof t==`function`&&(n=t,t={}),t||={};let{pathEnv:i,pathExt:c,pathExtExe:l}=s(e,t),u=[],d=n=>new Promise((a,s)=>{if(n===i.length)return t.all&&u.length?a(u):s(o(e));let c=i[n],l=/^".*"$/.test(c)?c.slice(1,-1):c,d=r.join(l,e);a(f(!l&&/^\.[\\\/]/.test(e)?e.slice(0,2)+d:d,n,0))}),f=(e,n,r)=>new Promise((i,o)=>{if(r===c.length)return i(d(n+1));let s=c[r];a(e+s,{pathExt:l},(a,o)=>{if(!a&&o)if(t.all)u.push(e+s);else return i(e+s);return i(f(e,n,r+1))})});return n?d(0).then(e=>n(null,e),n):d(0)};t.exports=c,c.sync=(e,t)=>{t||={};let{pathEnv:n,pathExt:i,pathExtExe:c}=s(e,t),l=[];for(let o=0;o{let n=(e={})=>{let t=e.env||process.env;return(e.platform||process.platform)===`win32`?Object.keys(t).reverse().find(e=>e.toUpperCase()===`PATH`)||`Path`:`PATH`};t.exports=n,t.exports.default=n})),te=_(((e,t)=>{let n=b(`path`),r=w(),i=ee();function a(e,t){let a=e.options.env||process.env,o=process.cwd(),s=e.options.cwd!=null,c=s&&process.chdir!==void 0&&!process.chdir.disabled;if(c)try{process.chdir(e.options.cwd)}catch{}let l;try{l=r.sync(e.command,{path:a[i({env:a})],pathExt:t?n.delimiter:void 0})}catch{}finally{c&&process.chdir(o)}return l&&=n.resolve(s?e.options.cwd:``,l),l}function o(e){return a(e)||a(e,!0)}t.exports=o})),ne=_(((e,t)=>{let n=/([()\][%!^"`<>&|;, *?])/g;function r(e){return e=e.replace(n,`^$1`),e}function i(e,t){return e=`${e}`,e=e.replace(/(?=(\\+?)?)\1"/g,`$1$1\\"`),e=e.replace(/(?=(\\+?)?)\1$/,`$1$1`),e=`"${e}"`,e=e.replace(n,`^$1`),t&&(e=e.replace(n,`^$1`)),e}t.exports.command=r,t.exports.argument=i})),re=_(((e,t)=>{t.exports=/^#!(.*)/})),ie=_(((e,t)=>{let n=re();t.exports=(e=``)=>{let t=e.match(n);if(!t)return null;let[r,i]=t[0].replace(/#! ?/,``).split(` `),a=r.split(`/`).pop();return a===`env`?i:i?`${a} ${i}`:a}})),ae=_(((e,t)=>{let n=b(`fs`),r=ie();function i(e){let t=Buffer.alloc(150),i;try{i=n.openSync(e,`r`),n.readSync(i,t,0,150,0),n.closeSync(i)}catch{}return r(t.toString())}t.exports=i})),oe=_(((e,t)=>{let n=b(`path`),r=te(),i=ne(),a=ae(),o=process.platform===`win32`,s=/\.(?:com|exe)$/i,c=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function l(e){e.file=r(e);let t=e.file&&a(e.file);return t?(e.args.unshift(e.file),e.command=t,r(e)):e.file}function u(e){if(!o)return e;let t=l(e),r=!s.test(t);if(e.options.forceShell||r){let r=c.test(t);e.command=n.normalize(e.command),e.command=i.command(e.command),e.args=e.args.map(e=>i.argument(e,r)),e.args=[`/d`,`/s`,`/c`,`"${[e.command].concat(e.args).join(` `)}"`],e.command=process.env.comspec||`cmd.exe`,e.options.windowsVerbatimArguments=!0}return e}function d(e,t,n){t&&!Array.isArray(t)&&(n=t,t=null),t=t?t.slice(0):[],n=Object.assign({},n);let r={command:e,args:t,options:n,file:void 0,original:{command:e,args:t}};return n.shell?r:u(r)}t.exports=d})),se=_(((e,t)=>{let n=process.platform===`win32`;function r(e,t){return Object.assign(Error(`${t} ${e.command} ENOENT`),{code:`ENOENT`,errno:`ENOENT`,syscall:`${t} ${e.command}`,path:e.command,spawnargs:e.args})}function i(e,t){if(!n)return;let r=e.emit;e.emit=function(n,i){if(n===`exit`){let n=a(i,t);if(n)return r.call(e,`error`,n)}return r.apply(e,arguments)}}function a(e,t){return n&&e===1&&!t.file?r(t.original,`spawn`):null}function o(e,t){return n&&e===1&&!t.file?r(t.original,`spawnSync`):null}t.exports={hookChildProcess:i,verifyENOENT:a,verifyENOENTSync:o,notFoundError:r}})),ce=_(((e,t)=>{let n=b(`child_process`),r=oe(),i=se();function a(e,t,a){let o=r(e,t,a),s=n.spawn(o.command,o.args,o.options);return i.hookChildProcess(s,o),s}function o(e,t,a){let o=r(e,t,a),s=n.spawnSync(o.command,o.args,o.options);return s.error=s.error||i.verifyENOENTSync(s.status,o),s}t.exports=a,t.exports.spawn=a,t.exports.sync=o,t.exports._parse=r,t.exports._enoent=i})),le=_(((e,t)=>{function n(e){return e==null?[]:Array.isArray(e)?e:[e]}function r(e,t,n,r){var i,a=e[t],o=~r.string.indexOf(t)?n==null||n===!0?``:String(n):typeof n==`boolean`?n:~r.boolean.indexOf(t)?n===`false`?!1:n===`true`||(e._.push((i=+n,i*0==0?i:n)),!!n):(i=+n,i*0==0?i:n);e[t]=a==null?o:Array.isArray(a)?a.concat(o):[a,o]}t.exports=function(e,t){e||=[],t||={};var i,a,o,s,c,l={_:[]},u=0,d=0,f=0,p=e.length;let m=t.alias!==void 0,h=t.unknown!==void 0,g=t.default!==void 0;if(t.alias=t.alias||{},t.string=n(t.string),t.boolean=n(t.boolean),m)for(i in t.alias)for(a=t.alias[i]=n(t.alias[i]),u=0;u0;)for(a=t.alias[t.boolean[u]]||[],d=a.length;d-- >0;)t.boolean.push(a[d]);for(u=t.string.length;u-- >0;)for(a=t.alias[t.string[u]]||[],d=a.length;d-- >0;)t.string.push(a[d]);if(g){for(i in t.default)if(s=typeof t.default[i],a=t.alias[i]=t.alias[i]||[],t[s]!==void 0)for(t[s].push(i),u=0;u0;)l[a.shift()]=l[i];return l}})),ue=y(ce(),1),de=y(le(),1);const fe=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),pe=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,me=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,he=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,ge=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,_e=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,ve=/\t{1,1000}/y,ye=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,be=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,xe=/\p{M}+/gu,Se={limit:1/0,ellipsis:``},Ce=(e,t={},n={})=>{let r=t.limit??1/0,i=t.ellipsis??``,a=t?.ellipsisWidth??(i?Ce(i,Se,n).width:0),o=n.controlWidth??0,s=n.tabWidth??8,c=n.emojiWidth??2,l=n.regularWidth??1,u=n.wideWidth??2,d=[[be,l],[he,0],[ge,o],[ve,s],[ye,c],[_e,u]],f=0,p=0,m=e.length,h=0,g=!1,_=m,v=Math.max(0,r-a),y=0,b=0,x=0,S=0;outer:for(;;){if(b>y||p>=m&&p>f){let t=e.slice(y,b)||e.slice(f,p);h=0;for(let e of t.replaceAll(xe,``)){let t=e.codePointAt(0)||0;if(S=pe(t)?2:me(t)?u:l,x+S>v&&(_=Math.min(_,Math.max(y,f)+h)),x+S>r){g=!0;break outer}h+=e.length,x+=S}y=b=0}if(p>=m)break outer;for(let t=0,n=d.length;tv&&(_=Math.min(_,p+Math.floor((v-x)/i))),x+S>r){g=!0;break outer}x+=S,y=f,b=p,p=f=n.lastIndex;continue outer}}p+=1}return{width:g?v:x,index:g?_:m,truncated:g,ellipsed:g&&r>=a}},we={limit:1/0,ellipsis:``,ellipsisWidth:0},T=(e,t={})=>Ce(e,we,t).width,E=`]8;;`,Te=RegExp(`(?:\\[(?\\d+)m|\\${E}(?.*))`,`y`),Ee=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},De=e=>`[${e}m`,Oe=e=>`${E}${e}`,D=(e,t,n)=>{let r=t[Symbol.iterator](),i=!1,a=!1,o=e.at(-1),s=o===void 0?0:T(o),c=r.next(),l=r.next(),u=0;for(;!c.done;){let o=c.value,d=T(o);s+d<=n?e[e.length-1]+=o:(e.push(o),s=0),(o===`\x1B`||o===`ย›`)&&(i=!0,a=t.startsWith(E,u+1)),i?a?o===`\x07`&&(i=!1,a=!1):o===`m`&&(i=!1):(s+=d,s===n&&!l.done&&(e.push(``),s=0)),c=l,l=r.next(),u+=o.length}o=e.at(-1),!s&&o!==void 0&&o.length&&e.length>1&&(e[e.length-2]+=e.pop())},ke=e=>{let t=e.split(` `),n=t.length;for(;n&&!T(t[n-1]);)n--;return n===t.length?e:t.slice(0,n).join(` `)+t.slice(n).join(``)},Ae=(e,t,n={})=>{if(n.trim!==!1&&e.trim()===``)return``;let r=``,i,a,o=e.split(` `),s=[``],c=0;for(let e=0;e=t&&(n.wordWrap===!1||n.trim===!1)&&(s.push(``),c=0),(c||n.trim===!1)&&(s[s.length-1]+=` `,c++));let i=T(r);if(n.hard&&i>t){let e=t-c,n=1+Math.floor((i-e-1)/t);Math.floor((i-1)/t)t&&c&&i){if(n.wordWrap===!1&&ct&&n.wordWrap===!1){D(s,r,t),c=T(s.at(-1)??``);continue}s[s.length-1]+=r,c+=i}n.trim!==!1&&(s=s.map(e=>ke(e)));let l=s.join(` +`),u=!1;for(let e=0;e=`\ud800`&&t<=`\udbff`,u)continue;if(t===`\x1B`||t===`ย›`){Te.lastIndex=e+1;let t=Te.exec(l)?.groups;if(t?.code!==void 0){let e=Number.parseFloat(t.code);i=e===39?void 0:e}else t?.uri!==void 0&&(a=t.uri.length===0?void 0:t.uri)}if(l[e+1]===` +`){a&&(r+=Oe(``));let e=i?Ee(i):void 0;i&&e&&(r+=De(e))}else t===` +`&&(i&&Ee(i)&&(r+=De(i)),a&&(r+=Oe(a)))}return r},je=/\r?\n/;function O(e,t,n){return String(e).normalize().split(je).map(e=>Ae(e,t,n)).join(` +`)}var k=_(((e,t)=>{let n={to(e,t){return t?`[${t+1};${e+1}H`:`[${e+1}G`},move(e,t){let n=``;return e<0?n+=`[${-e}D`:e>0&&(n+=`[${e}C`),t<0?n+=`[${-t}A`:t>0&&(n+=`[${t}B`),n},up:(e=1)=>`[${e}A`,down:(e=1)=>`[${e}B`,forward:(e=1)=>`[${e}C`,backward:(e=1)=>`[${e}D`,nextLine:(e=1)=>`\x1B[E`.repeat(e),prevLine:(e=1)=>`\x1B[F`.repeat(e),left:`\x1B[G`,hide:`\x1B[?25l`,show:`\x1B[?25h`,save:`\x1B7`,restore:`\x1B8`};t.exports={cursor:n,scroll:{up:(e=1)=>`\x1B[S`.repeat(e),down:(e=1)=>`\x1B[T`.repeat(e)},erase:{screen:`\x1B[2J`,up:(e=1)=>`\x1B[1J`.repeat(e),down:(e=1)=>`\x1B[J`.repeat(e),line:`\x1B[2K`,lineEnd:`\x1B[K`,lineStart:`\x1B[1K`,lines(e){let t=``;for(let r=0;r!e.disabled))return e;let r=e+t,i=Math.max(n.length-1,0),a=r<0?i:r>i?0:r;return n[a].disabled?A(a,t<0?-1:1,n):a}const j={actions:new Set([`up`,`down`,`left`,`right`,`space`,`enter`,`cancel`]),aliases:new Map([[`k`,`up`],[`j`,`down`],[`h`,`left`],[`l`,`right`],[``,`cancel`],[`escape`,`cancel`]]),messages:{cancel:`Canceled`,error:`Something went wrong`},withGuide:!0,date:{monthNames:[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],messages:{required:`Please enter a valid date`,invalidMonth:`There are only 12 months in a year`,invalidDay:(e,t)=>`There are only ${e} days in ${t}`,afterMin:e=>`Date must be on or after ${e.toISOString().slice(0,10)}`,beforeMax:e=>`Date must be on or before ${e.toISOString().slice(0,10)}`}}};function Me(e,t){if(typeof e==`string`)return j.aliases.get(e)===t;for(let n of e)if(n!==void 0&&Me(n,t))return!0;return!1}function Ne(e,t){if(e===t)return;let n=e.split(` +`),r=t.split(` +`),i=Math.max(n.length,r.length),a=[];for(let e=0;e`columns`in e&&typeof e.columns==`number`?e.columns:80,Fe=e=>`rows`in e&&typeof e.rows==`number`?e.rows:20;function F(e,t,n,r=n,i){return O(t,Pe(e??l)-n.length,{hard:!0,trim:!1}).split(` +`).map((e,t)=>{let a=i?i(e,t):e;return`${t===0?r:n}${a}`}).join(` +`)}let I=class{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame=``;_subscribers=new Map;_cursor=0;state=`initial`;error=``;value;userInput=``;constructor(e,t=!0){let{input:n=c,output:r=l,render:i,signal:a,...o}=e;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=i.bind(this),this._track=t,this._abortSignal=a,this.input=n,this.output=r}unsubscribe(){this._subscribers.clear()}setSubscriber(e,t){let n=this._subscribers.get(e)??[];n.push(t),this._subscribers.set(e,n)}on(e,t){this.setSubscriber(e,{cb:t})}once(e,t){this.setSubscriber(e,{cb:t,once:!0})}emit(e,...t){let n=this._subscribers.get(e)??[],r=[];for(let e of n)e.cb(...t),e.once&&r.push(()=>n.splice(n.indexOf(e),1));for(let e of r)e()}prompt(){return new Promise(e=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state=`cancel`,this.close(),e(M);this._abortSignal.addEventListener(`abort`,()=>{this.state=`cancel`,this.close()},{once:!0})}this.rl=u.createInterface({input:this.input,tabSize:2,prompt:``,escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on(`keypress`,this.onKeypress),P(this.input,!0),this.output.on(`resize`,this.render),this.render(),this.once(`submit`,()=>{this.output.write(k.cursor.show),this.output.off(`resize`,this.render),P(this.input,!1),e(this.value)}),this.once(`cancel`,()=>{this.output.write(k.cursor.show),this.output.off(`resize`,this.render),P(this.input,!1),e(M)})})}_isActionKey(e,t){return e===` `}_shouldSubmit(e,t){return!0}_setValue(e){this.value=e,this.emit(`value`,this.value)}_setUserInput(e,t){this.userInput=e??``,this.emit(`userInput`,this.userInput),t&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:`u`}),this._setUserInput(``)}onKeypress(e,t){if(this._track&&t.name!==`return`&&(t.name&&this._isActionKey(e,t)&&this.rl?.write(null,{ctrl:!0,name:`h`}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state===`error`&&(this.state=`active`),t?.name&&(!this._track&&j.aliases.has(t.name)&&this.emit(`cursor`,j.aliases.get(t.name)),j.actions.has(t.name)&&this.emit(`cursor`,t.name)),e&&(e.toLowerCase()===`y`||e.toLowerCase()===`n`)&&this.emit(`confirm`,e.toLowerCase()===`y`),this.emit(`key`,e?.toLowerCase(),t),t?.name===`return`&&this._shouldSubmit(e,t)){if(this.opts.validate){let e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state=`error`,this.rl?.write(this.userInput))}this.state!==`error`&&(this.state=`submit`)}Me([e,t?.name,t?.sequence],`cancel`)&&(this.state=`cancel`),(this.state===`submit`||this.state===`cancel`)&&this.emit(`finalize`),this.render(),(this.state===`submit`||this.state===`cancel`)&&this.close()}close(){this.input.unpipe(),this.input.removeListener(`keypress`,this.onKeypress),this.output.write(` +`),P(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let e=O(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(` +`).length-1;this.output.write(k.cursor.move(-999,e*-1))}render(){let e=O(this._render(this)??``,process.stdout.columns,{hard:!0,trim:!1});if(e!==this._prevFrame){if(this.state===`initial`)this.output.write(k.cursor.hide);else{let t=Ne(this._prevFrame,e),n=Fe(this.output);if(this.restoreCursor(),t){let r=Math.max(0,t.numLinesAfter-n),i=Math.max(0,t.numLinesBefore-n),a=t.lines.find(e=>e>=r);if(a===void 0){this._prevFrame=e;return}if(t.lines.length===1){this.output.write(k.cursor.move(0,a-i)),this.output.write(k.erase.lines(1));let t=e.split(` +`);this.output.write(t[a]),this._prevFrame=e,this.output.write(k.cursor.move(0,t.length-a-1));return}else if(t.lines.length>1){if(r0&&this.output.write(k.cursor.move(0,e))}this.output.write(k.erase.down());let t=e.split(` +`).slice(a);this.output.write(t.join(` +`)),this._prevFrame=e;return}}this.output.write(k.erase.down())}this.output.write(e),this.state===`initial`&&(this.state=`active`),this._prevFrame=e}}};var Ie=class extends I{get cursor(){return+!this.value}get _value(){return this.cursor===0}constructor(e){super(e,!1),this.value=!!e.initialValue,this.on(`userInput`,()=>{this.value=this._value}),this.on(`confirm`,e=>{this.output.write(k.cursor.move(0,-1)),this.value=e,this.state=`submit`,this.close()}),this.on(`cursor`,()=>{this.value=!this.value})}},Le=class extends I{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){this.value=this._selectedValue.value}constructor(e){super(e,!1),this.options=e.options;let t=this.options.findIndex(({value:t})=>t===e.initialValue),n=t===-1?0:t;this.cursor=this.options[n].disabled?A(n,1,this.options):n,this.changeValue(),this.on(`cursor`,e=>{switch(e){case`left`:case`up`:this.cursor=A(this.cursor,-1,this.options);break;case`down`:case`right`:this.cursor=A(this.cursor,1,this.options);break}this.changeValue()})}},Re=class extends I{get userInputWithCursor(){if(this.state===`submit`)return this.userInput;let e=this.userInput;if(this.cursor>=e.length)return`${this.userInput}\u2588`;let t=e.slice(0,this.cursor),[n,...r]=e.slice(this.cursor);return`${t}${o(`inverse`,n)}${r.join(``)}`}get cursor(){return this._cursor}constructor(e){super({...e,initialUserInput:e.initialUserInput??e.initialValue}),this.on(`userInput`,e=>{this._setValue(e)}),this.on(`finalize`,()=>{this.value||=e.defaultValue,this.value===void 0&&(this.value=``)})}};function ze(){return s.platform===`win32`?!!s.env.CI||!!s.env.WT_SESSION||!!s.env.TERMINUS_SUBLIME||s.env.ConEmuTask===`{cmd::Cmder}`||s.env.TERM_PROGRAM===`Terminus-Sublime`||s.env.TERM_PROGRAM===`vscode`||s.env.TERM===`xterm-256color`||s.env.TERM===`alacritty`||s.env.TERMINAL_EMULATOR===`JetBrains-JediTerm`:s.env.TERM!==`linux`}const Be=ze(),L=(e,t)=>Be?e:t,Ve=L(`โ—†`,`*`),He=L(`โ– `,`x`),Ue=L(`โ–ฒ`,`x`),R=L(`โ—‡`,`o`),z=L(`โ”‚`,`|`),B=L(`โ””`,`โ€”`),We=L(`โ—`,`>`),V=L(`โ—‹`,` `),Ge=L(`โ—`,`โ€ข`),Ke=L(`โ—†`,`*`),qe=L(`โ–ฒ`,`!`),Je=L(`โ– `,`x`),Ye=e=>{switch(e){case`initial`:case`active`:return o(`cyan`,Ve);case`cancel`:return o(`red`,He);case`error`:return o(`yellow`,Ue);case`submit`:return o(`green`,R)}},Xe=e=>{switch(e){case`initial`:case`active`:return o(`cyan`,z);case`cancel`:return o(`red`,z);case`error`:return o(`yellow`,z);case`submit`:return o(`green`,z)}},Ze=(e,t,n,r,i)=>{let a=t,o=0;for(let t=n;t{let c=Pe(r)-a,l=Fe(r),u=o(`dim`,`...`),d=Math.max(l-s,0),f=Math.max(Math.min(i,d),5),p=0;e>=f-3&&(p=Math.max(Math.min(e-f+3,t.length-f),0));let m=f0,h=fd){let t=0,n=0,r=v,i=e-y,a=(e,t)=>Ze(_,r,e,t,d);m?({lineCount:r,removals:t}=a(0,i),r>d&&({lineCount:r,removals:n}=a(i+1,_.length))):({lineCount:r,removals:n}=a(i+1,_.length),r>d&&({lineCount:r,removals:t}=a(0,i))),t>0&&(m=!0,_.splice(0,t)),n>0&&(h=!0,_.splice(_.length-n,n))}let x=[];m&&x.push(u);for(let e of _)for(let t of e)x.push(t);return h&&x.push(u),x},$e=e=>{let t=e.active??`Yes`,n=e.inactive??`No`;return new Ie({active:t,inactive:n,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue??!0,render(){let r=e.withGuide??j.withGuide,i=`${Ye(this.state)} `,a=r?`${o(`gray`,z)} `:``,s=F(e.output,e.message,a,i),c=`${r?`${o(`gray`,z)} +`:``}${s} +`,l=this.value?t:n;switch(this.state){case`submit`:return`${c}${r?`${o(`gray`,z)} `:``}${o(`dim`,l)}`;case`cancel`:return`${c}${r?`${o(`gray`,z)} `:``}${o([`strikethrough`,`dim`],l)}${r?` +${o(`gray`,z)}`:``}`;default:{let i=r?`${o(`cyan`,z)} `:``,a=r?o(`cyan`,B):``;return`${c}${i}${this.value?`${o(`green`,We)} ${t}`:`${o(`dim`,V)} ${o(`dim`,t)}`}${e.vertical?r?` +${o(`cyan`,z)} `:` +`:` ${o(`dim`,`/`)} `}${this.value?`${o(`dim`,V)} ${o(`dim`,n)}`:`${o(`green`,We)} ${n}`} +${a} +`}}}}).prompt()},H={message:(e=[],{symbol:t=o(`gray`,z),secondarySymbol:n=o(`gray`,z),output:r=process.stdout,spacing:i=1,withGuide:a}={})=>{let s=[],c=a??j.withGuide,l=c?n:``,u=c?`${t} `:``,d=c?`${n} `:``;for(let e=0;e0){let[e,...r]=f;e.length>0?s.push(`${u}${e}`):s.push(c?t:``);for(let e of r)e.length>0?s.push(`${d}${e}`):s.push(c?n:``)}r.write(`${s.join(` +`)} +`)},info:(e,t)=>{H.message(e,{...t,symbol:o(`blue`,Ge)})},success:(e,t)=>{H.message(e,{...t,symbol:o(`green`,Ke)})},step:(e,t)=>{H.message(e,{...t,symbol:o(`green`,R)})},warn:(e,t)=>{H.message(e,{...t,symbol:o(`yellow`,qe)})},warning:(e,t)=>{H.warn(e,t)},error:(e,t)=>{H.message(e,{...t,symbol:o(`red`,Je)})}},et=(e=``,t)=>{let n=t?.output??process.stdout,r=t?.withGuide??j.withGuide?`${o(`gray`,B)} `:``;n.write(`${r}${o(`red`,e)} + +`)},tt=(e=``,t)=>{let n=t?.output??process.stdout,r=t?.withGuide??j.withGuide?`${o(`gray`,z)} +${o(`gray`,B)} `:``;n.write(`${r}${e} + +`)},U=(e,t)=>e.includes(` +`)?e.split(` +`).map(e=>t(e)).join(` +`):t(e),nt=e=>{let t=(e,t)=>{let n=e.label??String(e.value);switch(t){case`disabled`:return`${o(`gray`,V)} ${U(n,e=>o(`gray`,e))}${e.hint?` ${o(`dim`,`(${e.hint??`disabled`})`)}`:``}`;case`selected`:return`${U(n,e=>o(`dim`,e))}`;case`active`:return`${o(`green`,We)} ${n}${e.hint?` ${o(`dim`,`(${e.hint})`)}`:``}`;case`cancelled`:return`${U(n,e=>o([`strikethrough`,`dim`],e))}`;default:return`${o(`dim`,V)} ${U(n,e=>o(`dim`,e))}`}};return new Le({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue,render(){let n=e.withGuide??j.withGuide,r=`${Ye(this.state)} `,i=`${Xe(this.state)} `,a=F(e.output,e.message,i,r),s=`${n?`${o(`gray`,z)} +`:``}${a} +`;switch(this.state){case`submit`:{let r=n?`${o(`gray`,z)} `:``;return`${s}${F(e.output,t(this.options[this.cursor],`selected`),r)}`}case`cancel`:{let r=n?`${o(`gray`,z)} `:``;return`${s}${F(e.output,t(this.options[this.cursor],`cancelled`),r)}${n?` +${o(`gray`,z)}`:``}`}default:{let r=n?`${o(`cyan`,z)} `:``,i=n?o(`cyan`,B):``,a=s.split(` +`).length,c=n?2:1;return`${s}${r}${Qe({output:e.output,cursor:this.cursor,options:this.options,maxItems:e.maxItems,columnPadding:r.length,rowPadding:a+c,style:(e,n)=>t(e,e.disabled?`disabled`:n?`active`:`inactive`)}).join(` +${r}`)} +${i} +`}}}}).prompt()},rt=`${o(`gray`,z)} `,W={message:async(e,{symbol:t=o(`gray`,z)}={})=>{process.stdout.write(`${o(`gray`,z)} +${t} `);let n=3;for await(let t of e){t=t.replace(/\n/g,` +${rt}`),t.includes(` +`)&&(n=3+a(t.slice(t.lastIndexOf(` +`))).length);let e=a(t).length;n+eW.message(e,{symbol:o(`blue`,Ge)}),success:e=>W.message(e,{symbol:o(`green`,Ke)}),step:e=>W.message(e,{symbol:o(`green`,R)}),warn:e=>W.message(e,{symbol:o(`yellow`,qe)}),warning:e=>W.warn(e),error:e=>W.message(e,{symbol:o(`red`,Je)})},it=e=>new Re({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,output:e.output,signal:e.signal,input:e.input,render(){let t=e?.withGuide??j.withGuide,n=`${`${t?`${o(`gray`,z)} +`:``}${Ye(this.state)} `}${e.message} +`,r=e.placeholder?o(`inverse`,e.placeholder[0])+o(`dim`,e.placeholder.slice(1)):o([`inverse`,`hidden`],`_`),i=this.userInput?this.userInputWithCursor:r,a=this.value??``;switch(this.state){case`error`:{let e=this.error?` ${o(`yellow`,this.error)}`:``,r=t?`${o(`yellow`,z)} `:``,a=t?o(`yellow`,B):``;return`${n.trim()} +${r}${i} +${a}${e} +`}case`submit`:{let e=a?` ${o(`dim`,a)}`:``;return`${n}${t?o(`gray`,z):``}${e}`}case`cancel`:{let e=a?` ${o([`strikethrough`,`dim`],a)}`:``,r=t?o(`gray`,z):``;return`${n}${r}${e}${a.trim()?` +${r}`:``}`}default:return`${n}${t?`${o(`cyan`,z)} `:``}${i} +${t?o(`cyan`,B):``} +`}}}).prompt();var at=_(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{KNOWN_AGENTS:()=>ee,determineAgent:()=>te}),t.exports=c(l);var u=b(`node:fs/promises`),d=b(`node:fs`);let f=`cursor`,p=`cursor-cli`,m=`claude`,h=`cowork`,g=`devin`,_=`replit`,v=`gemini`,y=`codex`,x=`antigravity`,S=`augment-cli`,C=`opencode`,w=`github-copilot`,ee={CURSOR:f,CURSOR_CLI:p,CLAUDE:m,COWORK:h,DEVIN:g,REPLIT:_,GEMINI:v,CODEX:y,ANTIGRAVITY:x,AUGMENT_CLI:S,OPENCODE:C,GITHUB_COPILOT:w,V0:`v0`};async function te(){if(process.env.AI_AGENT){let e=process.env.AI_AGENT.trim();if(e)return e===w||e===`github-copilot-cli`?{isAgent:!0,agent:{name:w}}:e===`v0`?{isAgent:!0,agent:{name:`v0`}}:{isAgent:!0,agent:{name:e}}}if(process.env.CURSOR_TRACE_ID)return{isAgent:!0,agent:{name:f}};if(process.env.CURSOR_AGENT||process.env.CURSOR_EXTENSION_HOST_ROLE===`agent-exec`)return{isAgent:!0,agent:{name:p}};if(process.env.GEMINI_CLI)return{isAgent:!0,agent:{name:v}};if(process.env.CODEX_SANDBOX||process.env.CODEX_CI||process.env.CODEX_THREAD_ID)return{isAgent:!0,agent:{name:y}};if(process.env.ANTIGRAVITY_AGENT)return{isAgent:!0,agent:{name:x}};if(process.env.AUGMENT_AGENT)return{isAgent:!0,agent:{name:S}};if(process.env.OPENCODE_CLIENT)return{isAgent:!0,agent:{name:C}};if(process.env.CLAUDECODE||process.env.CLAUDE_CODE)return process.env.CLAUDE_CODE_IS_COWORK?{isAgent:!0,agent:{name:h}}:{isAgent:!0,agent:{name:m}};if(process.env.REPL_ID)return{isAgent:!0,agent:{name:_}};if(process.env.COPILOT_MODEL||process.env.COPILOT_ALLOW_ALL||process.env.COPILOT_GITHUB_TOKEN)return{isAgent:!0,agent:{name:w}};try{return await(0,u.access)(`/opt/.devin`,d.constants.F_OK),{isAgent:!0,agent:{name:g}}}catch{}return{isAgent:!1,agent:void 0}}}))();const{blue:G,blueBright:K,cyan:q,green:ot,greenBright:st,magenta:J,red:Y,redBright:X,reset:ct,underline:lt,yellow:Z}=Pt(),Q=(0,de.default)(process.argv.slice(2),{boolean:[`help`,`overwrite`,`immediate`,`interactive`],alias:{h:`help`,t:`template`,i:`immediate`},string:[`template`]}),ut=process.cwd(),dt=`\ +Usage: create-vite [OPTION]... [DIRECTORY] + +Create a new Vite project in JavaScript or TypeScript. +When running in TTY, the CLI will start in interactive mode. + +Options: + -t, --template NAME use a specific template + -i, --immediate install dependencies and start dev + --overwrite remove existing files if target directory is not empty + --interactive / --no-interactive force interactive / non-interactive mode + +Available templates: +${Z(`vanilla-ts vanilla`)} +${ot(`vue-ts vue`)} +${q(`react-ts react`)} +${q(`react-compiler-ts react-compiler`)} +${J(`preact-ts preact`)} +${X(`lit-ts lit`)} +${Y(`svelte-ts svelte`)} +${G(`solid-ts solid`)} +${K(`qwik-ts qwik`)}`,$=[{name:`vanilla`,display:`Vanilla`,color:Z,variants:[{name:`vanilla-ts`,display:`TypeScript`,color:G},{name:`vanilla`,display:`JavaScript`,color:Z}]},{name:`vue`,display:`Vue`,color:ot,variants:[{name:`vue-ts`,display:`TypeScript`,color:G},{name:`vue`,display:`JavaScript`,color:Z},{name:`custom-create-vue`,display:`Official Vue Starter โ†—`,color:ot,customCommand:`npm create vue@latest TARGET_DIR`},{name:`custom-nuxt`,display:`Nuxt โ†—`,link:`https://nuxt.com`,color:st,customCommand:`npm exec nuxi init TARGET_DIR`},{name:`custom-vike-vue`,display:`Vike โ†—`,link:`https://vike.dev`,color:st,customCommand:`npm create -- vike@latest --vue TARGET_DIR`}]},{name:`react`,display:`React`,color:q,variants:[{name:`react-ts`,display:`TypeScript`,color:G},{name:`react-compiler-ts`,display:`TypeScript + React Compiler`,color:G},{name:`react`,display:`JavaScript`,color:Z},{name:`react-compiler`,display:`JavaScript + React Compiler`,color:Z},{name:`rsc`,display:`RSC`,color:J,customCommand:`npm exec tiged vitejs/vite-plugin-react/packages/plugin-rsc/examples/starter TARGET_DIR`},{name:`custom-react-router`,display:`React Router v7 โ†—`,link:`https://reactrouter.com`,color:q,customCommand:`npm create react-router@latest TARGET_DIR`},{name:`custom-tanstack-router-react`,display:`TanStack Router โ†—`,link:`https://tanstack.com/router`,color:q,customCommand:`npm exec -- @tanstack/cli@latest create TARGET_DIR --framework react --interactive`},{name:`redwoodsdk-standard`,display:`RedwoodSDK โ†—`,link:`https://rwsdk.com`,color:q,customCommand:`npm create rwsdk@latest TARGET_DIR`},{name:`custom-vike-react`,display:`Vike โ†—`,link:`https://vike.dev`,color:q,customCommand:`npm create -- vike@latest --react TARGET_DIR`}]},{name:`preact`,display:`Preact`,color:J,variants:[{name:`preact-ts`,display:`TypeScript`,color:G},{name:`preact`,display:`JavaScript`,color:Z},{name:`custom-create-preact`,display:`Official Preact Starter โ†—`,color:J,customCommand:`npm create preact@latest TARGET_DIR`}]},{name:`lit`,display:`Lit`,color:X,variants:[{name:`lit-ts`,display:`TypeScript`,color:G},{name:`lit`,display:`JavaScript`,color:Z}]},{name:`svelte`,display:`Svelte`,color:Y,variants:[{name:`svelte-ts`,display:`TypeScript`,color:G},{name:`svelte`,display:`JavaScript`,color:Z},{name:`custom-svelte-kit`,display:`SvelteKit โ†—`,color:Y,customCommand:`npm exec sv create TARGET_DIR`}]},{name:`solid`,display:`Solid`,color:G,variants:[{name:`solid-ts`,display:`TypeScript`,color:G},{name:`solid`,display:`JavaScript`,color:Z},{name:`custom-tanstack-router-solid`,display:`TanStack Router โ†—`,link:`https://tanstack.com/router`,color:q,customCommand:`npm exec -- @tanstack/cli@latest create TARGET_DIR --framework solid --interactive`},{name:`custom-vike-solid`,display:`Vike โ†—`,link:`https://vike.dev`,color:q,customCommand:`npm create -- vike@latest --solid TARGET_DIR`}]},{name:`ember`,display:`Ember`,color:X,variants:[{name:`ember-app-ts`,display:`TypeScript โ†—`,color:K,customCommand:`npm exec -- ember-cli@latest new TARGET_DIR --typescript`},{name:`ember-app`,display:`JavaScript โ†—`,color:X,customCommand:`npm exec -- ember-cli@latest new TARGET_DIR`}]},{name:`qwik`,display:`Qwik`,color:K,variants:[{name:`qwik-ts`,display:`TypeScript`,color:K},{name:`qwik`,display:`JavaScript`,color:Z},{name:`custom-qwik-city`,display:`QwikCity โ†—`,color:K,customCommand:`npm create qwik@latest empty TARGET_DIR`}]},{name:`angular`,display:`Angular`,color:Y,variants:[{name:`custom-angular`,display:`Angular โ†—`,color:Y,customCommand:`npm exec @angular/cli@latest new TARGET_DIR`},{name:`custom-analog`,display:`Analog โ†—`,color:Z,customCommand:`npm create analog@latest TARGET_DIR`}]},{name:`marko`,display:`Marko`,color:J,variants:[{name:`marko-run`,display:`Marko Run โ†—`,color:J,customCommand:`npm create -- marko@latest --name TARGET_DIR`}]},{name:`others`,display:`Others`,color:ct,variants:[{name:`create-vite-extra`,display:`Extra Vite Starters โ†—`,color:ct,customCommand:`npm create vite-extra@latest TARGET_DIR`},{name:`create-electron-vite`,display:`Electron โ†—`,color:ct,customCommand:`npm create electron-vite@latest TARGET_DIR`}]}],ft=$.map(e=>e.variants.map(e=>e.name)).reduce((e,t)=>e.concat(t),[]),pt={_gitignore:`.gitignore`},mt=`vite-project`;function ht([e,...t],n){let{status:r,error:i}=ue.default.sync(e,t,n);r!=null&&r>0&&process.exit(r),i&&(console.error(`\n${e} ${t.join(` `)} error!`),console.error(i),process.exit(1))}function gt(e,t){if(process.env._VITE_TEST_CLI){H.step(`Installing dependencies with ${t}... (skipped in test)`);return}H.step(`Installing dependencies with ${t}...`),ht(Mt(t),{stdio:`inherit`,cwd:e})}function _t(e,t){if(process.env._VITE_TEST_CLI){H.step(`Starting dev server... (skipped in test)`);return}H.step(`Starting dev server...`),ht(Nt(t,`dev`),{stdio:`inherit`,cwd:e})}async function vt(){let e=Q._[0]?yt(String(Q._[0])):void 0,i=Q.template,a=Q.overwrite,o=Q.immediate,s=Q.interactive;if(Q.help){console.log(dt);return}let c=s??process.stdin.isTTY,{isAgent:l}=await(0,at.determineAgent)();l&&c&&console.log(` +To create in one go, run: create-vite --no-interactive --template