Skip to content

Commit

Permalink
feat: reimplement server with h3 (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Sep 14, 2023
1 parent 58df066 commit 1f14c2e
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 321 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"unicorn/prefer-top-level-await": 0,
"unicorn/no-process-exit": 0,
"unicorn/prevent-abbreviations": 0,
"unicorn/no-null": 0,
"no-undef": 0
}
}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,13 @@ You can universally customize IPX configuration using `IPX_*` environment variab

- Default: `300`

- `IPX_HTTP_FETCH_OPTIONS`
#### `IPX_HTTP_FETCH_OPTIONS`

- Default: `{}`
- Default: `{}`

#### `IPX_HTTP_ALLOW_ALL_DOMAINS`

- Default: `false`

## Modifiers

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,19 @@
},
"dependencies": {
"@fastify/accept-negotiator": "^1.1.0",
"citty": "^0.1.4",
"consola": "^3.2.3",
"defu": "^6.1.2",
"destr": "^2.0.1",
"etag": "^1.8.1",
"h3": "^1.8.1",
"image-meta": "^0.1.1",
"listhen": "^1.5.2",
"node-fetch-native": "^1.4.0",
"pathe": "^1.1.1",
"sharp": "^0.32.5",
"ufo": "^1.3.0",
"unstorage": "^1.9.0",
"xss": "^1.0.14"
"unstorage": "^1.9.0"
},
"devDependencies": {
"@types/etag": "^1.8.1",
Expand Down
11 changes: 3 additions & 8 deletions playground.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import {
createIPX,
createIPXMiddleware,
ipxFSStorage,
ipxHttpStorage,
} from "./src";
import { createIPX, createIPXH3App, ipxFSStorage, ipxHttpStorage } from "./src";

const ipx = createIPX({
storage: ipxFSStorage({ dir: "./test/assets" }),
storage: ipxFSStorage(),
httpStorage: ipxHttpStorage({
domains: ["picsum.photos"],
}),
});

export default createIPXMiddleware(ipx);
export default createIPXH3App(ipx);
26 changes: 6 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "listhen/cli";
import { name, version, description } from "../package.json";
import { createIPX } from "./ipx";
import { createIPXMiddleware } from "./middleware";
import { createIPXNodeServer } from "./server";
import { ipxFSStorage } from "./storage/node-fs";
import { ipxHttpStorage } from "./storage/http";

Expand Down Expand Up @@ -37,8 +37,7 @@ const serve = defineCommand({
domains: args.domains,
}),
});
const middleware = createIPXMiddleware(ipx);
await listen(middleware, {
await listen(createIPXNodeServer(ipx), {
name: "IPX",
...parseListhenArgs(args),
});
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from "./ipx";
export * from "./middleware";
export * from "./server";
export * from "./types";
export * from "./storage/http";
export * from "./storage/node-fs";
Expand Down
27 changes: 20 additions & 7 deletions src/ipx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { defu } from "defu";
import { imageMeta as getImageMeta } from "image-meta";
import { hasProtocol, joinURL, withLeadingSlash } from "ufo";
import type { SharpOptions } from "sharp";
import { createError } from "h3";
import type { ImageMeta, IPXStorage } from "./types";
import { HandlerName, applyHandler, getHandler } from "./handlers";
import { cachedPromise, getEnv, createError } from "./utils";
import { cachedPromise, getEnv } from "./utils";

type IPXSourceMeta = { mtime?: Date; maxAge?: number };

Expand Down Expand Up @@ -47,8 +48,8 @@ const SUPPORTED_FORMATS = new Set([

export function createIPX(userOptions: IPXOptions): IPX {
const options: IPXOptions = defu(userOptions, {
alias: getEnv<Record<string, string>>("IPX_ALIAS", {}),
maxAge: getEnv<number>("IPX_MAX_AGE", 300),
alias: getEnv<Record<string, string>>("IPX_ALIAS") || {},
maxAge: getEnv<number>("IPX_MAX_AGE") || 300,
sharpOptions: {},
} satisfies Omit<IPXOptions, "storage">);

Expand All @@ -70,7 +71,10 @@ export function createIPX(userOptions: IPXOptions): IPX {
return function ipx(id, modifiers = {}, opts = {}) {
// Validate id
if (!id) {
throw createError("resource `id` is missing", 400);
throw createError({
statusCode: 400,
message: `Resource id is missing`,
});
}

// Enforce leading slash for non absolute urls
Expand All @@ -88,14 +92,20 @@ export function createIPX(userOptions: IPXOptions): IPX {
? options.httpStorage || options.storage
: options.storage || options.httpStorage;
if (!storage) {
throw createError("No storage configured!", 500);
throw createError({
statusCode: 500,
message: "No storage configured!",
});
}

// Resolve Resource
const getSourceMeta = cachedPromise(async () => {
const sourceMeta = await storage.getMeta(id, opts);
if (!sourceMeta) {
throw createError(`Resource not found: ${id}`, 404);
throw createError({
statusCode: 404,
message: `Resource not found: ${id}`,
});
}
return {
maxAge:
Expand All @@ -108,7 +118,10 @@ export function createIPX(userOptions: IPXOptions): IPX {
const getSourceData = cachedPromise(async () => {
const sourceData = await storage.getData(id, opts);
if (!sourceData) {
throw createError(`Resource not found: ${id}`, 404);
throw createError({
statusCode: 404,
message: `Resource not found: ${id}`,
});
}
return Buffer.from(sourceData);
});
Expand Down
Loading

0 comments on commit 1f14c2e

Please sign in to comment.