Open maxdumas opened 4 years ago
"type": "module"
field: https://nodejs.org/api/esm.html#esm_code_package_json_code_code_type_code_fieldHave any of the library maintainers considered deno support?
I've been passively following the Deno development, and while it has great potential and has done many things right (Rust, TS, security), it's still very immature project. I don't think it makes sense at this point to even consider adding Deno support to large complex Node.js modules like Ink.
If you really want to see this happen, I would recommend forking and trying to implement support for it yourself. Could be a fun exercise. But don't expect anything to be merged upstream anytime soon.
No package.json, no Babel, no Typescript compiler, no need for associated code generators like create-ink-app.
The only thing you need is a package.json, and it can be small. Babel/TypeScript/etc are not required.
Thanks for the response @sindresorhus! Those are definitely fair points, especially regarding (3). I may continue exploring the idea in my own fork. If I am able to get anywhere then I'll definitely keep you posted.
Hi! It's been a year. Deno has published its official 1.x version as well. Since v1.7, we can even compile a deno project into a single binary file. I'd be much happy to see ink supporting it! Any plan so far?
Any word on if this is ever going to happen? We are at Deno 1.8 now and Deno is heavly used on the command line.
Hey, I'm currently spending all my free time on Lotus, so unfortunately I can't promise anything. As Sindre suggested, feel free to experiment with it by forking Ink and let's see what we can do to support it out of the box if possible.
Going to re-open this issue to increase visibility.
I'd love Deno support too, this would be great to pair with https://cliffy.io/
I gave it a go with the following code.
import { render, Text } from "https://esm.sh/ink@3.2.0";
import React from "https://esm.sh/react@18.2.0";
export const Example = () => (
<>
<Text color="green">I am green</Text>
<Text color="black" backgroundColor="white">
I am black on white
</Text>
<Text color="#ffffff">I am white</Text>
<Text bold>I am bold</Text>
<Text italic>I am italic</Text>
<Text underline>I am underline</Text>
<Text strikethrough>I am strikethrough</Text>
<Text inverse>I am inversed</Text>
</>
);
render(<Example />);
But ultimately it failed with:
This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills
This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills
error: Uncaught TypeError: _ is not a function
at https://esm.sh/v90/restore-cursor@3.1.0/deno/restore-cursor.js:2:1092
at https://esm.sh/v90/restore-cursor@3.1.0/deno/restore-cursor.js:2:700
at https://esm.sh/v90/restore-cursor@3.1.0/deno/restore-cursor.js:2:1173
I haven't bothered looking at it any further. I imagine it's likely to be very long & dark rabbit hole for someone to go down.
Also just had a look at https://bun.sh & boy is it fast. It seems to be striving to have better node compat than deno too so it might one day be easier to make this work on bun than deno. Although granted today bun is really just an experiment not a useable bit of software IMO. Defo one to keep an eye on though.
A couple months ago I put in about an hour into making Ink work with Deno, did get it working albeit with the same warning. Screenshot below has two of the builtin demos and the code @brad-jones used above:
Ultimately didn't end up pursuing it further, but it's definitely possible to do!
apparently deno is improving node/npm compatiblity, so it might just work out of the box in the following months https://deno.com/blog/changes#compatibility-with-node-and-npm
Deno 1.25.0 is out, it's now possible to use NPM module specifiers (experimental).
There's still React's obnoxious rAF warning though.
$ deno run --unstable --allow-all ink-test.jsx
// required because ink does some trickery with node's Console object
import console from "https://deno.land/std@0.153.0/node/console.ts";
window.console = console;
import React from "npm:react";
import { render, Box, Text, useFocus } from "npm:ink";
const Focus = () => (
<Box flexDirection="column" padding={1}>
<Box marginBottom={1}>
<Text>
Press Tab to focus next element, Shift+Tab to focus previous element,
Esc to reset focus.
</Text>
</Box>
<Item label="First" />
<Item label="Second" />
<Item label="Third" />
</Box>
);
const Item = ({label}) => {
const {isFocused} = useFocus();
return (
<Text>
{label} {isFocused && <Text color="green">(focused)</Text>}
</Text>
);
};
render(<Focus />)
Edit: raf polyfill - make sure this is the first import!
raf.js
// based on https://gist.github.com/paulirish/1579671
let lastTime = 0;
window.requestAnimationFrame = function (callback, _element) {
let currTime = new Date().getTime();
let timeToCall = Math.max(0, 16 - (currTime - lastTime));
let id = setTimeout(() => callback(currTime + timeToCall), timeToCall);
lastTime = currTime + timeToCall;
return id;
};
window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
ink-test.jsx
import "./raf.js";
import console from "https://deno.land/std@0.153.0/node/console.ts";
window.console = console;
import React from "npm:react";
import { render, Box, Text, useFocus } from "npm:ink";
// ...
Protip: don't use react 18 with deno and ink.
import_map.json
{
"imports": {
"react": "npm:react@17",
"ink": "npm:ink",
"cli-spinners": "npm:cli-spinners"
}
}
You'll just end up with lots of errors around either:
useContext
useState
With the latest Deno. And the above suggestion. This seems to work without the --unstable
flag.
$ deno run --allow-all ink-test.jsx
// required because ink does some trickery with node's Console object
import console from "node:console";
window.console = console;
import React from "https://esm.sh/react@18";
import { render, Box, Text, useFocus } from "https://esm.sh/ink@4";
const Focus = () => (
<Box flexDirection="column" padding={1}>
<Box marginBottom={1}>
<Text>
Press Tab to focus next element, Shift+Tab to focus previous element,
Esc to reset focus.
</Text>
</Box>
<Item label="First" />
<Item label="Second" />
<Item label="Third" />
</Box>
);
const Item = ({label}) => {
const {isFocused} = useFocus();
return (
<Text>
{label} {isFocused && <Text color="green">(focused)</Text>}
</Text>
);
};
render(<Focus />)
Copying above instructions hasn't worked for me when making use of useStdin()
or useFocus()
inside an ink app with deno 1.37.0, tested with Windows/Mac/Linux.
Getting a stdin.ref is not a function
error.
Downgrading to ink 4.4.0 (vs 4.4.1) seems to remove the stdin.ref is not a function
error for me.
App does not exit gracefully with CTRL+C, though.
https://nodejs.org/dist/latest-v20.x/docs/api/net.html#socketref must be missing in Deno then.
https://nodejs.org/dist/latest-v20.x/docs/api/net.html#socketref must be missing in Deno then.
https://deno.land/std@0.158.0/node/net.ts?s=Socket&p=prototype.ref seems to suggest otherwise? I might be mistaken, though.
@vadimdemedes you are right, it's indeed missing. I don't know what the docs above are referring to. Opened an issue.
https://deno.land/std@0.158.0/node/net.ts?s=Socket&p=prototype.ref seems to suggest otherwise? I might be mistaken, though.
That looks like an older version of the standard library. I'm not sure where that code went, since the file does not exist in the latest version of the standard lib, or if it was removed for some reason.
I'm quite sure the standard library is not part of the Deno runtime environment, and I think it's not part of what's included in the import ... from "npm:..."
support in Deno, but I could be mistaken :)
Hopefully you will find help through the issue you filed, @ulken!
@hugojosefson you're absolutely right. Silly me.
I think Node API Compatibility List is a better resource.
Under node:tty
one can read:
Missing ReadStream and WriteStream implementation.
ReadStream
is essential here.
I have managed to use this library with Deno 1.40.4. I could not get useInput
to work because of the difference between Deno and Node with stdin, but I got it working by using the "input" from Cliffy (deno library).
@mabasic I was able to run the demo as well with the latest version of Deno, but among other things, hitting CTRL-C
didn't work. Do you have a snippet or a gist of what you did to get keyboard input to function?
@mabasic I was able to run the demo as well with the latest version of Deno, but among other things, hitting
CTRL-C
didn't work. Do you have a snippet or a gist of what you did to get keyboard input to function?
There is a trick which I have found somewhere in the issues ... I'll try to find it in my code and send you the example
@cowboyd
const handleKeyPresses = useCallback(async (
event: KeyPressEvent,
) => {
if (event.key === "c" && event.ctrlKey) {
exit(); // exits ink
Deno.exit(0); // exits deno process
}
}, []);
useEffect(() => {
keypress().addEventListener("keydown", handleKeyPresses);
return () => {
keypress().removeEventListener("keydown", handleKeyPresses);
};
}, [handleKeyPresses]);
You may want to also consider supporting https://bun.sh/ at the same time, in theory its suppose to be a light replacement, but I confirmed that the display is not getting the inputs when running in bun
https://www.builder.io/blog/bun-vs-node-js has more about the whole bun and other run times ...
I did do a deep dive to see what I could do, but it looks like the biggest issue is the way use input is hooked into the context change detection from process.stdin and the event call backs around it. There are also some defaults of process. but giving up on it now ..
I arrived at here for trying to create tui app by Deno.
With deno v1.43.1, I found the @pethin code works without node:console
and CTRL-C
also works without any tricks🙌
import React from "npm:react";
import { Box, render, Text, useFocus } from "npm:ink";
const Focus = () => (
<Box flexDirection="column" padding={1}>
<Box marginBottom={1}>
<Text>
Press Tab to focus next element, Shift+Tab to focus previous element,
Esc to reset focus.
</Text>
</Box>
<Item label="First" />
<Item label="Second" />
<Item label="Third" />
</Box>
);
const Item = ({ label }) => {
const { isFocused } = useFocus();
return (
<Text>
{label} {isFocused && <Text color="green">(focused)</Text>}
</Text>
);
};
render(<Focus />);
I am on Deno v1.43.3 and my TUI app is using Ink v5.0.0 without any hacks.
My only gripe is my app now requires certain read and env permissions after installing the react
and ink
packages. The app requires these permissions even after compiling the executable with deno compile
. More specifically, it requires read access to the current working directory and .cache/deno/npm/registry.npmjs.org/yoga-wasm-web/0.3.3/dist/yoga.wasm
; as well as access to all environment variables. Does anyone know of a way around this? I'd rather not grant all permissions by supplying -A
as that defeats the purpose of Deno's sandboxing capability.
deno
seems like a great environment for runningink
, as it aims to be a simple, secure, and fast way to ship JavaScript executables to users while being extremely light in setup for developers. Looking atink
and putzing around a bit (I'm admittedly pretty new todeno
andink
), it seems that there are a few issues with its current setup that make it difficult to use withdeno
:ink
does not publish a version of itself as a bundled ESM.deno
requires that packages be consumed as ESM, and that ESM would likely have to have bundled with it all ofink
s dependencies. To fix that would require introducing an ESM bundling step as part of the build for the package, using something likerollup
. I took a quick stab at doing that in a fork, which can be found here. The fork successfully bundles but still does not work indeno
."module"
field inpackage.json
. Then package managers and CDNs that vend ES6 modules, like pika.dev, could pick upink
and serve the ESM bundle. Note how currently pika.dev hasink
listed but cannot serve it because there is no"module"
field in thepackage.json
.ink
or its npm dependencies have on the Node standard library or Node-specific runtime behavior may need to be refactored to accommodate adeno
environment. See here for thedeno
standard library. It does deviate somewhat from the Node standard library. I have not taken the time to actually identify which libraries or parts ofink
might fall under this category, but this could be the largest chunk of work to providedeno
support and will potentially involve updating multiple libraries.Have any of the library maintainers considered
deno
support? Points (1) and (2) seem valuable in general, even outside of a goal ofdeno
support, as moving the JS ecosystem towards an ESM-first world will make a big impact in the usability of libraries in a more progressive, lightweight manner. However, withdeno
, getting up and started withink
could be as simple as (sloppily adapting the Counter demo):Note that the code hasn't changed much, but the real difference is that this one file would be the entire project for getting started with an
ink
app. Nopackage.json
, no Babel, no Typescript compiler, no need for associated code generators likecreate-ink-app
. It would allow new developers and folks just experimenting to useink
much more quickly and easily.Comments? Thoughts?