Avatar

devdoshi

10 public vals
Joined January 12, 2023
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { swaggerUI } from "npm:@hono/swagger-ui";
import { z } from "npm:@hono/zod-openapi";
import { createRoute, OpenAPIHono } from "npm:@hono/zod-openapi";
import { html } from "npm:hono/html";
const ParamsSchema = z.object({
id: z
.string()
.min(3)
.openapi({
param: {
name: "id",
in: "path",
},
example: "1212121",
}),
});
const UserSchema = z
.object({
id: z.string().openapi({
example: "123",
}),
name: z.string().openapi({
example: "John Doe",
}),
age: z.number().openapi({
example: 42,
}),
})
.openapi("User");
const route = createRoute({
method: "get",
path: "/users/{id}",
request: {
params: ParamsSchema,
},
responses: {
200: {
content: {
"application/json": {
schema: UserSchema,
},
},
description: "Retrieve the user",
},
},
});
const app = new OpenAPIHono();
app.get("/", c => c.html(html`Try going to <a href="/ui">/ui</a>`));
app.openapi(route, (c) => {
const { id } = c.req.valid("param");
return c.json({
id,
age: 20,
name: "Ultra-man",
});
});
// The OpenAPI documentation will be available at /doc
app.doc("/doc", {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "My API",
},
});
app.get("/ui", swaggerUI({ url: "/doc" }));
export default app.fetch;
1
2
3
4
5
6
export let handleFetchTextResponse = async function (response: Response) {
if (response.ok) {
return await response.text();
}
throw new Error(await response.text());
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { fetch } from "https://esm.town/v/std/fetch";
import { handleFetchTextResponse } from "https://esm.town/v/devdoshi/handleFetchTextResponse";
export let subscribeToPush = async (req: express.Request, res: express.Response) => {
const routes = {
POST: {
"/subscriptions": (req: express.Request, res: express.Response) => {
res.json({ yay: true });
},
},
GET: {
"/": async (req: express.Request, res: express.Response) => {
const response = await fetch(
`https://raw.githubusercontent.com/pirminrehm/service-worker-web-push-example/main/client${
req.path.substring(`/ui`.length)
}`,
).then(handleFetchTextResponse);
const contentTypeMapping = {
"html": "text/html",
"js": "application/javascript",
"css": "text/css",
};
const extensionIndex = req.path.lastIndexOf(".");
const extension = req.path.substring(extensionIndex + 1);
console.log({ extensionIndex, extension });
res.set("content-type", contentTypeMapping[extension] || "text/plain")
.send(response);
},
},
};
try {
const handler = routes[req.method][req.path];
if (handler) {
return handler(req, res);
}
const handlers = routes[req.method];
const partialMatch = Object.keys(handlers).find((k) =>
req.path.startsWith(k)
);
if (partialMatch) {
return handlers[partialMatch](req, res);
}
throw new Error("could not find a matching route handler");
}
catch (e) {
console.error(e);
return res.status(400).json({
path: req.path,
method: req.method,
error: e.message,
});
}
};

Usage:

async (rawInput) => {
  const validators = await @devdoshi.validators();
  const inputSchema = validators.inputSchema();
  const input = inputSchema.safeParse(rawInput);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export const validators = async () => {
const { z } = await import("npm:zod");
const inputSchema = () =>
z.object({
ip: z.string().min(1),
port: z.number(),
securityGroupId: z.string().min(1),
aws: z.object({
secretAccessKey: z.string().min(1),
accessKeyId: z.string().min(1),
region: z.string().min(1),
}),
});
return {
inputSchema,
};
};

Usage:

@devdoshi.authorizeIpIngress({
  securityGroupId: "sg-123",
  ip: "1.2.3.4",
  port: 8080,
  aws: {
    region: "us-east-2",
    secretAccessKey: "hunter2",
    accessKeyId: "ABC123",
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { validators as validators2 } from "https://esm.town/v/devdoshi/validators";
export const authorizeIpIngress = async (rawInput) => {
const validators = await validators2();
const inputSchema = validators.inputSchema();
const input = inputSchema.safeParse(rawInput);
console.log(input.success);
if (input.success) {
try {
const {
EC2Client,
CreateSecurityGroupCommand,
AuthorizeSecurityGroupIngressCommand,
} = await import("https://esm.sh/@aws-sdk/client-ec2");
const { port, ip, aws, securityGroupId } = input.data;
const ec2Client = new EC2Client({
region: aws.region,
credentials: {
accessKeyId: aws.accessKeyId,
secretAccessKey: aws.secretAccessKey,
},
});
const authorizeCommand = new AuthorizeSecurityGroupIngressCommand({
GroupId: securityGroupId,
IpPermissions: [
{
FromPort: port,
ToPort: port,
IpProtocol: "tcp",
IpRanges: [{ CidrIp: `${ip}/32` }],
},
],
});
try {
await ec2Client.send(authorizeCommand);
}
catch (e) {
console.error(e);
if (!e.message.endsWith("already exists")) {
throw new Error(e.message);
}
}
return { success: true };
}
catch (e) {
console.error(e);
return { success: false };
}
}
};
1
2
3
import { exportedKeys } from "https://esm.town/v/devdoshi/exportedKeys";
export const publicKey = () => exportedKeys.publicKey;

I wanted to see if val.town forwards my client IP Address using the x-forwarded-for header, which it does, but cloudflare provides the True-Client-IP header as well. When you run a val on the website, it is actually running from val's servers so it won't come from your client IP. You'll need to copy the express fetch and run that from your client.

1
2
3
4
5
6
7
8
export let whatIsMyIp = (req: express.Request, res: express.Response) => {
const xForwardedFor = req.get("x-forwarded-for");
const ip = req.get("True-Client-IP");
res.json({
ip,
xForwardedFor,
});
};
1
2
3
4
5
6
7
8
9
import { email } from "https://esm.town/v/std/email?v=9";
import { fetchCongressTradeReports } from "https://esm.town/v/claytn/fetchCongressTradeReports?v=3";
export async function congress() {
let text;
fetchCongressTradeReports((reports) => text = reports);
if (text)
await email({ text, subject: "Congress" });
}
1
2
3
4
5
6
let { count } = await import("https://esm.town/v/devdoshi/count");
export function increment() {
count += 1;
return count;
}
1
2
// set by @devdoshi.increment at 2023-01-13T16:06:44.474Z
export let count = 13
Next