Compare commits
	
		
			2 Commits
		
	
	
		
			5337b44b11
			...
			f69e40ae9e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f69e40ae9e | |||
| cece103504 | 
| @ -12,6 +12,7 @@ export * as Path from "https://deno.land/std@0.62.0/path/mod.ts"; | ||||
| export * as FS from "https://deno.land/std@0.62.0/fs/mod.ts"; | ||||
|  | ||||
| export * as Base64 from "https://deno.land/std@0.62.0/encoding/base64.ts"; | ||||
| export * as Hash from "https://deno.land/std@0.62.0/hash/mod.ts"; | ||||
|  | ||||
| export * as Compress from "https://git.stamm.me/Deno/DenReg/raw/branch/master/tar/mod.ts"; | ||||
|  | ||||
| @ -24,6 +25,6 @@ export { | ||||
|    React, | ||||
|    jsx, | ||||
|    Fragment, | ||||
| } from "https://raw.githubusercontent.com/hibas123/jsx-html/master/mod.ts"; | ||||
| } from "https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts"; | ||||
|  | ||||
| export const Datastore = DS; | ||||
|  | ||||
| @ -8,12 +8,21 @@ import db, { IPackage } from "../db.ts"; | ||||
| import { v4 } from "https://deno.land/std/uuid/mod.ts"; | ||||
|  | ||||
| export default function api(g: ABC.Group) { | ||||
|    g.get("/", (ctx) => { | ||||
|       return { version: "1" }; | ||||
|    }); | ||||
|    const cacheControl = (next) => (ctx) => { | ||||
|       ctx.response.headers.set("cache-control", "private"); | ||||
|       next(ctx); | ||||
|    }; | ||||
|  | ||||
|    g.get( | ||||
|       "/", | ||||
|       (ctx) => { | ||||
|          return { version: "1" }; | ||||
|       }, | ||||
|       cacheControl | ||||
|    ); | ||||
|  | ||||
|    // g.post("/getapikey", getApiKey, basicauth("api")); | ||||
|    g.post("/package/:name", uploadPackage, basicauth("api")); | ||||
|    g.post("/package/:name", uploadPackage, cacheControl, basicauth("api")); | ||||
| } | ||||
|  | ||||
| // async function getApiKey(ctx: ABC.Context) { | ||||
| @ -142,7 +151,7 @@ async function uploadPackage(ctx: ABC.Context) { | ||||
|       } | ||||
|       console.log("Setting new live version"); | ||||
|  | ||||
|       //TODO: Better option, since this could error whith multiple upload to the same package | ||||
|       //TODO: Better option, since this could error whith multiple uploads to the same package at the same time | ||||
|       await db.package.update( | ||||
|          { name: packageName }, | ||||
|          { | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| import { ABC } from "../deps.ts"; | ||||
| import { extractPackagePath, getFile } from "../utils.ts"; | ||||
|  | ||||
| const MAX_FIXED_CACHE_AGE = 60 * 60 * 24 * 365; | ||||
| const MAX_FLOATING_CACHE_AGE = 60 * 30; | ||||
|  | ||||
| export default function raw(g: ABC.Group) { | ||||
|    g.get("/:package/*path", async (ctx) => { | ||||
|       console.log(ctx.params, ctx.path); | ||||
| @ -18,7 +21,22 @@ export default function raw(g: ABC.Group) { | ||||
|          packageVersion, | ||||
|          ctx.params.path | ||||
|       ); | ||||
|  | ||||
|       if (packageVersion && result) { | ||||
|          ctx.response.headers.set( | ||||
|             "cache-control", | ||||
|             "public, max-age=" + MAX_FIXED_CACHE_AGE | ||||
|          ); | ||||
|       } else { | ||||
|          ctx.response.headers.set( | ||||
|             "cache-control", | ||||
|             "no-cache, max-age=" + MAX_FLOATING_CACHE_AGE | ||||
|          ); | ||||
|       } | ||||
|  | ||||
|       if (!result) return E404(); | ||||
|       return result; | ||||
|  | ||||
|       ctx.response.headers.set("e-tag", result.etag); | ||||
|       return result.data; | ||||
|    }); | ||||
| } | ||||
|  | ||||
| @ -1,29 +1,64 @@ | ||||
| import { ABC } from "../deps.ts"; | ||||
| import { basicauth, extractPackagePath } from "../utils.ts"; | ||||
| import { basicauth, extractPackagePath, sortVersions } from "../utils.ts"; | ||||
|  | ||||
| import { Hash } from "../deps.ts"; | ||||
| import db, { IPackage } from "../db.ts"; | ||||
|  | ||||
| const MAX_CACHE_AGE = 60 * 30; // 30 Minutes | ||||
|  | ||||
| const CACHE_CONTROL = "public, max-age=" + MAX_CACHE_AGE; | ||||
|  | ||||
| export default function views(g: ABC.Application) { | ||||
|    g.get( | ||||
|       "/", | ||||
|       async (ctx) => { | ||||
|          return ctx.render("index", { | ||||
|             search: ctx.queryParams["q"], | ||||
|          }); | ||||
|          // const render = await IndexView(); | ||||
|          // console.log(render); | ||||
|          // ctx.response.body = render; | ||||
|          // ctx.response.status = 200; | ||||
|       }, | ||||
|       basicauth("views") | ||||
|    ); | ||||
|    g.get( | ||||
|       "/package/:package", | ||||
|       async (ctx) => { | ||||
|          let [packageName, packageVersion] = extractPackagePath( | ||||
|             ctx.params.package | ||||
|          ); | ||||
|    g.get("/", async (ctx) => { | ||||
|       ctx.response.headers.set("cache-control", CACHE_CONTROL); | ||||
|  | ||||
|          return ctx.render("package", { packageName }); | ||||
|       }, | ||||
|       basicauth("views") | ||||
|    ); | ||||
|       const search = ctx.queryParams.q; | ||||
|  | ||||
|       let packages: IPackage[] = []; | ||||
|       if (search && search !== "") { | ||||
|          packages = await db.package.find({ | ||||
|             name: RegExp(`${search}`), | ||||
|          }); | ||||
|       } else { | ||||
|          packages = await db.package.find({}); | ||||
|       } | ||||
|  | ||||
|       ctx.render("index", { | ||||
|          packages, | ||||
|          search, | ||||
|       }); | ||||
|  | ||||
|       const etag = | ||||
|          "W/" + | ||||
|          Hash.createHash("sha3-256") | ||||
|             .update( | ||||
|                packages | ||||
|                   .map((e) => { | ||||
|                      const sorted = e.versions.sort(sortVersions).reverse(); | ||||
|                      return e.name + sorted[0]; | ||||
|                   }) | ||||
|                   .join(":") | ||||
|             ) | ||||
|             .toString("base64"); | ||||
|  | ||||
|       ctx.response.headers.set("cache-control", CACHE_CONTROL); | ||||
|       ctx.response.headers.set("E-Tag", etag); | ||||
|    }); | ||||
|    g.get("/package/:package", async (ctx) => { | ||||
|       let [packageName, packageVersion] = extractPackagePath( | ||||
|          ctx.params.package | ||||
|       ); | ||||
|  | ||||
|       const pkg = await db.package.findOne({ name: packageName }); | ||||
|  | ||||
|       const etag = | ||||
|          "W/" + | ||||
|          Hash.createHash("sha3-256") | ||||
|             .update(`${packageName}:${packageVersion}`) | ||||
|             .toString("base64"); | ||||
|  | ||||
|       await ctx.render("package", { pkg }); | ||||
|       ctx.response.headers.set("cache-control", CACHE_CONTROL); | ||||
|       ctx.response.headers.set("E-Tag", etag); | ||||
|    }); | ||||
| } | ||||
|  | ||||
| @ -95,7 +95,7 @@ export async function getFile( | ||||
|    pkgName: string, | ||||
|    version: string | null | undefined, | ||||
|    file: string | ||||
| ): Promise<Uint8Array | null | undefined> { | ||||
| ): Promise<{ etag: string; data: Uint8Array } | null | undefined> { | ||||
|    const meta = await db.package.findOne({ name: pkgName }); | ||||
|  | ||||
|    if (!meta || meta.versions.length < 1) return null; | ||||
| @ -122,8 +122,12 @@ export async function getFile( | ||||
|    console.log("Getting file from:", bucketPath); | ||||
|  | ||||
|    try { | ||||
|       const data = (await bucket.getObject(bucketPath))?.body; | ||||
|       return data; | ||||
|       const res = await bucket.getObject(bucketPath); | ||||
|       if (!res) return undefined; | ||||
|       return { | ||||
|          etag: res.etag, | ||||
|          data: res.body, | ||||
|       }; | ||||
|    } catch (err) { | ||||
|       const msg = err.message as string; | ||||
|       if (msg.indexOf("404") >= 0) return null; | ||||
|  | ||||
| @ -33,16 +33,13 @@ function Package({ pkg }: { pkg: IPackage }) { | ||||
|  | ||||
| import { Main, Menu } from "./_default.tsx"; | ||||
|  | ||||
| export default async function index({ search }: any) { | ||||
|    let packages: IPackage[] = []; | ||||
|    if (search && search !== "") { | ||||
|       packages = await DB.package.find({ | ||||
|          name: RegExp(`${search}`), | ||||
|       }); | ||||
|    } else { | ||||
|       packages = await DB.package.find({}); | ||||
|    } | ||||
|  | ||||
| export default async function index({ | ||||
|    packages, | ||||
|    search, | ||||
| }: { | ||||
|    packages: IPackage[]; | ||||
|    search: string; | ||||
| }) { | ||||
|    return ( | ||||
|       <Base> | ||||
|          <Main> | ||||
|  | ||||
| @ -30,9 +30,7 @@ import { sortVersions, getFile } from "../utils.ts"; | ||||
|  | ||||
| import { Main, Menu } from "./_default.tsx"; | ||||
|  | ||||
| export default async function index({ packageName }: any) { | ||||
|    const pkg = await DB.package.findOne({ name: packageName }); | ||||
|  | ||||
| export default async function index({ pkg }: { pkg: IPackage }) { | ||||
|    if (!pkg) | ||||
|       return ( | ||||
|          <Base> | ||||
| @ -40,15 +38,14 @@ export default async function index({ packageName }: any) { | ||||
|          </Base> | ||||
|       ); | ||||
|  | ||||
|    const readmeContent = await getFile( | ||||
|       packageName, | ||||
|       undefined, | ||||
|       "README.md" | ||||
|    ).then((res) => { | ||||
|       if (res) | ||||
|          return Marked.parse(new TextDecoder().decode(res)).content as string; | ||||
|       else return undefined; | ||||
|    }); | ||||
|    const readmeContent = await getFile(pkg.name, undefined, "README.md").then( | ||||
|       (res) => { | ||||
|          if (res) | ||||
|             return Marked.parse(new TextDecoder().decode(res.data)) | ||||
|                .content as string; | ||||
|          else return undefined; | ||||
|       } | ||||
|    ); | ||||
|  | ||||
|    return ( | ||||
|       <Base> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	