wozwize commited on
Commit
628d40e
·
1 Parent(s): 9ebad8f

adding database functionality

Browse files
.gitignore CHANGED
@@ -1,5 +1,55 @@
1
- # Ignore Python compiled files
2
  __pycache__/
3
- *.pyc
4
- *.pyo
5
- *.pyd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
  __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual Environment
24
+ venv/
25
+ env/
26
+ ENV/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Local configuration
35
+ local_config.properties
36
+ .env
37
+ .env.local
38
+
39
+ # Logs
40
+ *.log
41
+
42
+ # Coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ coverage.xml
49
+ *.cover
50
+
51
+ # Node
52
+ node_modules/
53
+ npm-debug.log
54
+ yarn-debug.log
55
+ yarn-error.log
app/main.py CHANGED
@@ -1,22 +1,36 @@
 
1
  from fastapi import FastAPI
2
- from fastapi.middleware.cors import CORSMiddleware # ✅ Import this
 
3
  from app.routers import analyze, health
4
 
 
5
  app = FastAPI(title="MediaUnmasked API")
6
 
7
  # ✅ Enable CORS for Swagger UI
8
  app.add_middleware(
9
  CORSMiddleware,
10
- allow_origins=["*"], # Allow all origins (or specify ["http://localhost:7860"])
11
  allow_credentials=True,
12
  allow_methods=["*"], # Allow all methods
13
  allow_headers=["*"], # Allow all headers
14
  )
15
 
16
- # Include routers
 
 
 
 
 
 
 
 
 
 
17
  app.include_router(analyze.router, prefix="/api")
18
  app.include_router(health.router, prefix="/health")
19
 
 
20
  @app.get("/")
21
  async def root():
22
  return {"message": "MediaUnmasked API is running!"}
 
1
+ import os
2
  from fastapi import FastAPI
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from supabase import create_client
5
  from app.routers import analyze, health
6
 
7
+ # FastAPI app setup
8
  app = FastAPI(title="MediaUnmasked API")
9
 
10
  # ✅ Enable CORS for Swagger UI
11
  app.add_middleware(
12
  CORSMiddleware,
13
+ allow_origins=["*"], # Allow all origins (or specify ["http://localhost:7860"] for local testing)
14
  allow_credentials=True,
15
  allow_methods=["*"], # Allow all methods
16
  allow_headers=["*"], # Allow all headers
17
  )
18
 
19
+ # Initialize Supabase connection
20
+ SUPABASE_URL = os.getenv("SUPABASE_URL")
21
+ SUPABASE_KEY = os.getenv("SUPABASE_KEY")
22
+
23
+ if SUPABASE_URL and SUPABASE_KEY:
24
+ supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
25
+ print("Connected to Supabase successfully!")
26
+ else:
27
+ print("Supabase connection failed. Please check your secrets.")
28
+
29
+ # Include routers for analysis and health
30
  app.include_router(analyze.router, prefix="/api")
31
  app.include_router(health.router, prefix="/health")
32
 
33
+ # Test root endpoint to confirm the API is running
34
  @app.get("/")
35
  async def root():
36
  return {"message": "MediaUnmasked API is running!"}
app/routers/analyze.py CHANGED
@@ -2,6 +2,8 @@ from fastapi import APIRouter, HTTPException
2
  from pydantic import BaseModel, HttpUrl
3
  from typing import Dict, Any, List
4
  import logging
 
 
5
 
6
  from mediaunmasked.scrapers.article_scraper import ArticleScraper
7
  from mediaunmasked.analyzers.scoring import MediaScorer
@@ -16,6 +18,11 @@ router = APIRouter(tags=["analysis"])
16
  scraper = ArticleScraper()
17
  scorer = MediaScorer()
18
 
 
 
 
 
 
19
  class ArticleRequest(BaseModel):
20
  url: HttpUrl
21
 
@@ -57,6 +64,15 @@ async def analyze_article(request: ArticleRequest) -> AnalysisResponse:
57
  try:
58
  logger.info(f"Analyzing article: {request.url}")
59
 
 
 
 
 
 
 
 
 
 
60
  # Scrape article
61
  article = scraper.scrape_article(str(request.url))
62
  if not article:
@@ -76,7 +92,7 @@ async def analyze_article(request: ArticleRequest) -> AnalysisResponse:
76
  logger.info(f"media_unmasked_score type: {type(analysis['media_unmasked_score'])}")
77
  logger.info(f"media_unmasked_score value: {analysis['media_unmasked_score']}")
78
 
79
- # Ensure correct types in response
80
  response_dict = {
81
  "headline": str(article['headline']),
82
  "content": str(article['content']),
@@ -110,10 +126,20 @@ async def analyze_article(request: ArticleRequest) -> AnalysisResponse:
110
  }
111
  }
112
 
113
- # Log the final structure
114
- logger.info("Final response structure:")
115
- logger.info(response_dict)
 
 
 
 
 
 
 
 
 
116
 
 
117
  return AnalysisResponse.parse_obj(response_dict)
118
 
119
  except Exception as e:
@@ -157,4 +183,4 @@ async def debug_response():
157
  }
158
  }
159
  }
160
- return AnalysisResponse.parse_obj(mock_analysis)
 
2
  from pydantic import BaseModel, HttpUrl
3
  from typing import Dict, Any, List
4
  import logging
5
+ import os
6
+ from supabase import create_client
7
 
8
  from mediaunmasked.scrapers.article_scraper import ArticleScraper
9
  from mediaunmasked.analyzers.scoring import MediaScorer
 
18
  scraper = ArticleScraper()
19
  scorer = MediaScorer()
20
 
21
+ # Initialize Supabase connection
22
+ SUPABASE_URL = os.getenv("SUPABASE_URL")
23
+ SUPABASE_KEY = os.getenv("SUPABASE_KEY")
24
+ supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
25
+
26
  class ArticleRequest(BaseModel):
27
  url: HttpUrl
28
 
 
64
  try:
65
  logger.info(f"Analyzing article: {request.url}")
66
 
67
+ # Check if the article has already been analyzed
68
+ existing_article = supabase.table('article_analysis').select('*').eq('url', str(request.url)).execute()
69
+
70
+ if existing_article.status_code == 200 and existing_article.data:
71
+ logger.info("Article already analyzed. Returning cached data.")
72
+ # Return the existing analysis result if it exists
73
+ cached_data = existing_article.data[0]
74
+ return AnalysisResponse.parse_obj(cached_data)
75
+
76
  # Scrape article
77
  article = scraper.scrape_article(str(request.url))
78
  if not article:
 
92
  logger.info(f"media_unmasked_score type: {type(analysis['media_unmasked_score'])}")
93
  logger.info(f"media_unmasked_score value: {analysis['media_unmasked_score']}")
94
 
95
+ # Prepare response data
96
  response_dict = {
97
  "headline": str(article['headline']),
98
  "content": str(article['content']),
 
126
  }
127
  }
128
 
129
+ # Save the new analysis to Supabase
130
+ supabase.table('article_analysis').upsert({
131
+ 'url': str(request.url),
132
+ 'headline': response_dict['headline'],
133
+ 'content': response_dict['content'],
134
+ 'sentiment': response_dict['sentiment'],
135
+ 'bias': response_dict['bias'],
136
+ 'bias_score': response_dict['bias_score'],
137
+ 'bias_percentage': response_dict['bias_percentage'],
138
+ 'flagged_phrases': response_dict['flagged_phrases'],
139
+ 'media_score': response_dict['media_score']
140
+ }).execute()
141
 
142
+ # Return the response
143
  return AnalysisResponse.parse_obj(response_dict)
144
 
145
  except Exception as e:
 
183
  }
184
  }
185
  }
186
+ return AnalysisResponse.parse_obj(mock_analysis)
package-lock.json ADDED
@@ -0,0 +1,802 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "media-unmasked-api",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {
6
+ "": {
7
+ "dependencies": {
8
+ "supabase": "^2.12.1"
9
+ }
10
+ },
11
+ "node_modules/@isaacs/cliui": {
12
+ "version": "8.0.2",
13
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
14
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
15
+ "license": "ISC",
16
+ "dependencies": {
17
+ "string-width": "^5.1.2",
18
+ "string-width-cjs": "npm:string-width@^4.2.0",
19
+ "strip-ansi": "^7.0.1",
20
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
21
+ "wrap-ansi": "^8.1.0",
22
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
23
+ },
24
+ "engines": {
25
+ "node": ">=12"
26
+ }
27
+ },
28
+ "node_modules/@isaacs/fs-minipass": {
29
+ "version": "4.0.1",
30
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
31
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
32
+ "license": "ISC",
33
+ "dependencies": {
34
+ "minipass": "^7.0.4"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ }
39
+ },
40
+ "node_modules/@pkgjs/parseargs": {
41
+ "version": "0.11.0",
42
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
43
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
44
+ "license": "MIT",
45
+ "optional": true,
46
+ "engines": {
47
+ "node": ">=14"
48
+ }
49
+ },
50
+ "node_modules/agent-base": {
51
+ "version": "7.1.3",
52
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
53
+ "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
54
+ "license": "MIT",
55
+ "engines": {
56
+ "node": ">= 14"
57
+ }
58
+ },
59
+ "node_modules/ansi-regex": {
60
+ "version": "6.1.0",
61
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
62
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
63
+ "license": "MIT",
64
+ "engines": {
65
+ "node": ">=12"
66
+ },
67
+ "funding": {
68
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
69
+ }
70
+ },
71
+ "node_modules/ansi-styles": {
72
+ "version": "6.2.1",
73
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
74
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
75
+ "license": "MIT",
76
+ "engines": {
77
+ "node": ">=12"
78
+ },
79
+ "funding": {
80
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
81
+ }
82
+ },
83
+ "node_modules/balanced-match": {
84
+ "version": "1.0.2",
85
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
86
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
87
+ "license": "MIT"
88
+ },
89
+ "node_modules/bin-links": {
90
+ "version": "5.0.0",
91
+ "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-5.0.0.tgz",
92
+ "integrity": "sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==",
93
+ "license": "ISC",
94
+ "dependencies": {
95
+ "cmd-shim": "^7.0.0",
96
+ "npm-normalize-package-bin": "^4.0.0",
97
+ "proc-log": "^5.0.0",
98
+ "read-cmd-shim": "^5.0.0",
99
+ "write-file-atomic": "^6.0.0"
100
+ },
101
+ "engines": {
102
+ "node": "^18.17.0 || >=20.5.0"
103
+ }
104
+ },
105
+ "node_modules/brace-expansion": {
106
+ "version": "2.0.1",
107
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
108
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
109
+ "license": "MIT",
110
+ "dependencies": {
111
+ "balanced-match": "^1.0.0"
112
+ }
113
+ },
114
+ "node_modules/chownr": {
115
+ "version": "3.0.0",
116
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
117
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
118
+ "license": "BlueOak-1.0.0",
119
+ "engines": {
120
+ "node": ">=18"
121
+ }
122
+ },
123
+ "node_modules/cmd-shim": {
124
+ "version": "7.0.0",
125
+ "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-7.0.0.tgz",
126
+ "integrity": "sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==",
127
+ "license": "ISC",
128
+ "engines": {
129
+ "node": "^18.17.0 || >=20.5.0"
130
+ }
131
+ },
132
+ "node_modules/color-convert": {
133
+ "version": "2.0.1",
134
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
135
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
136
+ "license": "MIT",
137
+ "dependencies": {
138
+ "color-name": "~1.1.4"
139
+ },
140
+ "engines": {
141
+ "node": ">=7.0.0"
142
+ }
143
+ },
144
+ "node_modules/color-name": {
145
+ "version": "1.1.4",
146
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
147
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
148
+ "license": "MIT"
149
+ },
150
+ "node_modules/cross-spawn": {
151
+ "version": "7.0.6",
152
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
153
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
154
+ "license": "MIT",
155
+ "dependencies": {
156
+ "path-key": "^3.1.0",
157
+ "shebang-command": "^2.0.0",
158
+ "which": "^2.0.1"
159
+ },
160
+ "engines": {
161
+ "node": ">= 8"
162
+ }
163
+ },
164
+ "node_modules/data-uri-to-buffer": {
165
+ "version": "4.0.1",
166
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
167
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
168
+ "license": "MIT",
169
+ "engines": {
170
+ "node": ">= 12"
171
+ }
172
+ },
173
+ "node_modules/debug": {
174
+ "version": "4.4.0",
175
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
176
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
177
+ "license": "MIT",
178
+ "dependencies": {
179
+ "ms": "^2.1.3"
180
+ },
181
+ "engines": {
182
+ "node": ">=6.0"
183
+ },
184
+ "peerDependenciesMeta": {
185
+ "supports-color": {
186
+ "optional": true
187
+ }
188
+ }
189
+ },
190
+ "node_modules/eastasianwidth": {
191
+ "version": "0.2.0",
192
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
193
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
194
+ "license": "MIT"
195
+ },
196
+ "node_modules/emoji-regex": {
197
+ "version": "9.2.2",
198
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
199
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
200
+ "license": "MIT"
201
+ },
202
+ "node_modules/fetch-blob": {
203
+ "version": "3.2.0",
204
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
205
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
206
+ "funding": [
207
+ {
208
+ "type": "github",
209
+ "url": "https://github.com/sponsors/jimmywarting"
210
+ },
211
+ {
212
+ "type": "paypal",
213
+ "url": "https://paypal.me/jimmywarting"
214
+ }
215
+ ],
216
+ "license": "MIT",
217
+ "dependencies": {
218
+ "node-domexception": "^1.0.0",
219
+ "web-streams-polyfill": "^3.0.3"
220
+ },
221
+ "engines": {
222
+ "node": "^12.20 || >= 14.13"
223
+ }
224
+ },
225
+ "node_modules/foreground-child": {
226
+ "version": "3.3.0",
227
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
228
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
229
+ "license": "ISC",
230
+ "dependencies": {
231
+ "cross-spawn": "^7.0.0",
232
+ "signal-exit": "^4.0.1"
233
+ },
234
+ "engines": {
235
+ "node": ">=14"
236
+ },
237
+ "funding": {
238
+ "url": "https://github.com/sponsors/isaacs"
239
+ }
240
+ },
241
+ "node_modules/formdata-polyfill": {
242
+ "version": "4.0.10",
243
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
244
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
245
+ "license": "MIT",
246
+ "dependencies": {
247
+ "fetch-blob": "^3.1.2"
248
+ },
249
+ "engines": {
250
+ "node": ">=12.20.0"
251
+ }
252
+ },
253
+ "node_modules/glob": {
254
+ "version": "10.4.5",
255
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
256
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
257
+ "license": "ISC",
258
+ "dependencies": {
259
+ "foreground-child": "^3.1.0",
260
+ "jackspeak": "^3.1.2",
261
+ "minimatch": "^9.0.4",
262
+ "minipass": "^7.1.2",
263
+ "package-json-from-dist": "^1.0.0",
264
+ "path-scurry": "^1.11.1"
265
+ },
266
+ "bin": {
267
+ "glob": "dist/esm/bin.mjs"
268
+ },
269
+ "funding": {
270
+ "url": "https://github.com/sponsors/isaacs"
271
+ }
272
+ },
273
+ "node_modules/https-proxy-agent": {
274
+ "version": "7.0.6",
275
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
276
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
277
+ "license": "MIT",
278
+ "dependencies": {
279
+ "agent-base": "^7.1.2",
280
+ "debug": "4"
281
+ },
282
+ "engines": {
283
+ "node": ">= 14"
284
+ }
285
+ },
286
+ "node_modules/imurmurhash": {
287
+ "version": "0.1.4",
288
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
289
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
290
+ "license": "MIT",
291
+ "engines": {
292
+ "node": ">=0.8.19"
293
+ }
294
+ },
295
+ "node_modules/is-fullwidth-code-point": {
296
+ "version": "3.0.0",
297
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
298
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
299
+ "license": "MIT",
300
+ "engines": {
301
+ "node": ">=8"
302
+ }
303
+ },
304
+ "node_modules/isexe": {
305
+ "version": "2.0.0",
306
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
307
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
308
+ "license": "ISC"
309
+ },
310
+ "node_modules/jackspeak": {
311
+ "version": "3.4.3",
312
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
313
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
314
+ "license": "BlueOak-1.0.0",
315
+ "dependencies": {
316
+ "@isaacs/cliui": "^8.0.2"
317
+ },
318
+ "funding": {
319
+ "url": "https://github.com/sponsors/isaacs"
320
+ },
321
+ "optionalDependencies": {
322
+ "@pkgjs/parseargs": "^0.11.0"
323
+ }
324
+ },
325
+ "node_modules/lru-cache": {
326
+ "version": "10.4.3",
327
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
328
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
329
+ "license": "ISC"
330
+ },
331
+ "node_modules/minimatch": {
332
+ "version": "9.0.5",
333
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
334
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
335
+ "license": "ISC",
336
+ "dependencies": {
337
+ "brace-expansion": "^2.0.1"
338
+ },
339
+ "engines": {
340
+ "node": ">=16 || 14 >=14.17"
341
+ },
342
+ "funding": {
343
+ "url": "https://github.com/sponsors/isaacs"
344
+ }
345
+ },
346
+ "node_modules/minipass": {
347
+ "version": "7.1.2",
348
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
349
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
350
+ "license": "ISC",
351
+ "engines": {
352
+ "node": ">=16 || 14 >=14.17"
353
+ }
354
+ },
355
+ "node_modules/minizlib": {
356
+ "version": "3.0.1",
357
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz",
358
+ "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==",
359
+ "license": "MIT",
360
+ "dependencies": {
361
+ "minipass": "^7.0.4",
362
+ "rimraf": "^5.0.5"
363
+ },
364
+ "engines": {
365
+ "node": ">= 18"
366
+ }
367
+ },
368
+ "node_modules/mkdirp": {
369
+ "version": "3.0.1",
370
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
371
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
372
+ "license": "MIT",
373
+ "bin": {
374
+ "mkdirp": "dist/cjs/src/bin.js"
375
+ },
376
+ "engines": {
377
+ "node": ">=10"
378
+ },
379
+ "funding": {
380
+ "url": "https://github.com/sponsors/isaacs"
381
+ }
382
+ },
383
+ "node_modules/ms": {
384
+ "version": "2.1.3",
385
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
386
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
387
+ "license": "MIT"
388
+ },
389
+ "node_modules/node-domexception": {
390
+ "version": "1.0.0",
391
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
392
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
393
+ "funding": [
394
+ {
395
+ "type": "github",
396
+ "url": "https://github.com/sponsors/jimmywarting"
397
+ },
398
+ {
399
+ "type": "github",
400
+ "url": "https://paypal.me/jimmywarting"
401
+ }
402
+ ],
403
+ "license": "MIT",
404
+ "engines": {
405
+ "node": ">=10.5.0"
406
+ }
407
+ },
408
+ "node_modules/node-fetch": {
409
+ "version": "3.3.2",
410
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
411
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
412
+ "license": "MIT",
413
+ "dependencies": {
414
+ "data-uri-to-buffer": "^4.0.0",
415
+ "fetch-blob": "^3.1.4",
416
+ "formdata-polyfill": "^4.0.10"
417
+ },
418
+ "engines": {
419
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
420
+ },
421
+ "funding": {
422
+ "type": "opencollective",
423
+ "url": "https://opencollective.com/node-fetch"
424
+ }
425
+ },
426
+ "node_modules/npm-normalize-package-bin": {
427
+ "version": "4.0.0",
428
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz",
429
+ "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==",
430
+ "license": "ISC",
431
+ "engines": {
432
+ "node": "^18.17.0 || >=20.5.0"
433
+ }
434
+ },
435
+ "node_modules/package-json-from-dist": {
436
+ "version": "1.0.1",
437
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
438
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
439
+ "license": "BlueOak-1.0.0"
440
+ },
441
+ "node_modules/path-key": {
442
+ "version": "3.1.1",
443
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
444
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
445
+ "license": "MIT",
446
+ "engines": {
447
+ "node": ">=8"
448
+ }
449
+ },
450
+ "node_modules/path-scurry": {
451
+ "version": "1.11.1",
452
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
453
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
454
+ "license": "BlueOak-1.0.0",
455
+ "dependencies": {
456
+ "lru-cache": "^10.2.0",
457
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
458
+ },
459
+ "engines": {
460
+ "node": ">=16 || 14 >=14.18"
461
+ },
462
+ "funding": {
463
+ "url": "https://github.com/sponsors/isaacs"
464
+ }
465
+ },
466
+ "node_modules/proc-log": {
467
+ "version": "5.0.0",
468
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
469
+ "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==",
470
+ "license": "ISC",
471
+ "engines": {
472
+ "node": "^18.17.0 || >=20.5.0"
473
+ }
474
+ },
475
+ "node_modules/read-cmd-shim": {
476
+ "version": "5.0.0",
477
+ "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-5.0.0.tgz",
478
+ "integrity": "sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==",
479
+ "license": "ISC",
480
+ "engines": {
481
+ "node": "^18.17.0 || >=20.5.0"
482
+ }
483
+ },
484
+ "node_modules/rimraf": {
485
+ "version": "5.0.10",
486
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
487
+ "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
488
+ "license": "ISC",
489
+ "dependencies": {
490
+ "glob": "^10.3.7"
491
+ },
492
+ "bin": {
493
+ "rimraf": "dist/esm/bin.mjs"
494
+ },
495
+ "funding": {
496
+ "url": "https://github.com/sponsors/isaacs"
497
+ }
498
+ },
499
+ "node_modules/shebang-command": {
500
+ "version": "2.0.0",
501
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
502
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
503
+ "license": "MIT",
504
+ "dependencies": {
505
+ "shebang-regex": "^3.0.0"
506
+ },
507
+ "engines": {
508
+ "node": ">=8"
509
+ }
510
+ },
511
+ "node_modules/shebang-regex": {
512
+ "version": "3.0.0",
513
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
514
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
515
+ "license": "MIT",
516
+ "engines": {
517
+ "node": ">=8"
518
+ }
519
+ },
520
+ "node_modules/signal-exit": {
521
+ "version": "4.1.0",
522
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
523
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
524
+ "license": "ISC",
525
+ "engines": {
526
+ "node": ">=14"
527
+ },
528
+ "funding": {
529
+ "url": "https://github.com/sponsors/isaacs"
530
+ }
531
+ },
532
+ "node_modules/string-width": {
533
+ "version": "5.1.2",
534
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
535
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
536
+ "license": "MIT",
537
+ "dependencies": {
538
+ "eastasianwidth": "^0.2.0",
539
+ "emoji-regex": "^9.2.2",
540
+ "strip-ansi": "^7.0.1"
541
+ },
542
+ "engines": {
543
+ "node": ">=12"
544
+ },
545
+ "funding": {
546
+ "url": "https://github.com/sponsors/sindresorhus"
547
+ }
548
+ },
549
+ "node_modules/string-width-cjs": {
550
+ "name": "string-width",
551
+ "version": "4.2.3",
552
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
553
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
554
+ "license": "MIT",
555
+ "dependencies": {
556
+ "emoji-regex": "^8.0.0",
557
+ "is-fullwidth-code-point": "^3.0.0",
558
+ "strip-ansi": "^6.0.1"
559
+ },
560
+ "engines": {
561
+ "node": ">=8"
562
+ }
563
+ },
564
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
565
+ "version": "5.0.1",
566
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
567
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
568
+ "license": "MIT",
569
+ "engines": {
570
+ "node": ">=8"
571
+ }
572
+ },
573
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
574
+ "version": "8.0.0",
575
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
576
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
577
+ "license": "MIT"
578
+ },
579
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
580
+ "version": "6.0.1",
581
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
582
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
583
+ "license": "MIT",
584
+ "dependencies": {
585
+ "ansi-regex": "^5.0.1"
586
+ },
587
+ "engines": {
588
+ "node": ">=8"
589
+ }
590
+ },
591
+ "node_modules/strip-ansi": {
592
+ "version": "7.1.0",
593
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
594
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
595
+ "license": "MIT",
596
+ "dependencies": {
597
+ "ansi-regex": "^6.0.1"
598
+ },
599
+ "engines": {
600
+ "node": ">=12"
601
+ },
602
+ "funding": {
603
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
604
+ }
605
+ },
606
+ "node_modules/strip-ansi-cjs": {
607
+ "name": "strip-ansi",
608
+ "version": "6.0.1",
609
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
610
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
611
+ "license": "MIT",
612
+ "dependencies": {
613
+ "ansi-regex": "^5.0.1"
614
+ },
615
+ "engines": {
616
+ "node": ">=8"
617
+ }
618
+ },
619
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
620
+ "version": "5.0.1",
621
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
622
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
623
+ "license": "MIT",
624
+ "engines": {
625
+ "node": ">=8"
626
+ }
627
+ },
628
+ "node_modules/supabase": {
629
+ "version": "2.12.1",
630
+ "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.12.1.tgz",
631
+ "integrity": "sha512-vB6LX1KGrqku8AFlp2vJw49IUB9g6Rz2b84qpcWSZ3mMDFumA6hDSbXbFJUnr3hcvyPzoOsQlhMTZN7a6o3hfA==",
632
+ "hasInstallScript": true,
633
+ "license": "MIT",
634
+ "dependencies": {
635
+ "bin-links": "^5.0.0",
636
+ "https-proxy-agent": "^7.0.2",
637
+ "node-fetch": "^3.3.2",
638
+ "tar": "7.4.3"
639
+ },
640
+ "bin": {
641
+ "supabase": "bin/supabase"
642
+ },
643
+ "engines": {
644
+ "npm": ">=8"
645
+ }
646
+ },
647
+ "node_modules/tar": {
648
+ "version": "7.4.3",
649
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
650
+ "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
651
+ "license": "ISC",
652
+ "dependencies": {
653
+ "@isaacs/fs-minipass": "^4.0.0",
654
+ "chownr": "^3.0.0",
655
+ "minipass": "^7.1.2",
656
+ "minizlib": "^3.0.1",
657
+ "mkdirp": "^3.0.1",
658
+ "yallist": "^5.0.0"
659
+ },
660
+ "engines": {
661
+ "node": ">=18"
662
+ }
663
+ },
664
+ "node_modules/web-streams-polyfill": {
665
+ "version": "3.3.3",
666
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
667
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
668
+ "license": "MIT",
669
+ "engines": {
670
+ "node": ">= 8"
671
+ }
672
+ },
673
+ "node_modules/which": {
674
+ "version": "2.0.2",
675
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
676
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
677
+ "license": "ISC",
678
+ "dependencies": {
679
+ "isexe": "^2.0.0"
680
+ },
681
+ "bin": {
682
+ "node-which": "bin/node-which"
683
+ },
684
+ "engines": {
685
+ "node": ">= 8"
686
+ }
687
+ },
688
+ "node_modules/wrap-ansi": {
689
+ "version": "8.1.0",
690
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
691
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
692
+ "license": "MIT",
693
+ "dependencies": {
694
+ "ansi-styles": "^6.1.0",
695
+ "string-width": "^5.0.1",
696
+ "strip-ansi": "^7.0.1"
697
+ },
698
+ "engines": {
699
+ "node": ">=12"
700
+ },
701
+ "funding": {
702
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
703
+ }
704
+ },
705
+ "node_modules/wrap-ansi-cjs": {
706
+ "name": "wrap-ansi",
707
+ "version": "7.0.0",
708
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
709
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
710
+ "license": "MIT",
711
+ "dependencies": {
712
+ "ansi-styles": "^4.0.0",
713
+ "string-width": "^4.1.0",
714
+ "strip-ansi": "^6.0.0"
715
+ },
716
+ "engines": {
717
+ "node": ">=10"
718
+ },
719
+ "funding": {
720
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
721
+ }
722
+ },
723
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
724
+ "version": "5.0.1",
725
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
726
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
727
+ "license": "MIT",
728
+ "engines": {
729
+ "node": ">=8"
730
+ }
731
+ },
732
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
733
+ "version": "4.3.0",
734
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
735
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
736
+ "license": "MIT",
737
+ "dependencies": {
738
+ "color-convert": "^2.0.1"
739
+ },
740
+ "engines": {
741
+ "node": ">=8"
742
+ },
743
+ "funding": {
744
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
745
+ }
746
+ },
747
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
748
+ "version": "8.0.0",
749
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
750
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
751
+ "license": "MIT"
752
+ },
753
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
754
+ "version": "4.2.3",
755
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
756
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
757
+ "license": "MIT",
758
+ "dependencies": {
759
+ "emoji-regex": "^8.0.0",
760
+ "is-fullwidth-code-point": "^3.0.0",
761
+ "strip-ansi": "^6.0.1"
762
+ },
763
+ "engines": {
764
+ "node": ">=8"
765
+ }
766
+ },
767
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
768
+ "version": "6.0.1",
769
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
770
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
771
+ "license": "MIT",
772
+ "dependencies": {
773
+ "ansi-regex": "^5.0.1"
774
+ },
775
+ "engines": {
776
+ "node": ">=8"
777
+ }
778
+ },
779
+ "node_modules/write-file-atomic": {
780
+ "version": "6.0.0",
781
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz",
782
+ "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==",
783
+ "license": "ISC",
784
+ "dependencies": {
785
+ "imurmurhash": "^0.1.4",
786
+ "signal-exit": "^4.0.1"
787
+ },
788
+ "engines": {
789
+ "node": "^18.17.0 || >=20.5.0"
790
+ }
791
+ },
792
+ "node_modules/yallist": {
793
+ "version": "5.0.0",
794
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
795
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
796
+ "license": "BlueOak-1.0.0",
797
+ "engines": {
798
+ "node": ">=18"
799
+ }
800
+ }
801
+ }
802
+ }
package.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "dependencies": {
3
+ "supabase": "^2.12.1"
4
+ }
5
+ }
requirements.txt CHANGED
@@ -2,8 +2,8 @@ fastapi[all]==0.109.2
2
  uvicorn==0.27.1
3
  pydantic==2.6.1
4
  beautifulsoup4==4.12.3
5
- requests==2.31.0
6
- python-dotenv==1.0.1
7
  textblob==0.17.1
8
  nltk==3.8.1
9
  transformers==4.36.2
@@ -12,3 +12,5 @@ numpy==1.26.3
12
  pytest==7.4.3
13
  pytest-asyncio==0.21.1
14
  httpx==0.25.2
 
 
 
2
  uvicorn==0.27.1
3
  pydantic==2.6.1
4
  beautifulsoup4==4.12.3
5
+ requests>=2.31.0
6
+ python-dotenv>=1.0.0
7
  textblob==0.17.1
8
  nltk==3.8.1
9
  transformers==4.36.2
 
12
  pytest==7.4.3
13
  pytest-asyncio==0.21.1
14
  httpx==0.25.2
15
+ supabase>=2.0.0
16
+ configparser>=6.0.0
tests/test_supabase.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import configparser
2
+ from supabase import create_client
3
+
4
+ # Read the properties file
5
+ config = configparser.ConfigParser()
6
+ config.read('local_config.properties')
7
+
8
+ # Extract values from the properties file
9
+ SUPABASE_URL = config.get('DEFAULT', 'SUPABASE_URL')
10
+ SUPABASE_KEY = config.get('DEFAULT', 'SUPABASE_KEY')
11
+
12
+ # Initialize Supabase client
13
+ supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
14
+
15
+ # Test data to insert and update
16
+ test_url = "https://www.straitstimes.com/world/united-states/us-senate-confirms-trump-loyalist-kash-patel-to-head-fbi"
17
+ test_headline = "US Senate confirms Trump loyalist Kash Patel to head FBI"
18
+ test_content = "This is some test content for the article."
19
+
20
+ # 1. Insert data into the 'article_analysis' table
21
+ def insert_data():
22
+ try:
23
+ response = supabase.table('article_analysis').upsert({
24
+ 'url': test_url,
25
+ 'headline': test_headline,
26
+ 'content': test_content,
27
+ 'sentiment': 'Neutral',
28
+ 'bias': 'Neutral',
29
+ 'bias_score': 0.0,
30
+ 'bias_percentage': 0.0,
31
+ 'flagged_phrases': [],
32
+ 'media_score': {
33
+ 'media_unmasked_score': 75.0,
34
+ 'rating': 'Neutral',
35
+ 'details': {
36
+ 'headline_analysis': {'headline_vs_content_score': 50},
37
+ 'sentiment_analysis': {'sentiment': 'Neutral'},
38
+ 'bias_analysis': {'bias': 'Neutral'},
39
+ 'evidence_analysis': {'evidence_based_score': 80.0}
40
+ }
41
+ }
42
+ }).execute()
43
+ print("Data inserted successfully")
44
+ print(f"Response data: {response.data}")
45
+ except Exception as e:
46
+ print(f"Error inserting data: {str(e)}")
47
+
48
+ # 2. Update data (e.g., changing the sentiment)
49
+ def update_data():
50
+ try:
51
+ updated_sentiment = "Positive"
52
+ response = supabase.table('article_analysis').upsert({
53
+ 'url': test_url,
54
+ 'sentiment': updated_sentiment # Update only the sentiment field
55
+ }).execute()
56
+ print("Data updated successfully")
57
+ print(f"Response data: {response.data}")
58
+ except Exception as e:
59
+ print(f"Error updating data: {str(e)}")
60
+
61
+ # 3. Retrieve data by URL
62
+ def retrieve_data():
63
+ try:
64
+ result = supabase.table('article_analysis').select('*').eq('url', test_url).execute()
65
+ if result.data:
66
+ print(f"Retrieved data: {result.data}")
67
+ else:
68
+ print("No data found for the given URL")
69
+ except Exception as e:
70
+ print(f"Error retrieving data: {str(e)}")
71
+
72
+ # Run the tests: Insert, Update, and Retrieve data
73
+ insert_data()
74
+ update_data()
75
+ retrieve_data()