-
-
Notifications
You must be signed in to change notification settings - Fork 267
Conversation
package.json
Outdated
}, | ||
"scripts": { | ||
"test": "standard && node test | faucet" | ||
"test": "standard && ts-node --no-cache test | faucet" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be in addition to node tests. Tests passing in TS is not a guarantee for tests passing in node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can switch back to having both.
test/common.js
Outdated
|
||
assert(levelup.errors === errors) | ||
assert(leveluperrors === errors) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a requirement for TS? I like the previous better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately. without moving the test to ts (so you can trick the compiler) I'm not sure how to go around it. typescript treats it as an es2015 module.
The alternative would be to have specific typescript-based tests for common things - that way the typescript stuff would not interfere at all with the js tests. I don't mind doing that with something like mocha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have another stab; might be a way to add the errors onto the default too.
tsconfig.json
Outdated
"compilerOptions": { | ||
"target": "es2015", | ||
"moduleResolution": "node", | ||
"noEmitOnError": true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't notice this before. What does noEmitOnError
mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally a fail-safe to ensure it doesn't just warn then run, but fails completely. Its probably not needed as it defiantly was failing the test before without it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK so it's just a confusing name :)
package.json
Outdated
@@ -33,35 +33,39 @@ | |||
"storage", | |||
"json" | |||
], | |||
"main": "lib/levelup.js", | |||
"main": "lib/levelup.js", | |||
"typings": "lib/levelup.js", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be lib/levelup.d.ts
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to suggest us using var levelup = require('levelup')
instead of var levelup = require('levelup').default
because they are all the same and the second one looks ugly. :-]
@@ -3,7 +3,7 @@ | |||
* MIT License <https://github.com/level/levelup/blob/master/LICENSE.md> | |||
*/ | |||
|
|||
var levelup = require('../lib/levelup.js') | |||
var levelup = require('../lib/levelup.js').default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is not necessary because we had exported both LevelUP
and default
.
See:
Line 294 in f93790f
module.exports = LevelUP.default = LevelUP |
That will make sure the code will pass the following assertion:
const levelup1 = require('../lib/levelup.js')
const levelup2 = require('../lib/levelup.js').default
assert(levelup1 === levelup2)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its down to typescript - you cannot have both export default
and export =
in the typings. So the typings have gone with the default
export exclusively for typescript users.
It means when you run the normal js through the typescript compiler it will complain if you don't use the default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, understand.
Then how about we do a module.exports = LevelUP.default = LevelUP.LevelUP = LevelUP
?
Then we will be able to do a var { LevelUP } = require('../lib/levelup.js')
, which would be better than require('...').default
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of require('...').default
- but because it's only in the tests, I prefer it over more hacks in lib/levelup.js
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I don't think we need more hacks to the export; Its just for the test here because we're pushing the (mostly) unadulterated js through the compiler. normal javascript users:
const levelup = require('levelup')
normal ts users:
import levelup from 'levelup'
you can always do const {default:levelup} = require('levelup');
but I suspect we might run into issues if we're still testing on an older node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with default
too because it's just unit test script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward to the new NPM version with typings!
README.md
Outdated
@@ -24,6 +24,7 @@ LevelUP | |||
* <a href="#events">Events</a> | |||
* <a href="#extending">Extending LevelUP</a> | |||
* <a href="#multiproc">Multi-process access</a> | |||
* <a href="#typings">Typescript </a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: stylize like the official "TypeScript"? Same below
README.md
Outdated
Typescript | ||
---------- | ||
|
||
LevelUP comes with typescript definitions that can automatically infer options based on a typed `abstract-leveldown` implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the simpler form: "infer options from a typed"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@zixia any chance you could pull/fork from me and test this locally? if you do
in the the local |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe squash this
Does the wiki page need updating? |
No problem, will do it later today. |
No need, looks like @MeirionHughes already did |
@MeirionHughes I use your repository to install It passed my My commit to replace P.S. I think we should consider to create a new repository for TypeScript typing testing, because all the See the details:┌ zixia@zixia-desktop:~/git/flash-store [18:33:10] tty:[0] jobs:[0]
└ (MeirionHughes) $ grep MeirionHughes package.json
"levelup": "MeirionHughes/levelup",
┌ zixia@zixia-desktop:~/git/flash-store [18:33:13] tty:[0] jobs:[0]
└ (MeirionHughes) $ npm run lint
> flash-store@0.0.20 lint /home/zixia/git/flash-store
> tslint --project tsconfig.json && npm run clean && tsc --noEmit
> flash-store@0.0.20 clean /home/zixia/git/flash-store
> shx rm -fr dist/* bundles/*
┌ zixia@zixia-desktop:~/git/flash-store [18:33:18] tty:[0] jobs:[0]
└ (MeirionHughes) $ npm run dist
> flash-store@0.0.20 dist /home/zixia/git/flash-store
> npm run clean && npm run build && npm run rollup && npm run dist:es6to5
> flash-store@0.0.20 clean /home/zixia/git/flash-store
> shx rm -fr dist/* bundles/*
> flash-store@0.0.20 build /home/zixia/git/flash-store
> tsc --module es6
> flash-store@0.0.20 rollup /home/zixia/git/flash-store
> rollup -c
(!) Some options have been renamed
https://gist.github.com/Rich-Harris/d472c50732dab03efeb37472b08a3f32
options.entry is now options.input
options.moduleName is now options.name
options.sourceMap is now options.sourcemap
options.dest is now options.output.file
options.format is now options.output.format
dist/flash-store.js → bundles/flash-store.es6.umd.js...
(!) Mixing named and default exports
Consumers of your bundle will have to use bundle['default'] to access the default export, which may not be what you want. Use `exports: 'named'` to disable this warning
(!) Missing shims for Node.js built-ins
Creating a browser bundle that depends on 'path'. You might need to include https://www.npmjs.com/package/rollup-plugin-node-builtins
(!) `this` has been rewritten to `undefined`
https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined
dist/flash-store.js
1: var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
^
2: return new (P || (P = Promise))(function (resolve, reject) {
3: function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
...and 9 other occurrences
(!) Unresolved dependencies
https://github.com/rollup/rollup/wiki/Troubleshooting#treating-module-as-external-dependency
path (imported by dist/flash-store.js)
app-root-path (imported by dist/flash-store.js)
brolog (imported by dist/flash-store.js)
rimraf (imported by dist/flash-store.js)
encoding-down (imported by dist/flash-store.js)
leveldown (imported by dist/flash-store.js)
levelup (imported by dist/flash-store.js)
(!) Missing global variable names
Use options.globals to specify browser global variable names corresponding to external modules
path (guessing 'path')
app-root-path (guessing 'appRootPath')
brolog (guessing 'brolog')
rimraf (guessing 'rimrafProxy')
encoding-down (guessing 'encodingProxy')
leveldown (guessing 'leveldownProxy')
levelup (guessing 'levelupProxy')
created bundles/flash-store.es6.umd.js in 45ms
> flash-store@0.0.20 dist:es6to5 /home/zixia/git/flash-store
> tsc --out ./bundles/flash-store.umd.js --target es5 --allowJs bundles/flash-store.es6.umd.js --lib es6,dom
┌ zixia@zixia-desktop:~/git/flash-store [18:33:23] tty:[0] jobs:[0]
└ (MeirionHughes) $ npm t
> flash-store@0.0.20 test /home/zixia/git/flash-store
> npm run lint && npm run test:unit
> flash-store@0.0.20 lint /home/zixia/git/flash-store
> tslint --project tsconfig.json && npm run clean && tsc --noEmit
> flash-store@0.0.20 clean /home/zixia/git/flash-store
> shx rm -fr dist/* bundles/*
> flash-store@0.0.20 test:unit /home/zixia/git/flash-store
> blue-tape -r ts-node/register -r source-map-support/register "src/**/*.spec.ts" "tests/**/*.spec.ts"
TAP version 13
# constructor()
ok 1 should not throw exception with a non existing workDir
# Store as iterator
# async iterator for empty store
ok 2 should create the workDir
ok 3 should get empty iterator
# async iterator
ok 4 should get key back
ok 5 should get val back
ok 6 should iterate once
# get()
# return null for non existing key
ok 7 should get null for not exist key
# store string key/val
ok 8 should get VAL after set KEY
# store object value
ok 9 should get VAL_OBJ after set KEY
# put()
ok 10 should put VAL for KEY
# count()
ok 11 should get count 0 after init
ok 12 should get count 1 after put
# keys()
ok 13 should get 0 key after init
ok 14 should get back the key
ok 15 should get 1 key after 1 put
# values()
ok 16 should get 0 value after init
ok 17 should get back the value
ok 18 should get 1 value after 1 put
1..18
# tests 18
# pass 18
# ok |
@zixia How do you make those "details"? Just type opening and closing tags manually or do you use some sort of tool for it? |
@ralphtheninja Ha, I learned this trick from someone else on Github before... I guess it's a html5 tag which will be rendered by Github: <details>
<summary>
See the details:
</summary>
bla...
bla...
bla...
</details> |
@MeirionHughes Mind rebasing this onto latest master? |
@MeirionHughes this does sound like we should have continuous integration tests, as @zixia suggested. Or do you think that's overkill and that the typings will become stable soon? |
A separate repo for typescript testing - to be used when anyone PRs to I think it more feasible to have one repo for most As for the current typing and this PR - I thought I'd managed to the get the iterator generic working perfectly, but somehow its now pulling up that extra type union (see above). While its not perfect, it still does default to maybe @zixia fancies another stab at typings. Get a fresh perspective. |
There are tools that can help with this. It's also fine to start off with something that requires manually triggering builds. Esp. because the alternative (all typings in one repo), like you say, is more difficult to maintain with regards to versioning.
Sounds like a plan. You could also open an issue for this and tag it with |
Need to make a decision on this because typescript users are having issues. #500 There is one minor imperfection with regard to the inferring of iterator options (typed). If you explicitly type out the LevelUp type manually there is no issue. That said, these generics are insane... I think there are 9 generic types on LevelUp. An alternative would be to strip the generics entirely, remove support for infering from the given AbstractLevelDown and type LevelUP with a very limited set of very common options, while allowing other (untyped) options to be passed, where applicable. Personally, while it was * cough * fun to get bend typescript to infer all the option types based off the EDIT: Poll locked. cc: @gpresland, @zixia @earslap @vweevers @ralphtheninja @juliangruber |
@MeirionHughes what do you mean by common options? What are those? |
Any option, or set of options, that is the same across all |
I don't feel qualified to vote. Defer to your judgement on this. |
me neither. Which is why I'm starting to be quite sure that we shouldn't land typing without a team that maintains them, ie more than one person who is on board and able to commit. |
My two cents is to landing the current typing definition, and then we will be able to maintain it. I'm currently using the following dependencies for my TypeScript project: "encoding-down": "^2.3.1",
"leveldown": "^2.0.0",
"levelup": "github:MeirionHughes/levelup", |
What though if we need to do a major types change? For now, we could merge it but say they are unstable and might break without a major release. |
@juliangruber I'll be ok with "the typings are unstable and might break without a major release" because:
|
It would be great to make TS developers real first class citizens for leveldb, and that's why we need to get the integration right from the start. Is everyone ok with following a stability index as nodejs does for the typings, and mark them experimental at first? |
Sounds good to me! |
@sandersn Thanks for the fixes on abstract-leveldown; would welcome any thoughts you had on the |
What needs to happen here? Add a note to the readme about the typing stability, rebase, and merge? |
@vweevers yeah probably; its been stalled because there is no right answer at the moment; the complexity of typing the high-level In any case, as far as I'm aware the current typings available from defiantly-typed are still out-of-date: http://definitelytyped.org/docs/levelup--levelup/modules/levelup.html |
Then let's get it in as-is. Perhaps usage in the wild will lead to more feedback. Do you have the time or do you want someone to take over? |
@vweevers yes, if possible. Spinning too many plates at the moment to give this the attention it deserves. |
@MeirionHughes @vweevers I vote for getting it in as-it-is because as @MeirionHughes said, I'm happy with it. :-p |
Is there something inherently wrong with the types that is keeping this from being merged? Been using MeirionHughes' repo for the last month and had no problems so far. |
I'd like to suggest to merge the types this month instead of using the repo from MeirionHughes. @Level/typescript |
I'll review this as soon as I can and hopefully pull the trigger. [edit] I tried to get my head into it on the weekend, but with kids running around behind me during the day its difficult. 👪 |
An insane alternative to using generics... type unknown = {} | undefined | null;
interface AbstractOptions {
GO: unknown;
K: unknown;
V: unknown;
GET: unknown;
}
interface AbstractLevelDown extends AbstractOptions {
GO: {
keyAsBuffer?: boolean;
valueAsBuffer?: boolean;
},
K: string | Buffer;
V: string | Buffer;
}
interface CodecEncoder<T=unknown> {
T: T;
encode: (val: T) => Buffer;
decode: (val: Buffer) => T;
buffer: boolean
type: string
}
interface Codec<K=unknown, V=unknown> {
K: K;
V: V;
keyEncoding?: CodecEncoder<K>
valueEncoding?: CodecEncoder<V>
}
interface EncodingDown<O extends AbstractOptions, C extends Codec> extends AbstractOptions {
C: C;
K: C["K"];
V: C["V"];
GO: O["GO"] & {
valueAsBuffer?: boolean,
valueEncoding?: CodecEncoder
}
GET(key: this["C"]["K"], cb: (value: this["C"]["V"]) => void);
GET(key: this["C"]["K"], options: this["GO"] & { valueAsBuffer: false }, cb: (value: this["C"]["V"]) => void);
GET(key: this["C"]["K"], options: this["GO"] & { valueAsBuffer: true }, cb: (value: Buffer) => void);
GET<VE extends CodecEncoder>(key: this["C"]["K"], options: this["GO"] | { valueEncoding: VE }, cb: (value: VE["T"]) => void);
}
interface LevelUp<AD extends AbstractOptions> {
GO: AD["GO"];
K: AD["K"];
V: AD["V"];
GET(key: this["K"]): Promise<this["V"]>;
GET<V = this["V"]>(key: this["K"], options: this["GO"]): Promise<V>;
get: AD["GET"] & this["GET"];
}
declare function encoding<O extends AbstractOptions, C extends Codec>(db: O, c: C): EncodingDown<O, C>
declare function levelup<O extends AbstractOptions>(db: O): Pick<LevelUp<O>, "get">
type MyKey = {
foo: string;
}
type MyValue = {
bar: string;
}
type AltValue = {
ray: string;
}
let codex = {} as Codec<MyKey, MyValue>
let encoder = encoding({} as AbstractLevelDown, codex);
let db = levelup(encoder);
async function main() {
const alt = {} as CodecEncoder<AltValue>;
db.get({ foo: "hello" }, (v) => {
// v is MyValue
});
db.get({ foo: "hello" }, { valueEncoding: alt }, (v) => {
// v is AltValue
});
db.get({ foo: "hello" }, { valueAsBuffer: true }, (v) => {
// v is Buffer
});
let a = await db.get({ foo: "hello" }); // a is MyValue
let b = await db.get({ foo: "hello" }, { valueEncoding: alt }); // b is still MyValue :(
let c = await db.get<AltValue>({ foo: "hello" }, { valueEncoding: alt }); // c is AltValue
} ... yeah |
Some good news at least is that type inference is landing in typescript 2.8 ( missed this as I thought we'd only be getting conditional types). microsoft/TypeScript#21496 So in typescript 2.8 we should hopefully be able to just infer options and return types from the enclosed db and avoid the complex generics. [Update]: I tested it out; unfortunately it falls short because the conditional-mapping + inference doesn't support overloaded functions. So, for example, Promisifying the |
Figuring out what to do for level typings was a fricking pain, having to muddle through the different repos and issues. This should really get merged, if only to make it clear that there ARE working typings and that they are not stable.. I couldn't find working typings for the promisified version published. |
We're considering moving the typings out of Level and into DefinitelyTyped. Please see Level/community#16. |
.default
for some level stuff. This is because the typescript compiler will complain because those repositories now have es2015 default exports.