-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
310 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
/// <reference types="astro/client" /> | ||
import type { KVNamespace, R2Bucket } from "@cloudflare/workers-types"; | ||
import type { DirectoryRuntime } from "@astrojs/cloudflare"; | ||
|
||
interface ImportMetaEnv { | ||
readonly PUBLIC_GIT_SHA: string; | ||
} | ||
type ENV = { | ||
kv: KVNamespace; | ||
r2: R2Bucket; | ||
}; | ||
|
||
interface ImportMeta { | ||
readonly env: ImportMetaEnv; | ||
declare namespace App { | ||
interface Locals extends DirectoryRuntime { | ||
runtime: DirectoryRuntime & { env: { | ||
kv: KVNamespace; | ||
r2: R2Bucket; | ||
} }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// ABSOLUTE LEGEND: https://github.com/sveltejs/kit/issues/4292#issuecomment-1550596497 | ||
type StorageOptionsMemory = { | ||
type: 'memory'; | ||
}; | ||
|
||
type StorageOptionsFile = { | ||
type: 'file'; | ||
path: string; | ||
}; | ||
|
||
export type StorageOptions = StorageOptionsMemory | StorageOptionsFile; | ||
|
||
export const createCache = async (storageOptions: StorageOptions) => { | ||
const { Cache } = await import('@miniflare/cache'); | ||
|
||
if (storageOptions.type === 'memory') { | ||
const { MemoryStorage } = await import('@miniflare/storage-memory'); | ||
return new Cache(new MemoryStorage()); | ||
} else if (storageOptions.type === 'file') { | ||
const { FileStorage } = await import('@miniflare/storage-file'); | ||
return new Cache(new FileStorage(storageOptions.path)); | ||
} | ||
|
||
throw new Error('StorageType not found'); | ||
}; | ||
|
||
export const createD1 = async (storageOptions: StorageOptions) => { | ||
const { createSQLiteDB } = await import('@miniflare/shared'); | ||
const { D1Database, D1DatabaseAPI } = await import('@miniflare/d1'); | ||
|
||
if (storageOptions.type === 'memory') { | ||
const sqliteDb = await createSQLiteDB(':memory:'); | ||
return new D1Database(new D1DatabaseAPI(sqliteDb)); | ||
} else if (storageOptions.type === 'file') { | ||
const sqliteDb = await createSQLiteDB(storageOptions.path); | ||
return new D1Database(new D1DatabaseAPI(sqliteDb)); | ||
} | ||
|
||
throw new Error('StorageType not found'); | ||
}; | ||
|
||
export const createR2 = async (storageOptions: StorageOptions) => { | ||
const { R2Bucket } = await import('@miniflare/r2'); | ||
|
||
if (storageOptions.type === 'memory') { | ||
const { MemoryStorage } = await import('@miniflare/storage-memory'); | ||
return new R2Bucket(new MemoryStorage()); | ||
} else if (storageOptions.type === 'file') { | ||
const { FileStorage } = await import('@miniflare/storage-file'); | ||
return new R2Bucket(new FileStorage(storageOptions.path)); | ||
} | ||
|
||
throw new Error('StorageType not found'); | ||
}; | ||
|
||
export const createKV = async (storageOptions: StorageOptions) => { | ||
const { KVNamespace } = await import('@miniflare/kv'); | ||
|
||
if (storageOptions.type === 'memory') { | ||
const { MemoryStorage } = await import('@miniflare/storage-memory'); | ||
return new KVNamespace(new MemoryStorage()); | ||
} else if (storageOptions.type === 'file') { | ||
const { FileStorage } = await import('@miniflare/storage-file'); | ||
return new KVNamespace(new FileStorage(storageOptions.path)); | ||
} | ||
|
||
throw new Error('StorageType not found'); | ||
}; | ||
|
||
export const createDOStorage = async (storageOptions: StorageOptions) => { | ||
const { DurableObjectStorage } = await import('@miniflare/durable-objects'); | ||
|
||
if (storageOptions.type === 'memory') { | ||
const { MemoryStorage } = await import('@miniflare/storage-memory'); | ||
return new DurableObjectStorage(new MemoryStorage()); | ||
} else if (storageOptions.type === 'file') { | ||
const { FileStorage } = await import('@miniflare/storage-file'); | ||
return new DurableObjectStorage(new FileStorage(storageOptions.path)); | ||
} | ||
|
||
throw new Error('StorageType not found'); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { createKV, createR2 } from './lib/server/miniflare'; | ||
import { defineMiddleware } from "astro:middleware"; | ||
|
||
export const onRequest = defineMiddleware(async (context, next) => { | ||
if (import.meta.env.DEV) { | ||
context.locals.runtime = { | ||
env: { | ||
kv: await createKV({ type: 'file', path: '.mf/kv-counter' }), | ||
r2: await createR2({ type: 'file', path: '.mf/r2-bucket' }), | ||
}, | ||
}; | ||
} | ||
|
||
return next(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { errorNoData } from "@utils/response"; | ||
import { parseParams } from "@utils/url"; | ||
|
||
import type { APIContext } from "astro"; | ||
|
||
export async function GET(context: APIContext) { | ||
const { reference, error } = parseParams(context.params); | ||
if (error != null) { | ||
return error; | ||
} | ||
|
||
let response: typeof Response; | ||
|
||
// DB Query | ||
const data = await context.locals?.runtime?.env.r2.get(reference); | ||
if (data == null) { | ||
response = errorNoData(); | ||
} else { | ||
response = new Response(data.body); | ||
} | ||
|
||
return response; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { errorNoData } from "@utils/response"; | ||
import { parseParams } from "@utils/url"; | ||
import type { APIContext } from "astro"; | ||
|
||
export async function GET(context: APIContext) { | ||
const { name, reference } = parseParams(context.params); | ||
|
||
// DB Query | ||
let dbKey: string; | ||
if (reference.includes("sha256")) { | ||
dbKey = reference; | ||
} else { | ||
dbKey = name + "/" + reference; | ||
} | ||
|
||
// Potential for readable stream and no waiting | ||
const data = await context.locals?.runtime?.env.kv.get(dbKey); | ||
if (!data) { | ||
return errorNoData(); | ||
} | ||
|
||
// Set body of response | ||
let body = ""; | ||
if (context.request.method !== "HEAD") { | ||
body = data; | ||
} | ||
|
||
const resp = new Response(body); | ||
|
||
// Set docker-content-digest header | ||
let shaTag = reference; | ||
if (!reference.includes("sha256")) { | ||
shaTag = data; | ||
} | ||
resp.headers.set("docker-content-digest", shaTag); | ||
|
||
// Set Content-Type header | ||
let contentType = ""; | ||
if (data.startsWith("{")) { | ||
contentType = JSON.parse(data)?.mediaType; | ||
} | ||
if (!contentType) { | ||
contentType = "application/vnd.docker.distribution.manifest.list.v2+json"; | ||
} | ||
resp.headers.set("Content-Type", contentType); | ||
resp.headers.set("Content-Length", data.length.toString()); | ||
|
||
return resp; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// import type { Env} from "../../../env.d.ts" | ||
|
||
let authHeader: string; | ||
|
||
async function getAuth() { | ||
const resp = await fetch( | ||
"https://auth.docker.io/token?scope=repository%3Alibrary%2Fhello-world%3Apull&service=registry.docker.io" | ||
); | ||
return "Bearer " + ((await resp.json()) as Record<string, string>).token; | ||
} | ||
|
||
async function seedTag(env: Env, tag: string) { | ||
// Get hello-world:latest | ||
const label_req = await fetch( | ||
"https://registry-1.docker.io/v2/library/hello-world/manifests/latest", | ||
{ | ||
method: "HEAD", | ||
headers: { | ||
Authorization: authHeader, | ||
Accept: "application/vnd.docker.distribution.manifest.list.v2+json", | ||
}, | ||
} | ||
); | ||
|
||
if (label_req.status != 200) { | ||
console.error("Tag does not exist", label_req.statusText); | ||
return; | ||
} | ||
|
||
console.log(await label_req.text()); | ||
|
||
const sha_hash = await label_req.headers.get("docker-content-digest")!; | ||
await env.kv.put(tag, sha_hash); | ||
console.log(sha_hash); | ||
seedOS(env, sha_hash); | ||
} | ||
|
||
async function seedOS(env: Env, hash: string) { | ||
// Get sha256: | ||
const label_req = await fetch( | ||
`https://registry-1.docker.io/v2/library/hello-world/manifests/${hash}`, | ||
{ | ||
method: "GET", | ||
headers: { | ||
Authorization: authHeader, | ||
Accept: "application/vnd.docker.distribution.manifest.list.v2+json", | ||
}, | ||
} | ||
); | ||
|
||
if (label_req.status != 200) { | ||
console.error("OS list does not exist", label_req.statusText); | ||
return; | ||
} | ||
|
||
const os_list = await label_req.text(); | ||
await env.kv.put(hash, os_list); | ||
const os_json = JSON.parse(os_list) as Record<any, any>; | ||
|
||
for (var key in os_json.manifests) { | ||
seedImage(env, os_json.manifests[key].digest); | ||
} | ||
} | ||
|
||
async function seedImage(env: Env, hash: string) { | ||
// Get sha256: | ||
const label_req = await fetch( | ||
`https://registry-1.docker.io/v2/library/hello-world/manifests/${hash}`, | ||
{ | ||
method: "GET", | ||
headers: { | ||
Authorization: authHeader, | ||
Accept: "application/vnd.docker.distribution.manifest.v2+json", | ||
}, | ||
} | ||
); | ||
|
||
if (label_req.status != 200) { | ||
console.error("OS list does not exist", label_req.statusText); | ||
return; | ||
} | ||
|
||
const os_list = await label_req.text(); | ||
await env.kv.put(hash, os_list); | ||
const image_json = JSON.parse(os_list) as Record<any, any>; | ||
|
||
seedBlob(env, image_json.config.digest); | ||
for (var key in image_json.layers) { | ||
seedBlob(env, image_json.layers[key].digest); | ||
} | ||
} | ||
|
||
async function seedBlob(env: Env, hash: string) { | ||
const req = await fetch( | ||
`https://registry-1.docker.io/v2/library/hello-world/blobs/${hash}`, | ||
{ | ||
headers: { | ||
Authorization: authHeader, | ||
}, | ||
} | ||
); | ||
|
||
if (req.status != 200) { | ||
console.error("Seed not 200", req.statusText); | ||
} | ||
|
||
await env.r2.put(hash, await req.arrayBuffer()); | ||
} | ||
|
||
export const GET: APIRoute = async (context) => { | ||
if (!import.meta.env.DEV) { | ||
return new Response("", { status: 404 }); | ||
} | ||
|
||
console.log("Seeding..."); | ||
authHeader = await getAuth(); | ||
await seedTag(context.locals?.runtime?.env, "hello-world:latest"); | ||
console.log("DONE Seeding"); | ||
|
||
return new Response("DONE"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
export const prerender = true; | ||
|
||
export function get(): Record<string, string> { | ||
return { | ||
body: import.meta.env.PUBLIC_GIT_SHA, | ||
}; | ||
export const GET: APIRoute = async () => { | ||
// return new Response(import.meta.env.PUBLIC_GIT_SHA); | ||
return new Response("todo!()"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters