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

Import & update typings from DefinitelyTyped #656

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

HoldYourWaffle
Copy link
Contributor

The current DefinitelyTyped typescript definitions for this module are a mess. They're needlessly convoluted and in some ways outdated or wrong.
Because my definitions would be a breaking change and because DT is a mess in general (giant mono-repo, having to install another package) I suggest merging these definitions into the main repository.

I made 2 commits to make the difference between the DT definitions and mine clearer, I'd be happy to squash them before this is merged.

Changes relative to the DT definition

  • regenerate, load and createSession are not functions on Store. I'm not sure why they were there in the first place, I think Session has similar methods but they aren't a proper match.
  • Reuse Express.CookieOptions for SessionCookie¹
  • SessionData no longer has a string => any index type. This makes it possible to use declaration merging to allow the user to type their own sessions. This is also seen on express's Request type.
  • There is no BaseMemoryStore, MemoryStore just extends Store
  • A less convoluted type hierarchy

Notes

  • I suggest removing the optional modifier on Express.Request.session and Express.Request.sessionID. Although they're technically 'optional' in the sense that they don't exist before you use your session middleware it's really inconvenient when working with strict null checking enabled. If you have used the middleware these properties are guaranteed to be there, making any checks redundant. Because of this I'd suggest going for convenience rather than accuracy in this instance.
  • ¹I'm definitely not sure about the types of the cookie related properties. There seems to be a container Cookie class here but I'm not sure how it's used and how to represent it in these definitions. I made it an interface which extends Express.CookieOptions for now but I'm pretty sure this neither accurate nor semantically correct.



@horiuchi, @jacobbogers, @builtinnya and @ry7n, you are credited as the original authors of the DT definitions. I have a couple of questions about why they are the way they are:

  • Why is the type hierarchy so convoluted? I couldn't find a reference to anything resembling a BaseMemoryStore and several inheritances redefined common functions.
  • What do you think the cookie types should be?
  • Are there actually good reasons for why the convoluted hierarchies are that way, in other words: did I miss something?

@HoldYourWaffle
Copy link
Contributor Author

I just noticed that although the readme says that a store must be an EventEmitter there's no mention of why they have to be and how it's actually used.
I've never used EventEmitters before, but from what I can tell by a quick google search there doesn't seem to be a reason for this requirement. Even the connect-redis implementation that's set as an example doesn't seem to implement it (although I could just be missing something).

Is the readme wrong or is being an EventEmitter an actual requirement? If so, why do so many stores not implement it (including the one used as example in the readme)?

@HoldYourWaffle
Copy link
Contributor Author

Turns out declaration merging doesn't work properly with these definitions, currently investigating.

index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
@HoldYourWaffle
Copy link
Contributor Author

I have addressed your concerns, including a crude concept of additional documentation in the readme.

What do you think about my suggestion to remove the optional modifier on Request.session and Request.sessionID? Seems like a reasonable trade-off to me, especially with a note on it in the readme (included in the current concept).
And what about the EventEmitter requirement? I haven't found a reason why it's needed nor a store that actually fulfills it.

@dougwilson
Copy link
Contributor

So i have not finished reviewing yet, just things I found from a first look.

What do you think about my suggestion to remove the optional modifier on Request.session and Request.sessionID?

I don't know what this means, can you elaborate if you need an answer from me?

And what about the EventEmitter requirement? I haven't found a reason why it's needed nor a store that actually fulfills it.

It is required. Try making a store without it and it will fail immediately since this module attempts to add event listeners to the store during set up. Not sure what the confusion is.

index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
index.d.ts Outdated Show resolved Hide resolved
@HoldYourWaffle
Copy link
Contributor Author

I don't know what this means, can you elaborate if you need an answer from me?

Typescript employs strict null/undefined checking, which basically means that the compiler screams at you for using a nullable/undefinedable reference without the proper checks. It's really inconvenient in this case, although technically correct to have the session and sessionID properties be 'undefinedable' (optional). The original DT definitions did list these properties as optional, but I'm pretty sure other middleware type definitions don't do this. Either way it's just really inconvenient and messy to have these properties as 'optional', though technically correct.
I hope that's enough elaboration, if not I'm sure one of the original authors will be happy to comment on this matter.

It is required. Try making a store without it and it will fail immediately since this module attempts to add event listeners to the store during set up. Not sure what the confusion is.

Apologies, I completely missed this line which effectively causes all store implementations to implicitly extend EventEmitter. I have updated the definitions accordingly.

index.d.ts Outdated Show resolved Hide resolved
@dougwilson
Copy link
Contributor

I hope that's enough elaboration, if not I'm sure one of the original authors will be happy to comment on this matter.

Well, I've never used typescript and still this seems over my head to be able to answer.

index.d.ts Outdated Show resolved Hide resolved
@HoldYourWaffle
Copy link
Contributor Author

I found another possible mistake in the typings which boils down to the following: do the functions on the Store class expect a full-blown Session (including id, cookie, regenerate, etc.) or just the user-defined data properties?
The DT definitions went for the latter (although I could just be misinterpreting the weird convoluted hierarchy), but I'm not sure that's correct as it seems pretty backwards.

@HoldYourWaffle
Copy link
Contributor Author

I have decided to drop the optional modifier on session/sessionID, mainly because in 99% of the cases it's completely useless. It's just unnecessarily inconvenient, and it's safe to assume someone will actually register the middleware if they're using this module.

I also decided to give the length parameter of the callback passed to the function with the same name a type of just number. I can't think of a use-case where length would return anything else than a number without an error having occured (which in my opinion should result in an error being thrown). Although technically valid, I don't think it's worth it to bother typescript users with a nullable/undefinedable typing.

Lastly I took another shot at the whole cookie system hierarchy. I think I got it right this time, but you should definitely check my summary in the comment above in case I missed something.

Are there any more changes you'd like to see before this can get merged?

@dougwilson
Copy link
Contributor

Thanks so much! I will take another review though them due to the number of changes to double check as well 👍

As for next steps, ignoring the outcome of the review, it would be nice to...

  1. Have a passing CI to merge
  2. Have tests in some form to, at minimum, verify that the tsd is syntacticly correct since it is hand maintained
  3. Is this safe to just land in 1.x? Not sure how landing this affects existing ts users.

@HoldYourWaffle
Copy link
Contributor Author

Have a passing CI to merge

Don't ask me how but I never noticed that the tests are failing. No idea how that can happen by the addition of typings but I'll take a look.

Have tests in some form to, at minimum, verify that the tsd is syntacticly correct since it is hand maintained

I'll see how DefinitelyTyped does this, since they're the biggest (hand-maintained) repository of TypeScript definitions.

Is this safe to just land in 1.x? Not sure how landing this affects existing ts users.

No idea actually. It's probably going to conflict somehow with the DefinitelyTyped version but I'm not sure how well the TypeScript compiler handles duplicate typings. It would make sense for it to only use the in-package definitions but I don't think that's actually how it works. However, if this gets merged the DefinitelyTyped package will ultimately be deprecated/removed providing existing TS users with a nice little warning that'll tell them there are new (and improved) definitions.
As for safety, I think these definitions are under normal usage circumstances compatible (since they both describe the same module and the DT one technically did 'work' although badly).

@dougwilson
Copy link
Contributor

So the safe to land in 1.x is, overall, my main concern. Is there any way to gather what would happen to an existing app?

index.d.ts Outdated Show resolved Hide resolved
@HoldYourWaffle
Copy link
Contributor Author

So the safe to land in 1.x is, overall, my main concern. Is there any way to gather what would happen to an existing app?

Do you know a codebase I could test on?

@dougwilson
Copy link
Contributor

No, I have not used TypeScript before.

@HoldYourWaffle
Copy link
Contributor Author

Turns out CI is only failing in Node v0.8, probably because it's just too old to install the @types/express and @types/node packages (although I'm not sure why those packages would cause issues).
If you don't mind I can just remove Node v0.8 from the test matrix, which I don't think will be that big of an issue since it's almost 7 years old now. This comment suggests that only 0.04% of people were using Node v0.8 3 years ago (not sure where this number comes from but I really don't think the actual percentage will be much higher).

@HoldYourWaffle
Copy link
Contributor Author

In case anyone wants to use these definitions before the next major release without the hassle of git dependencies in node: I have published my fork here.

@HoldYourWaffle
Copy link
Contributor Author

It's been 8 months now, is there any chance of this getting merged soon?
Fixed typings for downstream session stores depend on this PR, so it'd be nice to have a solution that doesn't involve forked dependencies.

Little note to myself: notify JLuboff/connect-mssql-v2#10 when this is merged.

@dougwilson
Copy link
Contributor

#656 (comment)

@voxpelli
Copy link
Contributor

Wouldn’t it be possible to make the types optional dependencies?

They are probably failing because they are scoped dependencies that such an old npm version cannot handle?

Landing this in 1.x would be preferable as any future 2.x is just that – something that eventually happens at some point in the future.

@dougwilson
Copy link
Contributor

I'm not super familiar with typings, so can't really say. Besides the node.js change in this PR, I would assume if these landed in a 1.x version it would still break typescript projects, since the typings here are not compatible with existing typings folks are using, is that a correct assumption?

@HoldYourWaffle
Copy link
Contributor Author

Wouldn’t it be possible to make the types optional dependencies?
They are probably failing because they are scoped dependencies that such an old npm version cannot handle?

I don't fully understand what you're trying to say here.

since the typings here are not compatible with existing typings folks are using, is that a correct assumption?

I don't fully remember, but I'd be surprised if these new typings don't break something.

These changes definitely need to go into a new major version, but I agree with what @voxpelli says (I think). It's been 8 months since I submitted this PR, and (as far as I can tell) v2 hasn't come any closer. You say you want to wait with releasing v2 until all v1-PR's have 'landed', which makes a lot of sense, but if there's no work being done to reach this point it could take years to resolve this mess.

I'm not saying there's nothing happening, because I honestly have no idea if that's the case. I haven't used this module for several months, the only reason I checked in was because a downstream maintainer asked for a status update (chill117/express-mysql-session#93 (comment)).

The current typings mess is (most likely) affecting everyone who uses this library with TS, so I think it's fair to say that a quick solution would be appreciated by a lot of people. I don't want to rush you or anything, I'm just trying to help resolve this typings mess, in the hope that others won't have to go through the same troubles as me.

@HoldYourWaffle
Copy link
Contributor Author

English is not my first language, so I'm sorry if I seem a bit blunt.

Perhaps it'd be possible to release v2 before all PR's have landed?
This means that the new features won't be in v1 of course, but since the breaking changes are minimal updating shouldn't be a problem almost all, if not all, users.

@dougwilson
Copy link
Contributor

If you really need a quick solution, why can the typings not be updated in definatelytyped? Wouldn't that solve everything at concern here? Since that is a separate dependency folks can pull in the version of types that work for them without breaking others and then the others have a chance to migrate? Especially since the types are for the 1.x of this module.

@dougwilson
Copy link
Contributor

I'm ultimately not interested in releasing a major version of this module just to fix typings I never made. I'm happy to land them in here in conjunction with the other badly-needed changes. But I'm not sure why now the pressure is on a module and person who did not make a bunch of broken typings in the first place... this will be landed along with 2.0, but if you really need to "fix the mess" that is not even part of this module, land the fix in definitelytyped in the interim. Folks can use their package.json to refer to the relevant type definitions.

@dougwilson dougwilson added this to the 2.0.0 milestone Jan 19, 2020
@expressjs expressjs locked as too heated and limited conversation to collaborators Jan 19, 2020
@dougwilson
Copy link
Contributor

Note I have locked this thread temporarily while I can get some samesite cookie releases out tonight for folks and can resume this discussion at a later time. One thing to consider for later is who will keep the types up to date with changes in this module? Landing this before the other PRs will make them unlandable as-is since the types will be off. I just want to get those out of the way before we land the types so they are at least not just immediately out of data again. This week I will start a 2.0 beta branch to start getting things landed. We will use that as a test to see if there is anyone who helps keep the types up to date though those changes in the beta as a test for them going in the final release. That is just a proposal, and we can further discuss. I will open a meta issue so things are not lost.

@expressjs expressjs unlocked this conversation Jan 19, 2020
@dougwilson
Copy link
Contributor

Hi @HoldYourWaffle I have unlocked at your request, but I just want to make sure that you (not I) say anything rash is all. Many times I observe when a github issue or pr turns into a chat (based on the speed of responses) it can get out of hand (and I'm not always not at fault either). Especially because responses can be long and both people end up typing and posting at the same time, reading each other's response and again and again :) I don't want PRs just hanging around just like you expressed, but there is a lot going on in the conversation here. I hope some of the previous posts will have some clarity, and I'm going to commit to getting this landed in a 2.0 line this week for all involved here.

@HoldYourWaffle
Copy link
Contributor Author

HoldYourWaffle commented Jan 22, 2020

Thank you for (temporarily) reopening this.
I just wanted to say that I honestly never considered merging this into DT. I prefer to include (fixed) typings in modules because DT has its fair share of issues (which - among other things - caused this mess in the first place).

But you're right, in this case it may be the proper solution. After all, these situations are sort of what DT was meant for in the first place.

I'll see if I can create a PR over at DT soon, if you chip in to say that these typings match (like you did when you reviewed the PR) it should go smoothly. I'd still prefer including the typings in the module itself eventually, but this way you don't have to rush v2.

@dougwilson
Copy link
Contributor

Sounds good. I will be happy to confirm the types on there.

Note I only temporary locked it; it will remain open unless there is a reason to lock again, so you don't need to worry about it just suddenly going locked without warning :)

@HoldYourWaffle
Copy link
Contributor Author

I have just created the PR to update the definitions over at DT.

@HoldYourWaffle
Copy link
Contributor Author

I have just created a second-attempt PR to update the definitions over at DT, could you (@dougwilson) check if these are still accurate after a year?

@HoldYourWaffle
Copy link
Contributor Author

I have updated the imported definitions to the current latest DT candidate (PR). I'll update my published fork shortly.

To increase my developer-citizen-karma, I have copy-pasted (and reformatted) the documentation from the README into the type definitions as tsdoc. Unfortunately I couldn't find anything on CookieOptions.signed, CookieOptions.encode, Store.regenerate, Store.load and Store.createSession.

Did I miss something or is there really documentation on these properties/methods?

@HoldYourWaffle
Copy link
Contributor Author

HoldYourWaffle commented Nov 10, 2020

I'm happy to inform you that DefinitelyTyped/DefinitelyTyped#46576 was (finally) merged!

I'd still like these typings to be merged here some day, because (as you might've seen) DT can be a bureaucratic mess...

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

Successfully merging this pull request may close these issues.

None yet

3 participants