website

#astro#js#html#css

git clone https://git.pyrossh.dev/website

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


831f1f7 — pyrossh 2025-06-06T21:41:03+05:30
fix readmes

Generated files not shown: bun.lock

astro.config.mjs CHANGED
@@ -13,6 +13,7 @@ export default defineConfig({
13
13
  sitemap(),
14
14
  ],
15
15
  experimental: {
16
+ // csp: true,
16
17
  fonts: [{
17
18
  provider: fontProviders.google(),
18
19
  name: "Roboto",
infra/main.tf CHANGED
@@ -36,23 +36,9 @@ resource "aws_s3_bucket" "website" {
36
36
  bucket = "pyrossh-website"
37
37
  }
38
38
 
39
- # resource "aws_s3_bucket_acl" "website" {
39
+ resource "aws_s3_bucket" "repos_bucket" {
40
- # bucket = aws_s3_bucket.website.id
41
- # acl = "private"
42
- # }
43
-
44
- # resource "aws_s3_bucket_website_configuration" "s3_bucket" {
45
- # bucket = aws_s3_bucket.website.id
46
-
47
- # index_document {
48
- # suffix = "index.html"
49
- # }
50
-
51
- # error_document {
52
- # key = "error.html"
40
+ bucket = "pyrossh-repos"
53
- # }
54
-
55
- # }
41
+ }
56
42
 
57
43
  resource "aws_s3_bucket_public_access_block" "website_public_access" {
58
44
  bucket = aws_s3_bucket.website.id
@@ -83,7 +69,9 @@ data "aws_iam_policy_document" "cloudfront_oac_access" {
83
69
 
84
70
  resources = [
85
71
  aws_s3_bucket.website.arn,
86
- "${aws_s3_bucket.website.arn}/*"
72
+ "${aws_s3_bucket.website.arn}/*",
73
+ aws_s3_bucket.repos_bucket,
74
+ "${aws_s3_bucket.repos_bucket.arn}/*"
87
75
  ]
88
76
 
89
77
  condition {
@@ -131,6 +119,11 @@ resource "aws_cloudfront_distribution" "s3_distribution" {
131
119
  origin_id = aws_s3_bucket.website.bucket_regional_domain_name
132
120
  origin_access_control_id = aws_cloudfront_origin_access_control.website.id
133
121
  }
122
+ origin {
123
+ domain_name = aws_s3_bucket.repos_bucket.bucket_regional_domain_name
124
+ origin_id = aws_s3_bucket.repos_bucket.bucket_regional_domain_name
125
+ origin_access_control_id = aws_cloudfront_origin_access_control.website.id
126
+ }
134
127
  enabled = true
135
128
  is_ipv6_enabled = true
136
129
  aliases = ["pyrossh.dev"]
@@ -164,6 +157,27 @@ resource "aws_cloudfront_distribution" "s3_distribution" {
164
157
  function_arn = aws_cloudfront_function.subdirectory_redirector.arn
165
158
  }
166
159
  }
160
+
161
+ ordered_cache_behavior {
162
+ path_pattern = "/d/*"
163
+ allowed_methods = ["GET", "HEAD"]
164
+ cached_methods = ["GET", "HEAD"]
165
+ target_origin_id = aws_s3_bucket.repos_bucket.bucket_regional_domain_name
166
+
167
+ forwarded_values {
168
+ query_string = false
169
+ cookies {
170
+ forward = "none"
171
+ }
172
+ }
173
+
174
+ min_ttl = 0
175
+ default_ttl = 86400
176
+ max_ttl = 31536000
177
+ compress = true
178
+ viewer_protocol_policy = "redirect-to-https"
179
+ }
180
+
167
181
  price_class = "PriceClass_All"
168
182
  restrictions {
169
183
  geo_restriction {
package.json CHANGED
@@ -5,20 +5,22 @@
5
5
  "scripts": {
6
6
  "tauri": "tauri",
7
7
  "dev": "astro dev",
8
- "build": "astro build"
8
+ "build": "astro build",
9
+ "android": "tauri android dev",
10
+ "ios": "tauri ios dev"
9
11
  },
10
12
  "dependencies": {
11
13
  "@appzic/astro-reset-css": "^1.2.0",
12
- "@astrojs/mdx": "^4.2.5",
14
+ "@astrojs/mdx": "^4.3.0",
13
- "@astrojs/rss": "^4.0.11",
15
+ "@astrojs/rss": "^4.0.12",
14
- "@astrojs/sitemap": "^3.3.1",
16
+ "@astrojs/sitemap": "^3.4.1",
15
- "astro": "^5.7.5",
17
+ "astro": "^5.9.0",
16
18
  "simple-git": "^3.27.0",
17
19
  "timeago.js": "^4.0.2"
18
20
  },
19
21
  "devDependencies": {
20
- "@tauri-apps/cli": "^2",
21
22
  "@playwright/test": "^1.52.0",
23
+ "@tauri-apps/cli": "^2",
22
24
  "@types/node": "^22.15.3"
23
25
  }
24
- }
26
+ }
server.js ADDED
@@ -0,0 +1,128 @@
1
+ import { Parser } from 'node-sql-parser';
2
+ import { PutObjectCommand, S3Client, GetObjectCommand, paginateListObjectsV2 } from "@aws-sdk/client-s3";
3
+
4
+ const bucketName = "";
5
+
6
+ // import { S3Client } from "bun";
7
+ // const client = new S3Client({
8
+ // region: "ap-south-1",
9
+ // bucket: "",
10
+ // accessKeyId: "",
11
+ // secretAccessKey: "",
12
+ // endpoint: "https://s3express-aps1-az1.ap-south-1.amazonaws.com",
13
+ // });
14
+ // const s3file = client.file("123.json");
15
+ // await s3file.write(JSON.stringify({ hello: "world" }));
16
+
17
+ // const data = await s3file.json()
18
+ // console.log(data);
19
+
20
+ // const client = new S3Client({});
21
+ // const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
22
+ // for (const i of arr) {
23
+ // await client.send(new PutObjectCommand({
24
+ // Bucket: bucketName,
25
+ // Key: `posts/${i}.json`,
26
+ // ContentType: "application/json",
27
+ // Body: JSON.stringify({ id: `${i}`, data: `hello '${i}' world` }),
28
+ // }));
29
+ // }
30
+
31
+ // If-None-Match: * if it doesn't exist 409 - ConditionalRequestConflict 412 Precondition Failed
32
+ // If-Match: etag checks if etag is same CAS 409 - ConditionalRequestConflict 412 Precondition Failed
33
+
34
+ const getObjectName = (name) => name.split("::")[2];
35
+
36
+ const client = new S3Client({});
37
+
38
+ const getAllS3Files = async (bucketName, tableName) => {
39
+ const totalFiles = [];
40
+ for await (const data of paginateListObjectsV2({ client }, { Bucket: bucketName, Prefix: `${tableName}/` })) {
41
+ totalFiles.push(...(data.Contents ?? []));
42
+ }
43
+ return totalFiles;
44
+ };
45
+
46
+ const sql = async (query) => {
47
+ const parser = new Parser();
48
+ const { tableList, columnList, ast } = parser.parse(query, {
49
+ database: "Hive",
50
+ // type: 'table',
51
+ parseOptions: {
52
+ includeLocations: true
53
+ }
54
+ });
55
+ // console.log(ast);
56
+ // console.log(JSON.stringify(ast, 2, 2));
57
+ // console.log("tableName", tableName);
58
+ const tableName = getObjectName(tableList[0]);
59
+ // if (ast.type === "select") {
60
+ // }
61
+ const contents = await getAllS3Files(bucketName, tableName)
62
+ return await Promise.all(contents.map((r) => {
63
+ return client.send(new GetObjectCommand({ Bucket: bucketName, Key: r.Key, }))
64
+ .then((rr) => rr.Body.transformToString())
65
+ .then(JSON.parse)
66
+ }));
67
+ }
68
+
69
+ const rows = await sql('SELECT * FROM posts LIMIT 10');
70
+ // const rows = await sql("INSERT INTO posts(id, data) VALUES ('11', 'body');");
71
+ console.log(rows);
72
+
73
+ // const rows = await sql(`
74
+ // CREATE TABLE struct_test(
75
+ // property_id INT
76
+ // )
77
+ // `);
78
+
79
+ // console.log(rows);
80
+ // const resp = await parseQuery("SELECT * FROM POSTS");
81
+ // resp.stmts[0].stmt.SelectStmt.fromClause
82
+ // console.log("stmts", stmts);
83
+
84
+ // Data Definition Language (DDL): CREATE, ALTER, DROP
85
+ // Data Manipulation Language (DML): INSERT, UPDATE, DELETE, MERGE
86
+ // Data Query Language (DQL): SELECT
87
+ // Data Control Language (DCL): GRANT, REVOKE
88
+
89
+ // TABLES/VIEWS/INDEX
90
+
91
+
92
+
93
+ //
94
+ // import { gluesql } from 'gluesql';
95
+
96
+ // const db = gluesql();
97
+
98
+ // async function run() {
99
+ // await db.query(`
100
+ // CREATE TABLE User (id INTEGER, name TEXT);
101
+ // CREATE TABLE Device (name TEXT, userId INTEGER);
102
+ // INSERT INTO User VALUES
103
+ // (1, 'glue'), (2, 'sticky'), (3, 'watt');
104
+ // INSERT INTO Device VALUES
105
+ // ('Phone', 1), ('Mic', 1), ('Monitor', 3),
106
+ // ('Mouse', 2), ('Touchpad', 2);
107
+ // `);
108
+
109
+ // let sql;
110
+
111
+ // sql = 'SHOW TABLES;';
112
+ // const [{ tables }] = await db.query(sql);
113
+ // console.log(`\n[Query]\n${sql}`);
114
+ // console.table(tables);
115
+
116
+ // sql = `
117
+ // SELECT
118
+ // u.name as user,
119
+ // d.name as device
120
+ // FROM User u
121
+ // JOIN Device d ON u.id = d.userId
122
+ // `.trim().replace(/[ ]{4}/g, '');
123
+ // const [{ rows }] = await db.query(sql);
124
+ // console.log(`\n[Query]\n${sql}`);
125
+ // console.table(rows);
126
+ // }
127
+
128
+ // run();
src/components/Commit.astro CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { format } from "timeago.js";
3
3
 
4
- const { title, author_name, hash, date, message } = Astro.props;
4
+ const { title, author_name, hash, date, message, refs } = Astro.props;
5
5
  ---
6
6
 
7
7
  <div class="event">
@@ -11,6 +11,7 @@ const { title, author_name, hash, date, message } = Astro.props;
11
11
  </a>
12
12
  — {author_name}
13
13
  <small class="pull-right">
14
+ <h3>{refs}</h3>
14
15
  <a href={`/repos/${title}/logs?from=??`} rel="nofollow">
15
16
  <span title={date}>
16
17
  {format(date)}
src/content.config.ts CHANGED
@@ -1,24 +1,38 @@
1
- import fs from "fs";
1
+ import fs from "fs/promises";
2
2
  import { simpleGit } from "simple-git";
3
3
  import { glob } from 'astro/loaders';
4
4
  import { defineCollection, z } from 'astro:content';
5
5
  import { REPOS } from './consts';
6
6
 
7
+
8
+ // https://pyrossh.dev/downloads/rp2350/refs/heads/master/repo.zip
9
+ // https://pyrossh-repos.s3.ap-south-1.amazonaws.com/rp2350/refs/heads/master/repo.zip
10
+
11
+ async function checkFileExists(filePath: string) {
12
+ try {
13
+ await fs.stat(filePath);
14
+ return true; // File exists
15
+ } catch (error) {
16
+ return false; // File does not exist or cannot be accessed
17
+ }
18
+ }
19
+
7
20
  export const collections = {
8
21
  repos: defineCollection({
9
22
  loader: {
10
23
  name: "loader",
11
- load: async (ctx) => {
24
+ load: async ({ renderMarkdown, store }) => {
12
25
  for (const r of REPOS) {
13
26
  const repoPath = `/Users/pyrossh/Code/pyrossh/${r.title}`;
14
27
  const readmePath = repoPath + "/README.md";
15
28
  console.log("loading repo " + repoPath)
16
29
  const git = simpleGit(repoPath)
17
- const commits = await git.log();
18
- const tags = await git.tag();
19
- const branches = await git.branchLocal();
30
+ const commits = await git.log(["--branches", "--tags"]);
20
-
31
+ const readmeContent = await checkFileExists(readmePath) ? await renderMarkdown(await fs.readFile(readmePath, 'utf-8')) : {
32
+ html: '',
33
+ metadata: {},
34
+ }
21
- ctx.store.set({
35
+ store.set({
22
36
  id: r.title,
23
37
  data: {
24
38
  title: r.title,
@@ -31,12 +45,8 @@ export const collections = {
31
45
  date: item.date,
32
46
  refs: item.refs,
33
47
  })),
34
- branches: branches.all,
35
- tags: tags,
36
48
  },
37
- rendered: {
49
+ rendered: readmeContent,
38
- html: '', // fs.existsSync(readmePath) ? await (await import(readmePath)).compiledContent() : "",
39
- }
40
50
  });
41
51
  }
42
52
  },
src/layouts/Base.astro CHANGED
@@ -1,11 +1,11 @@
1
1
  ---
2
+ import "./Base.css"; // Note: This has to be first always
2
3
  import { ClientRouter } from "astro:transitions";
3
4
  import { Font } from "astro:assets";
4
5
  import ResetCSS from "@appzic/astro-reset-css";
5
6
  import Header from "@/components/Header.astro";
6
7
  import Footer from "@/components/Footer.astro";
7
8
  import Wrapper from "@/components/Wrapper.astro";
8
- import "./Base.css";
9
9
 
10
10
  interface Props {
11
11
  title: string;
src/pages/index.module.css CHANGED
@@ -1,5 +1,5 @@
1
1
  h2 {
2
- font-size: 1.5rem;
2
+ font-size: 16pt;
3
3
  font-weight: 600;
4
4
  }
5
5
 
@@ -35,13 +35,19 @@ section {
35
35
 
36
36
  .title {
37
37
  font-size: 1.875rem;
38
- /* text-3xl */
39
38
  line-height: 2.25rem;
40
- /* text-3xl */
41
39
  font-weight: 700;
42
- /* font-bold */
43
40
  margin-bottom: 1rem;
41
+ }
42
+
43
+ .firstSection {
44
+ display: flex;
44
- /* mb-4 */
45
+ flex-direction: column;
46
+ }
47
+
48
+ .firstPara {
49
+ display: flex;
50
+ flex-direction: row;
45
51
  }
46
52
 
47
53
  .linkUnderline {
src/pages/repos/[...slug]/index.astro CHANGED
@@ -39,30 +39,19 @@ const { Content } = await render(Astro.props);
39
39
  </h3>
40
40
  <h3>
41
41
  wget
42
- <a
42
+ <a href={`https://pyrossh.dev/zips/${title}.zip`}>
43
+ https://pyrossh.dev/zips/{title}.zip
43
- href={`https://pyrossh-repos.s3.ap-south-1.amazonaws.com/${title}/refs/heads/master/repo.zip`}
44
+ <!-- https://pyrossh-repos.s3.ap-south-1.amazonaws.com/rp2350/refs/heads/master/repo.zip -->
44
- >
45
- https://pyrossh-repos.s3.ap-south-1.amazonaws.com/{
46
- title
47
- }/refs/heads/master/repo.zip
48
45
  </a>
49
46
  </h3>
50
47
  </div>
51
48
  <div class={styles.nav}>
52
49
  <div>
53
- <a href={`${title}/commits`}>Commits (view all)</a>
50
+ <a href={`/repos/${title}/commits`}>Commits</a>
54
51
  </div>
55
52
  <div>|</div>
56
53
  <div>
57
- <a class="nav-link" href={`/${title}/files`}>Files</a>
54
+ <a class="nav-link" href={`/repos/${title}/files`}>Files</a>
58
- </div>
59
- <div>|</div>
60
- <div>
61
- <a class="nav-link" href={`/${title}/branches`}>Branches</a>
62
- </div>
63
- <div>|</div>
64
- <div>
65
- <a class="nav-link" href={`/${title}/tags`}>Tags</a>
66
55
  </div>
67
56
  </div>
68
57
  <div class={styles.summary}>
src/pages/repos/[...slug]/index.module.css CHANGED
@@ -57,9 +57,8 @@
57
57
  a {
58
58
  font-size: 12pt;
59
59
  padding-right: 0.5rem;
60
- color: #65686a;
60
+ color: #3395ff;
61
61
  cursor: pointer;
62
- color: #ced4da;
63
62
  }
64
63
  }
65
64