Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundler plugins #12

Merged
merged 59 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
217adca
feat: rollup plugin
magne4000 Jul 16, 2024
8893dd1
tests: rollup
magne4000 Jul 16, 2024
ce61d2b
tests: rollup
magne4000 Jul 16, 2024
1d9dac6
tests: rollup
magne4000 Jul 16, 2024
20cc163
feat: esbuild plugin
magne4000 Jul 16, 2024
ace5ca3
fix: rollup
magne4000 Jul 16, 2024
15b44b1
fix: rollup
magne4000 Jul 16, 2024
97d7201
chore(esbuild): respect outbase
magne4000 Jul 17, 2024
873e0ca
feat(esbuild): generate report
magne4000 Jul 17, 2024
434b3f2
chore: pnpm-lock
magne4000 Jul 17, 2024
ea40a65
refactor: share code between esbuild and rollup
magne4000 Jul 17, 2024
09f3ef2
chore(rollup): ensure externals
magne4000 Jul 17, 2024
f9f1c32
chore: force build order
magne4000 Jul 17, 2024
d7bc7ce
chore: windows tests
magne4000 Jul 17, 2024
1812dd8
chore: remove comments
magne4000 Jul 17, 2024
29fbcae
chore: windows tests
magne4000 Jul 17, 2024
64ac9ce
chore: windows tests
magne4000 Jul 17, 2024
de9c817
chore: windows tests
magne4000 Jul 17, 2024
3c60201
chore: windows tests
magne4000 Jul 17, 2024
f048657
chore: windows tests
magne4000 Jul 17, 2024
2264f83
chore: windows tests
magne4000 Jul 17, 2024
82b8c24
tests: report
magne4000 Jul 17, 2024
15315f2
chore: fix build
magne4000 Jul 17, 2024
1bccff9
chore: windows tests
magne4000 Jul 17, 2024
e4d3406
chore: eslint ignore
magne4000 Jul 17, 2024
8dc6134
chore: windows tests
magne4000 Jul 17, 2024
5baefa8
chore: windows tests
magne4000 Jul 17, 2024
f14c17b
chore: tests-tool
magne4000 Jul 17, 2024
5891cad
chore: edit package.json
magne4000 Jul 17, 2024
97e0042
chore: working tests-example
magne4000 Jul 17, 2024
fa8e540
tests: e2e tests
magne4000 Jul 17, 2024
eb5b7df
tests: types
magne4000 Jul 17, 2024
cdf09c3
chore
magne4000 Jul 17, 2024
417c71c
feat: Add ability to forwards args to underlying handler or middlewar…
magne4000 Jul 17, 2024
04b80f7
Merge branch 'main' into plugin
magne4000 Jul 19, 2024
e14a8dc
feat: support for In and Out Context
magne4000 Aug 17, 2024
1cb1080
feat: webroute adapter
magne4000 Aug 17, 2024
c9af0d4
chore: deno.lock
magne4000 Aug 17, 2024
1c923ac
fixes
magne4000 Aug 17, 2024
5684fb0
fix: typings
magne4000 Aug 17, 2024
c1ac056
feat: initial support for runtime parameter
magne4000 Aug 18, 2024
d1c2f86
chore: update package.sjon
magne4000 Aug 18, 2024
117733a
chore: update package.sjon
magne4000 Aug 18, 2024
819f8a6
chore: dedupe webroute
magne4000 Aug 18, 2024
53407b3
chore: return context update
magne4000 Aug 18, 2024
043298c
feat: complete webroute support
magne4000 Aug 18, 2024
7b8a994
chore: better TS types for webroute generated exports
magne4000 Aug 18, 2024
edb8959
refactor: dts generation
magne4000 Aug 18, 2024
150d7c6
tests: auto generated exports typings
magne4000 Aug 18, 2024
ee3a451
chore: deps
magne4000 Aug 18, 2024
c267778
release: @universal-middleware/[email protected]
magne4000 Aug 18, 2024
57624e4
chore: prepare files for release
magne4000 Aug 18, 2024
43c8836
chore: update deno lock files
magne4000 Aug 18, 2024
cfa17a4
chore: deno lock false
magne4000 Aug 18, 2024
e008ac4
chore: deno --unstable-byonm
magne4000 Aug 18, 2024
c084f99
doc(universal-middleware): readme
magne4000 Aug 18, 2024
dbcd8ac
doc: symlink global README to universal-middleware package
magne4000 Aug 18, 2024
3d1a75e
doc: intro to universal-middleware usage
magne4000 Aug 18, 2024
88143c4
doc: README
magne4000 Aug 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build artifacts
dist/**
**/dist/**

# JS files at the root of the project
*.js
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ jobs:
- name: Install
run: pnpm install

- run: pnpm exec playwright install chromium

- name: Build
run: pnpm run build

Expand Down
3 changes: 3 additions & 0 deletions .idea/universal-handler.iml

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

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
package-manager-strict=false
auto-install-peers=false
97 changes: 0 additions & 97 deletions README.md

This file was deleted.

1 change: 1 addition & 0 deletions README.md
116 changes: 116 additions & 0 deletions examples/tool/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"name": "@universal-middleware-examples/tool",
"version": "0.0.0",
"private": true,
"type": "module",
"files": [
"dist"
],
"exports": {
"./dummy-handler": {
"types": "./dist/dummy.d.ts",
"import": "./dist/dummy.js",
"default": "./dist/dummy.js"
},
"./middlewares/context-middleware": {
"types": "./dist/middlewares/context.d.ts",
"import": "./dist/middlewares/context.js",
"default": "./dist/middlewares/context.js"
},
"./middlewares/headers-middleware": {
"types": "./dist/middlewares/headers.d.ts",
"import": "./dist/middlewares/headers.js",
"default": "./dist/middlewares/headers.js"
},
"./dummy-handler-hono": {
"types": "./dist/handlers/universal-hono-handler-handler.d.ts",
"import": "./dist/handlers/universal-hono-handler-handler.js",
"default": "./dist/handlers/universal-hono-handler-handler.js"
},
"./dummy-handler-express": {
"types": "./dist/handlers/universal-express-handler-handler.d.ts",
"import": "./dist/handlers/universal-express-handler-handler.js",
"default": "./dist/handlers/universal-express-handler-handler.js"
},
"./dummy-handler-hattip": {
"types": "./dist/handlers/universal-hattip-handler-handler.d.ts",
"import": "./dist/handlers/universal-hattip-handler-handler.js",
"default": "./dist/handlers/universal-hattip-handler-handler.js"
},
"./middlewares/context-middleware-hono": {
"types": "./dist/middlewares/universal-hono-middleware-context.middleware.d.ts",
"import": "./dist/middlewares/universal-hono-middleware-context.middleware.js",
"default": "./dist/middlewares/universal-hono-middleware-context.middleware.js"
},
"./middlewares/context-middleware-express": {
"types": "./dist/middlewares/universal-express-middleware-context.middleware.d.ts",
"import": "./dist/middlewares/universal-express-middleware-context.middleware.js",
"default": "./dist/middlewares/universal-express-middleware-context.middleware.js"
},
"./middlewares/context-middleware-hattip": {
"types": "./dist/middlewares/universal-hattip-middleware-context.middleware.d.ts",
"import": "./dist/middlewares/universal-hattip-middleware-context.middleware.js",
"default": "./dist/middlewares/universal-hattip-middleware-context.middleware.js"
},
"./middlewares/headers-middleware-hono": {
"types": "./dist/middlewares/universal-hono-middleware-headers.middleware.d.ts",
"import": "./dist/middlewares/universal-hono-middleware-headers.middleware.js",
"default": "./dist/middlewares/universal-hono-middleware-headers.middleware.js"
},
"./middlewares/headers-middleware-express": {
"types": "./dist/middlewares/universal-express-middleware-headers.middleware.d.ts",
"import": "./dist/middlewares/universal-express-middleware-headers.middleware.js",
"default": "./dist/middlewares/universal-express-middleware-headers.middleware.js"
},
"./middlewares/headers-middleware-hattip": {
"types": "./dist/middlewares/universal-hattip-middleware-headers.middleware.d.ts",
"import": "./dist/middlewares/universal-hattip-middleware-headers.middleware.js",
"default": "./dist/middlewares/universal-hattip-middleware-headers.middleware.js"
},
"./dummy-handler-webroute": {
"types": "./dist/handlers/universal-webroute-handler-handler.d.ts",
"import": "./dist/handlers/universal-webroute-handler-handler.js",
"default": "./dist/handlers/universal-webroute-handler-handler.js"
},
"./middlewares/context-middleware-webroute": {
"types": "./dist/middlewares/universal-webroute-middleware-context.middleware.d.ts",
"import": "./dist/middlewares/universal-webroute-middleware-context.middleware.js",
"default": "./dist/middlewares/universal-webroute-middleware-context.middleware.js"
},
"./middlewares/headers-middleware-webroute": {
"types": "./dist/middlewares/universal-webroute-middleware-headers.middleware.d.ts",
"import": "./dist/middlewares/universal-webroute-middleware-headers.middleware.js",
"default": "./dist/middlewares/universal-webroute-middleware-headers.middleware.js"
}
},
"author": "Joël Charles <[email protected]>",
"repository": "https://github.com/magne4000/universal-handler",
"license": "MIT",
"scripts": {
"build": "rimraf dist && tsup",
"prepack": "pnpm build",
"test:typecheck": "tsc -p tsconfig.json --noEmit"
},
"devDependencies": {
"@hono/node-server": "^1.12.0",
"@swc/core": "^1.7.11",
"@types/node": "^20.14.10",
"rimraf": "^6.0.0",
"tsup": "^8.2.4",
"typescript": "^5.5.4",
"universal-middleware": "*"
},
"optionalDependencies": {
"@universal-middleware/express": "^0",
"@universal-middleware/hattip": "^0",
"@universal-middleware/hono": "^0",
"@universal-middleware/webroute": "^0"
},
"sideEffects": false,
"peerDependencies": {
"@universal-middleware/express": "^0",
"@universal-middleware/hattip": "^0",
"@universal-middleware/hono": "^0",
"@universal-middleware/webroute": "^0"
}
}
9 changes: 9 additions & 0 deletions examples/tool/src/handlers/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Get, UniversalHandler } from "universal-middleware";

const handler: Get<[], UniversalHandler> = () => (_request, ctx) => {
return new Response("context: " + JSON.stringify(ctx), {
status: 200,
});
};

export default handler;
11 changes: 11 additions & 0 deletions examples/tool/src/middlewares/context.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Get, UniversalMiddleware } from "universal-middleware";

const contextMiddleware = ((value) => (_request, ctx) => {
return {
...ctx,
something: value,
};
// Using `satisfies` to not lose return type
}) satisfies Get<[string], UniversalMiddleware>;

export default contextMiddleware;
12 changes: 12 additions & 0 deletions examples/tool/src/middlewares/headers.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Get, UniversalMiddleware } from "universal-middleware";

const headersMiddleware: Get<[], UniversalMiddleware<{ something?: string }>> =
() => (_request, ctx) => {
return (response) => {
response.headers.set("X-Custom-Header", ctx.something ?? "NONE");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't review everything, but I'll be honest, stuff like this rubs me all the wrong ways - requiring optional fields in the context type, and then using the ?? operator, it just sounds too brittle for my taste. Users will put those middlewares in the wrong order, things will quietly malfunction - because the types aren't really telling the truth, it will be difficult for them to understand why.

I really want to see type safety for this.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type safety can be achieved with a proper webroute-adapter for instance.
Proper type safety cannot be achieved currently with the current state of javascript servers (without something like webroute), which is out of scope here.

The scope of this PR is to ease the work of tool authors, and the whole middleware composition stack should not be a part of this solution, as it adds a lot of overhead, maintainability cost, and complexity when explaining what this project purpose is.

It's still a huge step forward in the right direction. And again, complete type safety will be possible with webroute and the servers it supports.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could perhaps add the webroute adapter in this PR, so that we can review it as well

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still a huge step forward in the right direction.

Yeah, no doubt. 🙂

And again, complete type safety will be possible with webroute and the servers it supports.

How?

If this universal middleware has inaccurate context types, how would webroute solve that?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently working on some improvements and the webroute adapter to make it clearer.

Copy link
Owner Author

@magne4000 magne4000 Aug 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example using webroute adapter

cc @mindplay-dk @sinclairnick

The middleware signature has been adapted to correspond to this comment.

@sinclairnick as you can see, declaring middlewares outside @webroute/router flow makes it a little bit verbose to actually extract the correct types.
I wonder if there would be a solution where webroute could automatically extract required TState ("input" state) and generated DataResult ("output" state) for middlewares declared outside of webroute flow.
For instance, I could declare a middleware with the following signature WebrouteMiddleware<InState, OutState = OutState> and have webroute extract InState and OutState if the signature matches WebrouteMiddleware.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies if I've misunderstood here, as there's obviously a lot of context/info in this repo I may have missed.

But if I understand correctly, there is indeed a type that's allows declaring the inputs and outputs, without having to rely on inference.

The MiddlewareFn type enables setting:

  • The "data result"
  • The middleware's extra input parameters
  • The "response handler"'s extra parameters
export type MiddlewareFn<
  T extends DataResult | void = void,
  TRest extends any[] = any[],
  TRestRes extends any[] = any[]
> = (
  request: Request,
  ...rest: TRest
) => Awaitable<MiddlewareResult<T, TRestRes>>;

So to achieve what you're describing this would look something like:

type MyMiddleware = MiddlewareFn<OutputCtx, [InputCtx], []>
// OutputCtx is the return type, InputCtx is a single extra param, no response handler extra params

Obviously a small wrapper type could bend this into the correct order of params etc.

Copy link
Owner Author

@magne4000 magne4000 Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sinclairnick thanks, that's a good start, but I realize that I should make a reproduction repo. My issue seems to be more related to the interaction between MiddlewareFn from @webroute/middleware then using it inside @webroute/route route().use(...). But I think that we'll hit a Typescript limitation for what I have in mind...


return response;
};
};

export default headersMiddleware;
17 changes: 17 additions & 0 deletions examples/tool/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"module": "ESNext",
"noEmit": true,
"moduleResolution": "Bundler",
"target": "ES2022",
"lib": ["DOM", "DOM.Iterable", "ESNext"]
},
"exclude": ["dist"]
}
21 changes: 21 additions & 0 deletions examples/tool/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
import universalMiddleware from "universal-middleware/esbuild";

export default defineConfig([
{
entry: {
dummy: "./src/handlers/handler.ts",
"middlewares/context": "./src/middlewares/context.middleware.ts",
"middlewares/headers": "./src/middlewares/headers.middleware.ts",
},
format: ["esm"],
platform: "neutral",
target: "es2022",
dts: true,
esbuildPlugins: [universalMiddleware()],
esbuildOptions(opts) {
opts.outbase = "src";
},
bundle: true,
},
]);
Loading