-
Notifications
You must be signed in to change notification settings - Fork 39
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
The official "addressbook" example working in JS #56
Conversation
.travis.yml
Outdated
@@ -12,13 +12,14 @@ before_install: | |||
- export PATH="$HOME/.yarn/bin:$PATH" | |||
install: | |||
- yarn --frozen-lockfile | |||
- yarn run bootstrap -- --frozen-lockfile |
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 made bootstrapping a "post install" of the monorepo.
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.
Great idea. 👍
"**/node_modules": true, | ||
"**/bower_components": true, | ||
"**/lib": true, | ||
"**/lib-test": 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.
Let me know if you can't bear these changes. Personally i find keeping the generated code out of the search results is more important that keeping it out of the IDE, I like to poke around in it occasionally.
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.
That shouldn't bother me. It's also nice for tracing unmapped stack traces (tsc's output is super nice and legible, unlike babel...).
npm install -g capnpc-ts | ||
npm install -g capnpc-ts # For TypeScript | ||
# OR | ||
npm install -g capnpc-js # For JavaScript |
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.
Have you registered these npm names, or whatever the process is?
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.
As you'll want to register capnpc-js too
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.
"Registering" is simply a matter of publishing first.
Suppose I'll just do that today with zero fanfare so nobody tries using it yet...
@@ -5,11 +5,8 @@ | |||
}, | |||
"description": "Strongly typed Cap'n Proto implementation for the browser and Node.js using TypeScript", | |||
"devDependencies": { | |||
"@types/benchmark": "1.0.30", |
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.
these don't need to be added here, lerna bootstrap --hoist
effectively automatically takes care of this for you.
"codecov": "^2.2.0", | ||
"glob": "^7.1.2", |
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.
you added this to dependencies but I think its just a devDependency, but let me know if i was mistaken.
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.
Correct. Good catch.
package.json
Outdated
"benchmark": "gulp benchmark", | ||
"build": "gulp build", | ||
"ci": "gulp lint && gulp coverage && codecov --disable=gcov", | ||
"ci": "gulp lint && gulp coverage && codecov --disable=gcov && cd js-examples && ./test.sh", |
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.
We should probably have a gulp ci target or something?
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.
Yes. I'm also a bit reticent about having test.sh
be UNIX only, since that means you need a *NIX box to work on this library.
Sigh maybe that's fine.
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.
The upstream source does it. We want simplicity in this package as it serves as the basic usage example. But I'm happy to add a .bat for Windows perhaps?
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 mean it's vital for the library itself to be cross-platform (and it very much is).
For development... eh. If people want to actually do dev on Windows I'll accept a patch but this isn't really worth fussing about now.
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.
Us windows devs are pretty used to porting those npm scripts to batch to get things working.
Seriously however I don't see much issue with having a small shell script, a small batch script and declaring ourselves fully cross platform.
package.json
Outdated
"coverage": "gulp coverage", | ||
"lerna": "lerna", |
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.
nifty to have npm run lerna -- ...
but let me now if you'd prefer not to have 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.
Doesn't hurt. Something like npx seems like the real answer.
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.
Nifty tool, thanks.
Codecov Report
@@ Coverage Diff @@
## master #56 +/- ##
=======================================
Coverage 75.47% 75.47%
=======================================
Files 48 48
Lines 2924 2924
Branches 229 229
=======================================
Hits 2207 2207
Misses 657 657
Partials 60 60 Continue to review full report at Codecov.
|
Gotta fix up the apt-get installs to work in the container. I'll deal with that tomorrow as its late here in LA. |
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.
This is great. The build failure is the only thing blocking this, this otherwise looks good to merge as is.
Also, please add yourself to HUMANS.md if you like!
"codecov": "^2.2.0", | ||
"glob": "^7.1.2", |
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.
Correct. Good catch.
package.json
Outdated
"coverage": "gulp coverage", | ||
"lerna": "lerna", |
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.
Doesn't hurt. Something like npx seems like the real answer.
} | ||
|
||
function main() { | ||
// TODO Not sure if we have dynamic schema usage available yet |
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.
Dynamic schemas will likely never be a thing in this library. https://groups.google.com/d/msg/capnproto/lESKRE_pix8/ZB8ie0WuBgAJ
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.
If you have a look at the C++ example https://github.com/capnproto/capnproto/blob/master/c%2B%2B/samples/addressbook.c%2B%2B#L264 it appears that here "dynamic" doesn't mean reading the schema at runtime. Rather I think it just pulls out the raw schema's from the compiled struct. eg. The member at: https://github.com/capnproto/capnproto/blob/cff543590ab25652ce56e9178dd499a8a69e08f7/c%2B%2B/src/capnp/schema.capnp.c%2B%2B#L689
so it can use it in a "dynamic" fashion. These schema's seem somewhat equivalent to our ObjectSize objects, but carry a bit more information.
Obviously in JavaScript we could just do things like:
function setFieldInCapnpStruct ( struct, fieldname, value ) {
// ignore my lack of attention to the casing
struct['set' + fieldname ](value);
}
function printAllCapnpFields ( struct ) {
for(var prop in struct) {
// I'm improvising here, my javascript is patchy, but you should get the idea
if (/*has own property etc*/) {
if(prop.startsWith('get') && struct[prop] instanceof Function) {
console.log(prop.replace('get', '') + ' = ' + struct[prop].apply(struct));
}
}
}
}
Which means having a dynamic API to the capnp data does not yield an increase in value anywhere near the same as in C++ with its meagre reflection tools out of the box.
However, I think it might still be preferable to support these api's if we can. As you'll still receive much better editor type information when doing things similar to the above example, and they'd be even simpler and more performant than what I've shown above. Also, note what I did above was super hacky and doesn't handle anywhere near enough edge cases which wouldn't even be a concern if you had the first class type information from capnp, so if someone tried the above in lieu of access to the compiled schema's it would be harder still.
Might be good to get @kentonv 's thoughts here too? What do you think about dynamic api support that doesn't involve parsing schema's at runtime?
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.
A dynamic API is useful for writing generic algorithms that operate on arbitrary Cap'n Proto objects. For example, say you wanted to write a library for converting capnp types to/from JSON. This kind of thing usually requires schema information (maybe you can infer everything you need from native Javascript reflection, but often you can't). So your options are a dynamic API, or offline code generation.
Another use case that's particularly relevant to Javascript: It would be really cool to write a dynamic RPC interface explorer client. The client could connect to an RPC endpoint and dynamically request the interface's schema, then present a UI to the user to explore and manually invoke methods. In this case you don't even know the schemas at compile time, so a dynamic API is probably the only option.
This stuff probably isn't necessary for V1 but I think people will want it eventually.
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.
💯 that clears up some ideas actually on how to implement toJSON/fromJSON. Upweights #45 since we'll need to have the schema compiler add even more metadata to the struct classes.
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 write it in such a way that the schema object is easily serializable, and you can go from new CustomStruct()
to new DynamicStruct(CustomStruct._capnpSchema)()
.
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 write it in such a way that the schema object is easily serializable
I'd recommend embeding the actual capnp-encoded schema, which is what C++ and other code generators do. This way you can use the same code to dynamically process compiled-in types as well as schemas received dynamically over the wire, and you can also easily send your local schemas back out over the wire if desired.
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.
💡 !
# Used for release testing. | ||
|
||
set -exuo pipefail | ||
|
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.
You can avoid the need to cd
to js-examples
like so:
examples_dir=`dirname $0`
capnpc -o $examples_dir/node_modules/.bin/capnpc-js addressbook.capnp
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 have to add $examples_dir to all the local file references, no? addressbook.capnp, addressbook.js, etc?
What about we cd `dirname $0`
? It allows the script to get run from anywhere but the script still gets to assume its cwd.
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.
Both would be fine.
package.json
Outdated
"benchmark": "gulp benchmark", | ||
"build": "gulp build", | ||
"ci": "gulp lint && gulp coverage && codecov --disable=gcov", | ||
"ci": "gulp lint && gulp coverage && codecov --disable=gcov && cd js-examples && ./test.sh", |
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.
Yes. I'm also a bit reticent about having test.sh
be UNIX only, since that means you need a *NIX box to work on this library.
Sigh maybe that's fine.
packages/capnpc-js/src/index.ts
Outdated
/** | ||
* The equivalent of tsconfig.json used when compiling the emitted .ts file to .js. | ||
* | ||
* TODO: This should be configurable somehow? |
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.
Let's drop this comment entirely. I'm fine with this not being configurable until someone can present a use-case for 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.
Righty
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.
Leaving a little about the motivation for the settings as they are.
packages/capnpc-ts/src/generators.ts
Outdated
ts.createPropertyAccess(THIS, '_getList'), | ||
__, | ||
[offsetLiteral, listClassIdentifier]); | ||
init = ts.createCall( |
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 leave it up to you, but you might want to pull in this commit instead.
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.
Not sure if you were expecting some fancy git tricks, but my git-foo is not the best, I'm just gonna add your changes to my own.
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.
That's fine. I do have some git-fu for you though; add git@github.com:jdiaz5513/capnp-ts
as a remote to your fork next time: https://help.github.com/articles/configuring-a-remote-for-a-fork/
Then after running a pull once you can easily cherry pick a commit:
git pull
git cherry-pick 32df29647c3f9dc181b9b62b9d4eaef308fd0292
Slaps that commit as-is on top of your HEAD, and lets you resolve if there's a merge conflict.
|
||
chunk.copy(reqBuffer, i); | ||
const reqBuffer = new Buffer(chunks.reduce((l, chunk) => l + chunk.byteLength, 0)); |
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 I started the buffer byte length count at -1 because of strange behavior I was observing on OSX. 0 appears to be the correct starting point for the reducer, though, so this line is now correct.
I'll try to repro again later on OSX and come up with a patch that works across platforms if it's actually broken there. On my Arch box this works 💯.
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 this was breaking on osx for me (I was losing 1 byte at the end) which is why I changed it. I'm pretty sure that application code isn't meant to literally be passed an eof byte, pretty sure the underlying machinery in c runtime or somewhere is meant to turn it into a state change on the file descriptor and not feed it to you as data, I have no idea how you managed to receive an eof byte...
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 I misspoke on the c runtime thing. Sounds more like maybe you edited a binary codegenrequest in a text editor then piped it to stdin of the plugin directly and maybe it got an eof byte added by the editor?
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.
Heyo! That's exactly what happened. 😁
Let's uh, leave it at 0 and pretend -1 never happened.
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.
Clearly the capnproto spec just needs to allow trailing EOF bytes and we'd be good here.
@@ -375,6 +383,8 @@ export function generateStructFieldMethods( | |||
|
|||
default: | |||
|
|||
// TODO Maybe this should be an error? |
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.
Oh, I'd actually love your thoughts on this @jdiaz5513 ?
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.
It should log a warning to console.error
: "CAPNP-TS: Ignoring code generator request for unsupported struct field type: %s"
Welp, the |
So the good news is that the CI works now! :if_only_gh_had_party_parrot: |
It works? Ship it. Don't care if the CI takes 3 minutes longer. 30 mins would be nasty. If you really want, look into making a debian package. It's easier than you think. |
This introduces capnpc-js, and a new js-examples package that should be prominent within the repo, and have minimal dependencies to serve as a reference. It doubles as a full integration test of the system (although it's a little light on validation, as is the original in the C++ repo).
This introduces capnpc-js, and a new js-examples package that should be prominent within the repo, and have minimal dependencies to serve as a reference. It doubles as a full integration test of the system (although it's a little light on validation, as is the original in the C++ repo).
This introduces capnpc-js, and a new js-examples package that should be prominent within the repo, and have minimal dependencies to serve as a reference. It doubles as a full integration test of the system (although it's a little light on validation, as is the original in the C++ repo).
This introduces
capnpc-js
, and a newjs-examples
package that should be prominent within the repo, and have minimal dependencies to serve as a reference. It doubles as a full integration test of the system (although it's a little light on validation, as is the original in the C++ repo).