Stijnus commited on
Commit
fd98059
·
1 Parent(s): 5a6c0e5

connection github enhancements

Browse files
app/components/settings/connections/ConnectionsTab.tsx CHANGED
@@ -8,11 +8,34 @@ interface GitHubUserResponse {
8
  login: string;
9
  avatar_url: string;
10
  html_url: string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
12
 
13
  interface GitHubConnection {
14
  user: GitHubUserResponse | null;
15
  token: string;
 
16
  }
17
 
18
  export default function ConnectionsTab() {
@@ -22,18 +45,59 @@ export default function ConnectionsTab() {
22
  });
23
  const [isLoading, setIsLoading] = useState(true);
24
  const [isConnecting, setIsConnecting] = useState(false);
 
25
 
26
  // Load saved connection on mount
27
  useEffect(() => {
28
  const savedConnection = localStorage.getItem('github_connection');
29
 
30
  if (savedConnection) {
31
- setConnection(JSON.parse(savedConnection));
 
 
 
 
32
  }
33
 
34
  setIsLoading(false);
35
  }, []);
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  const fetchGithubUser = async (token: string) => {
38
  try {
39
  setIsConnecting(true);
@@ -44,16 +108,18 @@ export default function ConnectionsTab() {
44
  },
45
  });
46
 
47
- if (!response.ok) {
48
- throw new Error('Invalid token or unauthorized');
49
- }
50
 
51
- const data = (await response.json()) as GitHubUserResponse;
52
  const newConnection = { user: data, token };
53
 
54
  // Save connection
55
  localStorage.setItem('github_connection', JSON.stringify(newConnection));
56
  setConnection(newConnection);
 
 
 
 
57
  toast.success('Successfully connected to GitHub');
58
  } catch (error) {
59
  logStore.logError('Failed to authenticate with GitHub', { error });
@@ -75,16 +141,7 @@ export default function ConnectionsTab() {
75
  toast.success('Disconnected from GitHub');
76
  };
77
 
78
- if (isLoading) {
79
- return (
80
- <div className="flex items-center justify-center p-4">
81
- <div className="flex items-center gap-2">
82
- <div className="i-ph:spinner-gap-bold animate-spin w-4 h-4" />
83
- <span className="text-bolt-elements-textSecondary">Loading...</span>
84
- </div>
85
- </div>
86
- );
87
- }
88
 
89
  return (
90
  <div className="space-y-4">
@@ -200,9 +257,92 @@ export default function ConnectionsTab() {
200
  </span>
201
  )}
202
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  </div>
204
  </motion.div>
205
  </div>
206
  </div>
207
  );
208
  }
 
 
 
 
 
 
 
 
 
 
 
 
8
  login: string;
9
  avatar_url: string;
10
  html_url: string;
11
+ name: string;
12
+ bio: string;
13
+ public_repos: number;
14
+ followers: number;
15
+ following: number;
16
+ }
17
+
18
+ interface GitHubRepoInfo {
19
+ name: string;
20
+ full_name: string;
21
+ html_url: string;
22
+ description: string;
23
+ stargazers_count: number;
24
+ forks_count: number;
25
+ default_branch: string;
26
+ updated_at: string;
27
+ }
28
+
29
+ interface GitHubStats {
30
+ repos: GitHubRepoInfo[];
31
+ totalStars: number;
32
+ totalForks: number;
33
  }
34
 
35
  interface GitHubConnection {
36
  user: GitHubUserResponse | null;
37
  token: string;
38
+ stats?: GitHubStats;
39
  }
40
 
41
  export default function ConnectionsTab() {
 
45
  });
46
  const [isLoading, setIsLoading] = useState(true);
47
  const [isConnecting, setIsConnecting] = useState(false);
48
+ const [isFetchingStats, setIsFetchingStats] = useState(false);
49
 
50
  // Load saved connection on mount
51
  useEffect(() => {
52
  const savedConnection = localStorage.getItem('github_connection');
53
 
54
  if (savedConnection) {
55
+ const parsed = JSON.parse(savedConnection);
56
+ setConnection(parsed);
57
+ if (parsed.user && parsed.token) {
58
+ fetchGitHubStats(parsed.token);
59
+ }
60
  }
61
 
62
  setIsLoading(false);
63
  }, []);
64
 
65
+ const fetchGitHubStats = async (token: string) => {
66
+ try {
67
+ setIsFetchingStats(true);
68
+
69
+ // Fetch repositories
70
+ const reposResponse = await fetch('https://api.github.com/user/repos?sort=updated&per_page=10', {
71
+ headers: {
72
+ Authorization: `Bearer ${token}`,
73
+ },
74
+ });
75
+
76
+ if (!reposResponse.ok) throw new Error('Failed to fetch repositories');
77
+
78
+ const repos = await reposResponse.json() as GitHubRepoInfo[];
79
+
80
+ // Calculate total stats
81
+ const totalStars = repos.reduce((acc, repo) => acc + repo.stargazers_count, 0);
82
+ const totalForks = repos.reduce((acc, repo) => acc + repo.forks_count, 0);
83
+
84
+ setConnection(prev => ({
85
+ ...prev,
86
+ stats: {
87
+ repos,
88
+ totalStars,
89
+ totalForks,
90
+ },
91
+ }));
92
+
93
+ } catch (error) {
94
+ logStore.logError('Failed to fetch GitHub stats', { error });
95
+ toast.error('Failed to fetch GitHub statistics');
96
+ } finally {
97
+ setIsFetchingStats(false);
98
+ }
99
+ };
100
+
101
  const fetchGithubUser = async (token: string) => {
102
  try {
103
  setIsConnecting(true);
 
108
  },
109
  });
110
 
111
+ if (!response.ok) throw new Error('Invalid token or unauthorized');
 
 
112
 
113
+ const data = await response.json() as GitHubUserResponse;
114
  const newConnection = { user: data, token };
115
 
116
  // Save connection
117
  localStorage.setItem('github_connection', JSON.stringify(newConnection));
118
  setConnection(newConnection);
119
+
120
+ // Fetch additional stats
121
+ await fetchGitHubStats(token);
122
+
123
  toast.success('Successfully connected to GitHub');
124
  } catch (error) {
125
  logStore.logError('Failed to authenticate with GitHub', { error });
 
141
  toast.success('Disconnected from GitHub');
142
  };
143
 
144
+ if (isLoading) return <LoadingSpinner />;
 
 
 
 
 
 
 
 
 
145
 
146
  return (
147
  <div className="space-y-4">
 
257
  </span>
258
  )}
259
  </div>
260
+
261
+ {connection.user && connection.stats && (
262
+ <div className="mt-6 border-t border-[#E5E5E5] dark:border-[#1A1A1A] pt-6">
263
+ <div className="flex items-center gap-4 mb-6">
264
+ <img
265
+ src={connection.user.avatar_url}
266
+ alt={connection.user.login}
267
+ className="w-16 h-16 rounded-full"
268
+ />
269
+ <div>
270
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary">
271
+ {connection.user.name || connection.user.login}
272
+ </h3>
273
+ {connection.user.bio && (
274
+ <p className="text-sm text-bolt-elements-textSecondary">{connection.user.bio}</p>
275
+ )}
276
+ <div className="flex gap-4 mt-2 text-sm text-bolt-elements-textSecondary">
277
+ <span className="flex items-center gap-1">
278
+ <div className="i-ph:users w-4 h-4" />
279
+ {connection.user.followers} followers
280
+ </span>
281
+ <span className="flex items-center gap-1">
282
+ <div className="i-ph:star w-4 h-4" />
283
+ {connection.stats.totalStars} stars
284
+ </span>
285
+ <span className="flex items-center gap-1">
286
+ <div className="i-ph:git-fork w-4 h-4" />
287
+ {connection.stats.totalForks} forks
288
+ </span>
289
+ </div>
290
+ </div>
291
+ </div>
292
+
293
+ <h4 className="text-sm font-medium text-bolt-elements-textPrimary mb-3">
294
+ Recent Repositories
295
+ </h4>
296
+ <div className="space-y-3">
297
+ {connection.stats.repos.map((repo) => (
298
+ <a
299
+ key={repo.full_name}
300
+ href={repo.html_url}
301
+ target="_blank"
302
+ rel="noopener noreferrer"
303
+ className="block p-3 rounded-lg bg-[#F8F8F8] dark:bg-[#1A1A1A] hover:bg-[#F0F0F0] dark:hover:bg-[#252525] transition-colors"
304
+ >
305
+ <div className="flex items-center justify-between">
306
+ <div>
307
+ <h5 className="text-sm font-medium text-bolt-elements-textPrimary">
308
+ {repo.name}
309
+ </h5>
310
+ {repo.description && (
311
+ <p className="text-xs text-bolt-elements-textSecondary mt-1">
312
+ {repo.description}
313
+ </p>
314
+ )}
315
+ </div>
316
+ <div className="flex items-center gap-3 text-xs text-bolt-elements-textSecondary">
317
+ <span className="flex items-center gap-1">
318
+ <div className="i-ph:star w-3 h-3" />
319
+ {repo.stargazers_count}
320
+ </span>
321
+ <span className="flex items-center gap-1">
322
+ <div className="i-ph:git-fork w-3 h-3" />
323
+ {repo.forks_count}
324
+ </span>
325
+ </div>
326
+ </div>
327
+ </a>
328
+ ))}
329
+ </div>
330
+ </div>
331
+ )}
332
  </div>
333
  </motion.div>
334
  </div>
335
  </div>
336
  );
337
  }
338
+
339
+ function LoadingSpinner() {
340
+ return (
341
+ <div className="flex items-center justify-center p-4">
342
+ <div className="flex items-center gap-2">
343
+ <div className="i-ph:spinner-gap-bold animate-spin w-4 h-4" />
344
+ <span className="text-bolt-elements-textSecondary">Loading...</span>
345
+ </div>
346
+ </div>
347
+ );
348
+ }
app/components/settings/debug/DebugTab.tsx CHANGED
@@ -84,6 +84,7 @@ interface SystemInfo {
84
  }
85
 
86
  interface WebAppInfo {
 
87
  name: string;
88
  version: string;
89
  description: string;
@@ -91,6 +92,33 @@ interface WebAppInfo {
91
  nodeVersion: string;
92
  dependencies: { [key: string]: string };
93
  devDependencies: { [key: string]: string };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
 
96
  export default function DebugTab() {
@@ -298,14 +326,54 @@ export default function DebugTab() {
298
  try {
299
  setLoading((prev) => ({ ...prev, webAppInfo: true }));
300
 
301
- const response = await fetch('/api/system/app-info');
302
-
303
- if (!response.ok) {
304
  throw new Error('Failed to fetch webapp info');
305
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
 
307
- const data = await response.json();
308
- setWebAppInfo(data as WebAppInfo);
 
 
 
 
309
  } catch (error) {
310
  console.error('Failed to fetch webapp info:', error);
311
  toast.error('Failed to fetch webapp information');
@@ -895,6 +963,27 @@ export default function DebugTab() {
895
  <span className="text-bolt-elements-textSecondary">Node Version: </span>
896
  <span className="text-bolt-elements-textPrimary">{webAppInfo.nodeVersion}</span>
897
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
  </div>
899
  <div className="space-y-2">
900
  <div className="text-sm">
@@ -912,6 +1001,71 @@ export default function DebugTab() {
912
  ))}
913
  </div>
914
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
915
  </div>
916
  </div>
917
  ) : (
 
84
  }
85
 
86
  interface WebAppInfo {
87
+ // Local WebApp Info
88
  name: string;
89
  version: string;
90
  description: string;
 
92
  nodeVersion: string;
93
  dependencies: { [key: string]: string };
94
  devDependencies: { [key: string]: string };
95
+ // Build Info
96
+ buildTime?: string;
97
+ buildNumber?: string;
98
+ environment?: string;
99
+ // Git Info
100
+ gitInfo?: {
101
+ branch: string;
102
+ commit: string;
103
+ commitTime: string;
104
+ author: string;
105
+ remoteUrl: string;
106
+ };
107
+ // GitHub Repository Info
108
+ repoInfo?: {
109
+ name: string;
110
+ fullName: string;
111
+ description: string;
112
+ stars: number;
113
+ forks: number;
114
+ openIssues: number;
115
+ defaultBranch: string;
116
+ lastUpdate: string;
117
+ owner: {
118
+ login: string;
119
+ avatarUrl: string;
120
+ };
121
+ };
122
  }
123
 
124
  export default function DebugTab() {
 
326
  try {
327
  setLoading((prev) => ({ ...prev, webAppInfo: true }));
328
 
329
+ // Fetch local app info
330
+ const appInfoResponse = await fetch('/api/system/app-info');
331
+ if (!appInfoResponse.ok) {
332
  throw new Error('Failed to fetch webapp info');
333
  }
334
+ const appData = await appInfoResponse.json();
335
+
336
+ // Fetch git info
337
+ const gitInfoResponse = await fetch('/api/system/git-info');
338
+ let gitInfo = null;
339
+ if (gitInfoResponse.ok) {
340
+ gitInfo = await gitInfoResponse.json();
341
+ }
342
+
343
+ // Fetch GitHub repository info
344
+ const repoInfoResponse = await fetch('https://api.github.com/repos/stackblitz-labs/bolt.diy');
345
+ let repoInfo = null;
346
+ if (repoInfoResponse.ok) {
347
+ const repoData = await repoInfoResponse.json();
348
+ repoInfo = {
349
+ name: repoData.name,
350
+ fullName: repoData.full_name,
351
+ description: repoData.description,
352
+ stars: repoData.stargazers_count,
353
+ forks: repoData.forks_count,
354
+ openIssues: repoData.open_issues_count,
355
+ defaultBranch: repoData.default_branch,
356
+ lastUpdate: repoData.updated_at,
357
+ owner: {
358
+ login: repoData.owner.login,
359
+ avatarUrl: repoData.owner.avatar_url,
360
+ },
361
+ };
362
+ }
363
+
364
+ // Get build info from environment variables or config
365
+ const buildInfo = {
366
+ buildTime: process.env.NEXT_PUBLIC_BUILD_TIME || new Date().toISOString(),
367
+ buildNumber: process.env.NEXT_PUBLIC_BUILD_NUMBER || 'development',
368
+ environment: process.env.NEXT_PUBLIC_ENV || 'development',
369
+ };
370
 
371
+ setWebAppInfo({
372
+ ...appData,
373
+ ...buildInfo,
374
+ gitInfo,
375
+ repoInfo,
376
+ });
377
  } catch (error) {
378
  console.error('Failed to fetch webapp info:', error);
379
  toast.error('Failed to fetch webapp information');
 
963
  <span className="text-bolt-elements-textSecondary">Node Version: </span>
964
  <span className="text-bolt-elements-textPrimary">{webAppInfo.nodeVersion}</span>
965
  </div>
966
+ {webAppInfo.buildTime && (
967
+ <div className="text-sm flex items-center gap-2">
968
+ <div className="i-ph:calendar text-bolt-elements-textSecondary w-4 h-4" />
969
+ <span className="text-bolt-elements-textSecondary">Build Time: </span>
970
+ <span className="text-bolt-elements-textPrimary">{webAppInfo.buildTime}</span>
971
+ </div>
972
+ )}
973
+ {webAppInfo.buildNumber && (
974
+ <div className="text-sm flex items-center gap-2">
975
+ <div className="i-ph:hash text-bolt-elements-textSecondary w-4 h-4" />
976
+ <span className="text-bolt-elements-textSecondary">Build Number: </span>
977
+ <span className="text-bolt-elements-textPrimary">{webAppInfo.buildNumber}</span>
978
+ </div>
979
+ )}
980
+ {webAppInfo.environment && (
981
+ <div className="text-sm flex items-center gap-2">
982
+ <div className="i-ph:cloud text-bolt-elements-textSecondary w-4 h-4" />
983
+ <span className="text-bolt-elements-textSecondary">Environment: </span>
984
+ <span className="text-bolt-elements-textPrimary">{webAppInfo.environment}</span>
985
+ </div>
986
+ )}
987
  </div>
988
  <div className="space-y-2">
989
  <div className="text-sm">
 
1001
  ))}
1002
  </div>
1003
  </div>
1004
+ {webAppInfo.gitInfo && (
1005
+ <div className="text-sm">
1006
+ <div className="flex items-center gap-2 mb-2">
1007
+ <div className="i-ph:git-branch text-bolt-elements-textSecondary w-4 h-4" />
1008
+ <span className="text-bolt-elements-textSecondary">Git Info:</span>
1009
+ </div>
1010
+ <div className="pl-6 space-y-1">
1011
+ <div className="text-xs text-bolt-elements-textPrimary">
1012
+ Branch: {webAppInfo.gitInfo.branch}
1013
+ </div>
1014
+ <div className="text-xs text-bolt-elements-textPrimary">
1015
+ Commit: {webAppInfo.gitInfo.commit}
1016
+ </div>
1017
+ <div className="text-xs text-bolt-elements-textPrimary">
1018
+ Commit Time: {webAppInfo.gitInfo.commitTime}
1019
+ </div>
1020
+ <div className="text-xs text-bolt-elements-textPrimary">
1021
+ Author: {webAppInfo.gitInfo.author}
1022
+ </div>
1023
+ <div className="text-xs text-bolt-elements-textPrimary">
1024
+ Remote URL: {webAppInfo.gitInfo.remoteUrl}
1025
+ </div>
1026
+ </div>
1027
+ </div>
1028
+ )}
1029
+ {webAppInfo.repoInfo && (
1030
+ <div className="text-sm">
1031
+ <div className="flex items-center gap-2 mb-2">
1032
+ <div className="i-ph:github text-bolt-elements-textSecondary w-4 h-4" />
1033
+ <span className="text-bolt-elements-textSecondary">GitHub Repository:</span>
1034
+ </div>
1035
+ <div className="pl-6 space-y-1">
1036
+ <div className="text-xs text-bolt-elements-textPrimary">
1037
+ Name: {webAppInfo.repoInfo.name}
1038
+ </div>
1039
+ <div className="text-xs text-bolt-elements-textPrimary">
1040
+ Full Name: {webAppInfo.repoInfo.fullName}
1041
+ </div>
1042
+ <div className="text-xs text-bolt-elements-textPrimary">
1043
+ Description: {webAppInfo.repoInfo.description}
1044
+ </div>
1045
+ <div className="text-xs text-bolt-elements-textPrimary">
1046
+ Stars: {webAppInfo.repoInfo.stars}
1047
+ </div>
1048
+ <div className="text-xs text-bolt-elements-textPrimary">
1049
+ Forks: {webAppInfo.repoInfo.forks}
1050
+ </div>
1051
+ <div className="text-xs text-bolt-elements-textPrimary">
1052
+ Open Issues: {webAppInfo.repoInfo.openIssues}
1053
+ </div>
1054
+ <div className="text-xs text-bolt-elements-textPrimary">
1055
+ Default Branch: {webAppInfo.repoInfo.defaultBranch}
1056
+ </div>
1057
+ <div className="text-xs text-bolt-elements-textPrimary">
1058
+ Last Update: {webAppInfo.repoInfo.lastUpdate}
1059
+ </div>
1060
+ <div className="text-xs text-bolt-elements-textPrimary">
1061
+ Owner: {webAppInfo.repoInfo.owner.login}
1062
+ </div>
1063
+ <div className="text-xs text-bolt-elements-textPrimary">
1064
+ Avatar URL: {webAppInfo.repoInfo.owner.avatarUrl}
1065
+ </div>
1066
+ </div>
1067
+ </div>
1068
+ )}
1069
  </div>
1070
  </div>
1071
  ) : (
app/routes/api.system.git-info.ts ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { json } from '@remix-run/node';
2
+ import type { LoaderFunctionArgs } from '@remix-run/node';
3
+ import { execSync } from 'child_process';
4
+
5
+ export async function loader({ request }: LoaderFunctionArgs) {
6
+ try {
7
+ const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
8
+ const commit = execSync('git rev-parse --short HEAD').toString().trim();
9
+ const lastCommitMessage = execSync('git log -1 --pretty=%B').toString().trim();
10
+
11
+ return json({
12
+ branch,
13
+ commit,
14
+ lastCommitMessage,
15
+ timestamp: new Date().toISOString(),
16
+ });
17
+ } catch (error) {
18
+ return json(
19
+ {
20
+ error: 'Failed to fetch git information',
21
+ details: error instanceof Error ? error.message : 'Unknown error',
22
+ },
23
+ { status: 500 },
24
+ );
25
+ }
26
+ }
package.json CHANGED
@@ -67,6 +67,7 @@
67
  "@radix-ui/react-tooltip": "^1.1.4",
68
  "@remix-run/cloudflare": "^2.15.0",
69
  "@remix-run/cloudflare-pages": "^2.15.0",
 
70
  "@remix-run/react": "^2.15.0",
71
  "@uiw/codemirror-theme-vscode": "^4.23.6",
72
  "@unocss/reset": "^0.61.9",
 
67
  "@radix-ui/react-tooltip": "^1.1.4",
68
  "@remix-run/cloudflare": "^2.15.0",
69
  "@remix-run/cloudflare-pages": "^2.15.0",
70
+ "@remix-run/node": "^2.15.2",
71
  "@remix-run/react": "^2.15.0",
72
  "@uiw/codemirror-theme-vscode": "^4.23.6",
73
  "@unocss/reset": "^0.61.9",
pages/api/system/git-info.ts ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextApiRequest, NextApiResponse } from 'next';
2
+ import { execSync } from 'child_process';
3
+
4
+ export default async function handler(req: NextApiRequest, res: NextApiResponse) {
5
+ if (req.method !== 'GET') {
6
+ return res.status(405).json({ message: 'Method not allowed' });
7
+ }
8
+
9
+ try {
10
+ // Get git information using git commands
11
+ const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
12
+ const commit = execSync('git rev-parse HEAD').toString().trim();
13
+ const commitTime = execSync('git log -1 --format=%cd').toString().trim();
14
+ const author = execSync('git log -1 --format=%an').toString().trim();
15
+ const remoteUrl = execSync('git config --get remote.origin.url').toString().trim();
16
+
17
+ const gitInfo = {
18
+ branch,
19
+ commit,
20
+ commitTime,
21
+ author,
22
+ remoteUrl,
23
+ };
24
+
25
+ res.status(200).json(gitInfo);
26
+ } catch (error) {
27
+ console.error('Failed to get git information:', error);
28
+ res.status(500).json({ message: 'Failed to get git information' });
29
+ }
30
+ }
pnpm-lock.yaml CHANGED
@@ -122,6 +122,9 @@ importers:
122
  '@remix-run/cloudflare-pages':
123
  specifier: ^2.15.0
124
  version: 2.15.0(@cloudflare/[email protected])([email protected])
 
 
 
125
  '@remix-run/react':
126
  specifier: ^2.15.0
127
@@ -241,10 +244,10 @@ importers:
241
  version: 4.0.0
242
  remix-island:
243
  specifier: ^0.2.0
244
245
  remix-utils:
246
  specifier: ^7.7.0
247
248
  shiki:
249
  specifier: ^1.24.0
250
  version: 1.24.0
@@ -2294,6 +2297,15 @@ packages:
2294
  typescript:
2295
  optional: true
2296
 
 
 
 
 
 
 
 
 
 
2297
  '@remix-run/[email protected]':
2298
  resolution: {integrity: sha512-puqDbi9N/WfaUhzDnw2pACXtCB7ukrtFJ9ILwpEuhlaTBpjefifJ89igokW+tt1ePphIFMivAm/YspcbZdCQsA==}
2299
  engines: {node: '>=18.0.0'}
@@ -2318,6 +2330,15 @@ packages:
2318
  typescript:
2319
  optional: true
2320
 
 
 
 
 
 
 
 
 
 
2321
  '@remix-run/[email protected]':
2322
  resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==}
2323
 
@@ -8640,6 +8661,18 @@ snapshots:
8640
  optionalDependencies:
8641
  typescript: 5.7.2
8642
 
 
 
 
 
 
 
 
 
 
 
 
 
8643
8644
  dependencies:
8645
  '@remix-run/router': 1.21.0
@@ -8666,6 +8699,18 @@ snapshots:
8666
  optionalDependencies:
8667
  typescript: 5.7.2
8668
 
 
 
 
 
 
 
 
 
 
 
 
 
8669
  '@remix-run/[email protected]':
8670
  dependencies:
8671
  '@remix-run/web-stream': 1.1.0
@@ -12680,19 +12725,19 @@ snapshots:
12680
  mdast-util-to-markdown: 2.1.2
12681
  unified: 11.0.5
12682
 
12683
12684
  dependencies:
12685
12686
- '@remix-run/server-runtime': 2.15.0([email protected])
12687
  react: 18.3.1
12688
  react-dom: 18.3.1([email protected])
12689
 
12690
12691
  dependencies:
12692
  type-fest: 4.30.0
12693
  optionalDependencies:
12694
  '@remix-run/cloudflare': 2.15.0(@cloudflare/[email protected])([email protected])
12695
- '@remix-run/node': 2.15.0([email protected])
12696
12697
  '@remix-run/router': 1.21.0
12698
  react: 18.3.1
 
122
  '@remix-run/cloudflare-pages':
123
  specifier: ^2.15.0
124
  version: 2.15.0(@cloudflare/[email protected])([email protected])
125
+ '@remix-run/node':
126
+ specifier: ^2.15.2
127
+ version: 2.15.2([email protected])
128
  '@remix-run/react':
129
  specifier: ^2.15.0
130
 
244
  version: 4.0.0
245
  remix-island:
246
  specifier: ^0.2.0
247
248
  remix-utils:
249
  specifier: ^7.7.0
250
251
  shiki:
252
  specifier: ^1.24.0
253
  version: 1.24.0
 
2297
  typescript:
2298
  optional: true
2299
 
2300
+ '@remix-run/[email protected]':
2301
+ resolution: {integrity: sha512-NS/h5uxje7DYCNgcKqKAiUhf0r2HVnoYUBWLyIIMmCUP1ddWurBP6xTPcWzGhEvV/EvguniYi1wJZ5+X8sonWw==}
2302
+ engines: {node: '>=18.0.0'}
2303
+ peerDependencies:
2304
+ typescript: ^5.1.0
2305
+ peerDependenciesMeta:
2306
+ typescript:
2307
+ optional: true
2308
+
2309
  '@remix-run/[email protected]':
2310
  resolution: {integrity: sha512-puqDbi9N/WfaUhzDnw2pACXtCB7ukrtFJ9ILwpEuhlaTBpjefifJ89igokW+tt1ePphIFMivAm/YspcbZdCQsA==}
2311
  engines: {node: '>=18.0.0'}
 
2330
  typescript:
2331
  optional: true
2332
 
2333
+ '@remix-run/[email protected]':
2334
+ resolution: {integrity: sha512-OqiPcvEnnU88B8b1LIWHHkQ3Tz2GDAmQ1RihFNQsbrFKpDsQLkw0lJlnfgKA/uHd0CEEacpfV7C9qqJT3V6Z2g==}
2335
+ engines: {node: '>=18.0.0'}
2336
+ peerDependencies:
2337
+ typescript: ^5.1.0
2338
+ peerDependenciesMeta:
2339
+ typescript:
2340
+ optional: true
2341
+
2342
  '@remix-run/[email protected]':
2343
  resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==}
2344
 
 
8661
  optionalDependencies:
8662
  typescript: 5.7.2
8663
 
8664
8665
+ dependencies:
8666
+ '@remix-run/server-runtime': 2.15.2([email protected])
8667
+ '@remix-run/web-fetch': 4.4.2
8668
+ '@web3-storage/multipart-parser': 1.0.0
8669
+ cookie-signature: 1.2.2
8670
+ source-map-support: 0.5.21
8671
+ stream-slice: 0.1.2
8672
+ undici: 6.21.0
8673
+ optionalDependencies:
8674
+ typescript: 5.7.2
8675
+
8676
8677
  dependencies:
8678
  '@remix-run/router': 1.21.0
 
8699
  optionalDependencies:
8700
  typescript: 5.7.2
8701
 
8702
8703
+ dependencies:
8704
+ '@remix-run/router': 1.21.0
8705
+ '@types/cookie': 0.6.0
8706
+ '@web3-storage/multipart-parser': 1.0.0
8707
+ cookie: 0.6.0
8708
+ set-cookie-parser: 2.7.1
8709
+ source-map: 0.7.4
8710
+ turbo-stream: 2.4.0
8711
+ optionalDependencies:
8712
+ typescript: 5.7.2
8713
+
8714
  '@remix-run/[email protected]':
8715
  dependencies:
8716
  '@remix-run/web-stream': 1.1.0
 
12725
  mdast-util-to-markdown: 2.1.2
12726
  unified: 11.0.5
12727
 
12728
12729
  dependencies:
12730
12731
+ '@remix-run/server-runtime': 2.15.2([email protected])
12732
  react: 18.3.1
12733
  react-dom: 18.3.1([email protected])
12734
 
12735
12736
  dependencies:
12737
  type-fest: 4.30.0
12738
  optionalDependencies:
12739
  '@remix-run/cloudflare': 2.15.0(@cloudflare/[email protected])([email protected])
12740
+ '@remix-run/node': 2.15.2([email protected])
12741
12742
  '@remix-run/router': 1.21.0
12743
  react: 18.3.1