Skip to content

[node] Fix http.createServer signature#70289

Merged
typescript-bot merged 12 commits intoDefinitelyTyped:masterfrom
Lordfirespeed:fix/http-prototypes
Sep 3, 2024
Merged

[node] Fix http.createServer signature#70289
typescript-bot merged 12 commits intoDefinitelyTyped:masterfrom
Lordfirespeed:fix/http-prototypes

Conversation

@Lordfirespeed
Copy link
Contributor

@Lordfirespeed Lordfirespeed commented Aug 13, 2024

I am changing an existing definition:

  • Provide a URL to documentation or source code which provides context for the suggested changes: [none applicable]

Basically, createServer's current definition doesn't work when using custom prototypes like the following for IncomingMessage, ServerResponse:

class MyRequest extends http.IncomingMessage {
    foo: string 
}

class MyResponse<Request extends MyRequest = MyRequest> extends http.ServerResponse<Request> {
    foo: string
}

createServer({ IncomingMessage: MyRequest, ServerResponse: MyResponse }) // this fails

because the construct signature of MyResponse doesn't match

new <Request extends IncomingMessage = IncomingMessage>(request: Request): ServerResponse<Request>

Which is the wrong signature to match against, it should be matching against ServerResponse<InstanceType<Request>> instead of ServerResponse, which is equivalent to ServerResponse<IncomingMessage>

https.d.ts and http2.d.ts have the same/similar issues, I haven't addressed those in this PR I have now addressed those in this PR.

@Lordfirespeed Lordfirespeed changed the title [node] Fix signature http.createServer [node] Fix http.createServer signature Aug 13, 2024
@typescript-bot
Copy link
Contributor

typescript-bot commented Aug 13, 2024

@Lordfirespeed Thank you for submitting this PR! I see this is your first time submitting to DefinitelyTyped 👋 — I'm the local bot who will help you through the process of getting things through.

This is a live comment that I will keep updated.

3 packages in this PR

Code Reviews

Because this is a widely-used package, a DT maintainer will need to review it before it can be merged.

You can test the changes of this PR in the Playground.

Status

  • ✅ No merge conflicts
  • ✅ Continuous integration tests have passed
  • ✅ A DT maintainer needs to approve changes that affect more than one package

All of the items on the list are green. To merge, you need to post a comment including the string "Ready to merge" to bring in your changes.


Diagnostic Information: What the bot saw about this PR
{
  "type": "info",
  "now": "-",
  "pr_number": 70289,
  "author": "Lordfirespeed",
  "headCommitOid": "b6edb93fcab7dc15f95491aca8f86378398bd64e",
  "mergeBaseOid": "f90ce6987fce601c2e64de3dc0f0040bc2696ff7",
  "lastPushDate": "2024-08-13T20:59:52.000Z",
  "lastActivityDate": "2024-09-03T23:35:40.000Z",
  "mergeOfferDate": "2024-09-03T23:21:56.000Z",
  "mergeRequestDate": "2024-09-03T23:35:40.000Z",
  "mergeRequestUser": "Lordfirespeed",
  "hasMergeConflict": false,
  "isFirstContribution": true,
  "tooManyFiles": false,
  "hugeChange": false,
  "popularityLevel": "Critical",
  "pkgInfo": [
    {
      "name": "node-red__registry",
      "kind": "edit",
      "files": [
        {
          "path": "types/node-red__registry/node-red__registry-tests.ts",
          "kind": "test"
        }
      ],
      "owners": [
        "alexk111",
        "Shaquu"
      ],
      "addedOwners": [],
      "deletedOwners": [],
      "popularityLevel": "Well-liked by everyone"
    },
    {
      "name": "node",
      "kind": "edit",
      "files": [
        {
          "path": "types/node/http.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/http2.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/https.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/test/http.ts",
          "kind": "test"
        },
        {
          "path": "types/node/test/http2.ts",
          "kind": "test"
        },
        {
          "path": "types/node/v16/http.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v16/http2.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v16/https.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v16/test/http2.ts",
          "kind": "test"
        },
        {
          "path": "types/node/v18/http.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v18/http2.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v18/https.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v18/test/http2.ts",
          "kind": "test"
        },
        {
          "path": "types/node/v20/http.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v20/http2.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v20/https.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/node/v20/test/http2.ts",
          "kind": "test"
        }
      ],
      "owners": [
        "Microsoft",
        "jkomyno",
        "alvis",
        "r3nya",
        "btoueg",
        "smac89",
        "touffy",
        "DeividasBakanas",
        "eyqs",
        "Hannes-Magnusson-CK",
        "hoo29",
        "kjin",
        "ajafff",
        "islishude",
        "mwiktorczyk",
        "mohsen1",
        "galkin",
        "parambirs",
        "eps1lon",
        "ThomasdenH",
        "WilcoBakker",
        "wwwy3y3",
        "samuela",
        "kuehlein",
        "bhongy",
        "chyzwar",
        "trivikr",
        "yoursunny",
        "qwelias",
        "ExE-Boss",
        "peterblazejewicz",
        "addaleax",
        "victorperin",
        "ZYSzys",
        "NodeJS",
        "LinusU",
        "wafuwafu13",
        "mcollina",
        "Semigradsky"
      ],
      "addedOwners": [],
      "deletedOwners": [],
      "popularityLevel": "Critical"
    },
    {
      "name": "stoppable",
      "kind": "edit",
      "files": [
        {
          "path": "types/stoppable/stoppable-tests.ts",
          "kind": "test"
        }
      ],
      "owners": [
        "EricByers",
        "jplusje",
        "BendingBender"
      ],
      "addedOwners": [],
      "deletedOwners": [],
      "popularityLevel": "Popular"
    }
  ],
  "reviews": [
    {
      "type": "approved",
      "reviewer": "andrewbranch",
      "date": "2024-09-03T23:21:17.000Z",
      "isMaintainer": true
    },
    {
      "type": "approved",
      "reviewer": "mcollina",
      "date": "2024-09-01T08:18:21.000Z",
      "isMaintainer": false
    },
    {
      "type": "stale",
      "reviewer": "nicolas377",
      "date": "2024-08-15T01:26:53.000Z",
      "abbrOid": "ff38d26"
    }
  ],
  "mainBotCommentID": 2287131263,
  "ciResult": "pass"
}

@typescript-bot typescript-bot added Critical package Untested Change This PR does not touch tests labels Aug 13, 2024
@typescript-bot
Copy link
Contributor

typescript-bot commented Aug 13, 2024

@typescript-bot typescript-bot added The CI failed When GH Actions fails and removed Untested Change This PR does not touch tests labels Aug 13, 2024
@typescript-bot
Copy link
Contributor

@Lordfirespeed The CI build failed! Please review the logs for more information.

Once you've pushed the fixes, the build will automatically re-run. Thanks!

Note: builds that are failing do not end up on the list of PRs for the DT maintainers to review.

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Aug 13, 2024

I don't understand how to fix the build. The errors seem unrelated to my changes? some help would be much appreciated!

@typescript-bot typescript-bot added Edits multiple packages and removed The CI failed When GH Actions fails labels Aug 14, 2024
@Lordfirespeed
Copy link
Contributor Author

The build is failing now because of a breaking release to @npm/types here

@typescript-bot typescript-bot added the The CI failed When GH Actions fails label Aug 14, 2024
@typescript-bot
Copy link
Contributor

@Lordfirespeed The CI build failed! Please review the logs for more information.

Once you've pushed the fixes, the build will automatically re-run. Thanks!

Note: builds that are failing do not end up on the list of PRs for the DT maintainers to review.

@typescript-bot typescript-bot added The CI failed When GH Actions fails and removed The CI failed When GH Actions fails labels Aug 14, 2024
@typescript-bot
Copy link
Contributor

@Lordfirespeed The CI build failed! Please review the logs for more information.

Once you've pushed the fixes, the build will automatically re-run. Thanks!

Note: builds that are failing do not end up on the list of PRs for the DT maintainers to review.

@Lordfirespeed
Copy link
Contributor Author

The build is failing because ... no good reason ? 😩

@forivall
Copy link
Contributor

CI is showing the following:

Error in fontagon
Error: 
/home/runner/work/DefinitelyTyped/DefinitelyTyped/types/fontagon/index.d.ts
  2:38  error  TypeScript@4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6 compile error: 
Cannot find module 'svgicons2svgfont' or its corresponding type declarations  @definitelytyped/expect

✖ 1 problem (1 error, 0 warnings)

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Aug 14, 2024

Yes, and what's that got to do with this PR?!

I haven't touched that module at all! 😭

@nicolas377
Copy link
Contributor

I've been summoned from my summer break grave, and oh boy did I just go on the tour of this repo. Looks like the original reason my package is breaking is a semver major release from @npm/types, only a problem because of my careless version restrictions. I'm perfectly fine with this PR fixing my package, a maintainer will get around to it soon, sorry! In regards to the failing CI, Fontagon is tested since it's a dep of a dep (ttf2woff references node types), but it was broken because of the recently merged #70261. IMO this is pretty much a failure of the CI on that PR, maintainers was that intentional? The fontagon types need to be updated to rely on svgicons2svgfont itself (or an older version of the types) since it provides types (pinging @peterblazejewicz since it's late and I'm lazy, sorry). Also, I haven't been around for a sec, are we even supposed to test 2 layer deps? I'm going to bed, but signing off on the change.

@jakebailey
Copy link
Member

IMO this is pretty much a failure of the CI on that PR, maintainers was that intentional?

This is a known hole in CI; the package isn't shimmed on npm before the PR is merged, of course, so we can't test packages in the repo with it.

@jakebailey
Copy link
Member

Yes, and what's that got to do with this PR?!

I haven't touched that module at all! 😭

A change to the node types can break deps of deps of deps of ... and so on, so the entire transitive tree is checked. Unfortunately, that leaves popular packages sensitive to ecosystem-wide breaks until they are fixed.

@jakebailey
Copy link
Member

Sent #70297

@jakebailey jakebailey closed this Aug 15, 2024
@jakebailey jakebailey reopened this Aug 15, 2024
@typescript-bot typescript-bot removed the The CI failed When GH Actions fails label Aug 15, 2024
@typescript-bot
Copy link
Contributor

@typescript-bot typescript-bot added the Unreviewed No one showed up to review this PR, so it'll be reviewed by a DT maintainer. label Aug 25, 2024
@typescript-bot
Copy link
Contributor

typescript-bot commented Sep 1, 2024

Copy link
Contributor

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@typescript-bot typescript-bot added the Owner Approved A listed owner of this package signed off on the pull request. label Sep 1, 2024
@typescript-bot typescript-bot added Maintainer Approved Self Merge This PR can now be self-merged by the PR author or an owner and removed Unreviewed No one showed up to review this PR, so it'll be reviewed by a DT maintainer. labels Sep 3, 2024
@Lordfirespeed
Copy link
Contributor Author

Ready to merge

@typescript-bot typescript-bot merged commit c1be9cf into DefinitelyTyped:master Sep 3, 2024
Lordfirespeed added a commit to ducompsoc/durhack that referenced this pull request Sep 4, 2024
Lordfirespeed added a commit to ducompsoc/durhack-guilds that referenced this pull request Sep 4, 2024
@CertainlyAria
Copy link

This seems to break existing code. Link To CodeSandbox

image

It looks like the problem is StaticEventEmitterOptions is not exported from node:events Link

The same code and setup produces no errors with @type/node v22.5.2

@RobinTail
Copy link
Contributor

RobinTail commented Sep 4, 2024

breaks for express as well, same error, @Lordfirespeed

@mcollina @andrewbranch @nicolas377 , please revert

@Lordfirespeed
Copy link
Contributor Author

please revert

Reverting isn't the play here - this PR makes the types more correct. We should look into fixing the issue properly.

I haven't had a chance to look today because I was supposed to be flying home. My flight was cancelled and there are no hotel rooms available in this city. I have just sat down to eat my first meal in about 10 hours. I'm sorry I can't look at this right away.

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Sep 4, 2024

What confuses me is that some typescript versions correctly recognise the type as Server<X, Y> but others expand out the response type into some huge object type Server<X, { ... }>? This seems to be the root of the issue.

As a band-aid, though, please can someone try changing the events import on line 46 of http.d.ts to a namespace import (import * as events from "events") ?

@andrewbranch
Copy link
Member

Minimal repro without other libraries:

import https from 'node:https';

export const createServer = () => {
  return https.createServer();
}

(The failure in express-zod-api is unrelated to express)

@Lordfirespeed
Copy link
Contributor Author

Minimal repro without other libraries

What about http.createServer and http2.createServer? Is the problem localised to https?

@andrewbranch
Copy link
Member

As a band-aid, though, please can someone try changing the events import on line 46 of http.d.ts to a namespace import

No luck. Exporting two more private interfaces from events.d.ts fixes the error, but I think the indirection of Request extends typeof http.IncomingMessage and InstanceType<Request> is always going to have a really nasty effect on declaration emit (and quite possibly performance, too). Before:

import https from 'node:https';
export declare const createServer: () => https.Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;

After:

import https from 'node:https';
export declare const createServer: () => https.Server<typeof import("http").IncomingMessage, {
    new (req: import("http").IncomingMessage): import("http").ServerResponse<import("http").IncomingMessage>;
    fromWeb(writableStream: import("stream/web").WritableStream, options?: Pick<import("stream").WritableOptions, "decodeStrings" | "highWaterMark" | "objectMode" | "signal">): import("stream").Writable;
    toWeb(streamWritable: import("stream").Writable): import("stream/web").WritableStream;
    addAbortSignal<T extends import("stream").Stream>(signal: AbortSignal, stream: T): T;
    getDefaultHighWaterMark(objectMode: boolean): number;
    setDefaultHighWaterMark(objectMode: boolean, value: number): void;
    finished: typeof import("stream").finished;
    pipeline: typeof import("stream").pipeline;
    isErrored(stream: import("stream").Readable | import("stream").Writable | NodeJS.ReadableStream | NodeJS.WritableStream): boolean;
    isReadable(stream: import("stream").Readable | NodeJS.ReadableStream): boolean;
    Stream: typeof import("stream").Stream;
    Readable: typeof import("stream").Readable;
    Writable: typeof import("stream").Writable;
    Duplex: typeof import("stream").Duplex;
    Transform: typeof import("stream").Transform;
    PassThrough: typeof import("stream").PassThrough;
    readonly promises: typeof import("node:stream/promises");
    readonly consumers: typeof import("node:stream/consumers");
    once(emitter: NodeJS.EventEmitter, eventName: string | symbol, options?: import("events").StaticEventEmitterOptions): Promise<any[]>;
    once(emitter: EventTarget, eventName: string, options?: import("events").StaticEventEmitterOptions): Promise<any[]>;
    on(emitter: NodeJS.EventEmitter, eventName: string | symbol, options?: import("events").StaticEventEmitterIteratorOptions): AsyncIterableIterator<any[]>;
    on(emitter: EventTarget, eventName: string, options?: import("events").StaticEventEmitterIteratorOptions): AsyncIterableIterator<any[]>;
    listenerCount(emitter: NodeJS.EventEmitter, eventName: string | symbol): number;
    getEventListeners(emitter: EventTarget | NodeJS.EventEmitter, name: string | symbol): Function[];
    getMaxListeners(emitter: EventTarget | NodeJS.EventEmitter): number;
    setMaxListeners(n?: number, ...eventTargets: Array<EventTarget | NodeJS.EventEmitter>): void;
    addAbortListener(signal: AbortSignal, resource: (event: Event) => void): Disposable;
    readonly errorMonitor: typeof import("events").errorMonitor;
    readonly captureRejectionSymbol: typeof import("events").captureRejectionSymbol;
    captureRejections: boolean;
    defaultMaxListeners: number;
    EventEmitter: typeof import("events");
    EventEmitterAsyncResource: typeof import("events").EventEmitterAsyncResource;
}>;

The type parameters really ought to be refactored such that InstanceType isn’t needed, but that might be unacceptably breaky for @types/node.

I’m going to revert, sorry. We can’t wait days or even hours when @types/node is broken.

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Sep 4, 2024

What's odd is that typescript versions 5.0 through 5.3 (?) don't do the big messy object type - I wonder if there's been a regression on typescript's side ...

I’m going to revert, sorry. We can’t wait days or even hours when @types/node is broken.

Totally understandable. Hopefully I can resolve this issue and bring it back for a second go around without the problems

@andrewbranch
Copy link
Member

typescript versions 5.0 through 5.3 (?) don't do the big messy object type

They do, in declaration emit. I’m seeing it in quick info too, but it’s possible that some specific input code on some specific TS version was producing a clean-looking but invalid quick info response. Quick info isn’t always valid code.

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Sep 4, 2024

They do, in declaration emit. [...] Quick info isn’t always valid code.

Thankyou for the insight - that's good to know.

@Lordfirespeed
Copy link
Contributor Author

Lordfirespeed commented Sep 5, 2024

So @andrewbranch - what if I add overload declarations for the old signature that take precedence?

Using the old default value for the Response type parameter is sufficient.

This way the common use-case of having no custom prototypes should continue to work with no performance issues, but people using custom prototypes could do so unhindered.

Of course I would need to add those events imports too.

@nicolas377
Copy link
Contributor

@nicolas377 please revert

In the wise words of someone smart once: "not it"
If y'all actually need me to revert the approval, email me. I don't check github very often (this is my first time checking since I was pinged 3 weeks ago). I'm not gonna be helpful with fixing the problems than anyone else would.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Critical package Edits multiple packages Maintainer Approved Owner Approved A listed owner of this package signed off on the pull request. Self Merge This PR can now be self-merged by the PR author or an owner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants