tootallnate / nx.js Goto Github PK
View Code? Open in Web Editor NEWJavaScript runtime for Nintendo Switch homebrew applications
Home Page: https://nxjs.n8.io
License: MIT License
JavaScript runtime for Nintendo Switch homebrew applications
Home Page: https://nxjs.n8.io
License: MIT License
When calling clear after already clearing before, the runtime throws an Error
localStorage.clear();
localStorage.clear();
I would expect that no error is thrown (see web browser behavior)
https://developer.mozilla.org/en-US/docs/Web/API/File_System_API
The entry points into these interfaces on the Web require user interaction, which isn't necessary nx.js. So we can implement lower level entry points into these interfaces here. Perhaps something like:
Switch.openFile() -> Promise<FileSystemFileHandle>
Switch.openDir() -> Promise<FileSystemDirectoryHandle>
full error:
There was an error during the cloning process:
DegitError: could not find commit hash for v0.0.17
at Degit._cloneWithTar (C:\Users\andrei1010\AppData\Local\npm-cache\_npx\f598e7a88fe11b20\node_modules\degit\dist\index-688c5d50.js:14258:10)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Degit.clone (C:\Users\andrei1010\AppData\Local\npm-cache\_npx\f598e7a88fe11b20\node_modules\degit\dist\index-688c5d50.js:14096:4) {
code: 'MISSING_REF',
ref: 'v0.0.17'
}
x Canceled
npm ERR! code 1
npm ERR! path C:\Users\andrei1010
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c create-nxjs-app
npm ERR! A complete log of this run can be found in: C:\Users\andrei1010\AppData\Local\npm-cache\_logs\2023-09-28T14_25_55_116Z-debug-0.log
log file:
Hallo, thanks for this awesome project!
When I fetch an url that is being redirected, then nothing happens and it just returns 302. I see the static method redirect in the code base, but is never used. The default option for redirect in fetch seems to be 'follow' tho.
Does someone have any hints? Thanks!
nx.js can install updates or DLC using NSP files. For example, switch.install(path).
This project looks awesome! I would love to use it to build a custom game launcher with more features, similar to uLaunch. I know the API's are still in progress, but was wondering if there's already a way to get the list of games on the device and launch them.
Tesla-Menu support?
Error.prepareStackTrace
has been added to QuickJS in this commit, so it should be possible to implement native source maps to the err.stack
property.
Look into using jridgewell/trace-mapping
.
I did the getting started documentation, but the app doesn't appear.
Does the Switch need to be modded?
Could be like web bluetooth (like what chromium-based browsers use) if that makes things easier, but all in all I think it would just be interesting to be able to look for, connect to, and communicate with nearby Bluetooth LE devices, as spherov2.js would be pretty nice to have as something I could use in a Switch homebrew app, plus other people might think of better ways to utilize bluetooth here, like maybe communicating with a smart phone to transfer things like system info?
EDIT: Turns out safari doesn't support web bluetooth. Why the hell is such a spectacular thing ONLY supported in Chromium? (chrome, edge, opera, etc)
Consider implementing the WinterCG Socket
API proposal: https://sockets-api.proposal.wintercg.org/
https://developer.mozilla.org/en-US/docs/Web/API/Screen
It would still implement the Canvas
API.
For better compat with web-based modules, we need window
. For example, xterm-headless
relies on checking for this prop. Make globalThis
be an instance of the Window
class.
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
I would like to move away from the non-standard "frame" event on the Switch
namespace, and encourage usage of requestAnimationFrame()
instead.
Currently, the Switch
global is a variable that is an instance of the SwitchClass
class.
Instead, Switch
should be a singleton module that is defined as:
import * as Switch from './switch';
export type * as Switch from './switch';
def('Switch', Switch);
This way, it will be a namespace at the TypeScript and TypeDoc level, and we get rid of SwitchClass
entirely.
The nro application prompts an error when pressing +
to exit:
Originally posted by @hunshikan in #38 (comment)
Hello, when I try to remove a file it throws an error that the file or directory has not been found. Deleting folders works tho.
Images can currently be loaded with new Image()
, but the API for it is kind of dated, i.e.:
const { icon } = Switch.Application.self;
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0);
};
img.src = URL.createObjectURL(new Blob([icon]));
With createImageBitmap()
/ ImageBitmap
, we can use a nice promise-based API instead:
const { icon } = Switch.Application.self;
const img = await createImageBitmap(new Blob([icon]));
ctx.drawImage(img, 0, 0);
Something that works with envSetNextLoad().
At current stage, the app only supports loading installed titles/cart titles. I need it to launch retroarch nro, for instance.
Probably by leveraging the mbedtls
C library (which is already available on Switch ports in devkitpro), we need to expose a mechanism to upgrade a TCP socket connection to TLS. Possibly by having a startTls(): Socket
function on the Socket interface.
Once this exists, then it will be possible to implement the https:
protocol in fetch()
.
fetch()
currently requires an absolute URL.
For compat with i.e. browsers, or Deno with --location
flag, fetch()
should work with a relative path, which would resolve based off of import.meta.url
. Ex:
fetch('hello.wasm');
// should be the same as:
fetch(new URL('hello.wasm', import.meta.url));
// Examples:
// "romfs://hello.wasm" when `main.js` is packaged into the RomFS
// "sdmc://switch/hello.wasm" when entrypoint was `/switch/nxjs.js`
If this is implemented before #26, then replace import.meta.url
with Switch.entrypoint
, until that issue is resolved and then switch to the preferred import.meta.url
value in the future.
Hey so your http package works as expected. I struggeled a bit to get POST body working, but your tests helped a lot!
I wanted to ask if it would be possible to spawn a web browser like in this project:
https://github.com/crc-32/BrowseNX
In combination with the http package this could enable writing feature rich local web apps.
When I have a custom icon.jpg present in the root, It will show the default homebrew icon with the exclamation point.
The log states it is using the custom icon.jpg. I used an icon from a different homebrew of mine to make sure it has the proper dimensions.
Currently, only the first parameter is supported. Any additional params are ignored.
Subscribe to the appletHook
to get a callback when the operation mode changes:
void onAppletEvent(AppletHookType type, void* param) {
if (type == AppletHookType_OnOperationMode) {
bool docked = appletGetOperationMode() == AppletOperationMode_Console;
// invoke JS function to trigger "resize" event
}
}
// in main
AppletHookCookie cookie;
appletHook(&cookie, onAppletEvent, NULL);
window
"resize" eventpreventDefault()
on the "resize" event?Hey. I have the problem, that I cannot write large files, because I need to keep the whole blob in memory. Is it possible to implement an fs function to append a buffer to a file? This way I could write in chunks.
Thanks!
Hey,
I am facing issues building your tests.
I get the following error: The module "./src/index.js" was not found on the file system.
I could monkey-patch it by adding the src folder from your uvu fork to node_modules/uvu
.
Creating an nro also failed and I had to install and use nxjs-pack
.
Thanks!
It would be awesome if one could access the Switch album through nxjs, people could, for example, create apps that upload the taken screenshots to an online service, or serve a simple webapp for browsing the screenshot files on their PC (like on the stock OS with the mobile app feature).
I've tried to come up with a small data schema for reading album entries by looking at the documentation over at https://switchbrew.org/wiki/Capture_services and tried to fit it into a JS API as best as I could. I bet there is tons of room for improvement, especially coming from a TypeScript standpoint.
Switch
Album
Mount() [function]
Unmount() [function]
isMounted [bool]
usage []
fileSize []
Files [array]
File
Delete() [function]
file [blob]?
thumbnail [blob]?
programId []
fileName []
storage [nand,sd]
dateTime [datetime]
uniqueId []
contentType [screenshot,movie,extramovie]
I'm sure we will need to manually mount/unmount the album, especially since they can get quite big. File & thumbnail were set as blob in this schema because that's what ultimately is utilized with Switch.Application's icons already.
I've tried to come up with three examples utilizing the API.
Switch.Album.Mount();
console.log(`Album Usage: ${Switch.Album.usage}`);
console.log(`Album Size: ${Switch.Album.fileSIze}`);
for (const { file } of Switch.Album.Files) {
console.log(`-- ${file.uniqueId} --------`);
console.log(`Program Id: ${file.programId}`);
console.log(`File Name: ${file.fileName}`);
console.log(`Storage Location: ${file.storage === 'nand' ? 'NAND' : 'SD'}`);
console.log(`Date Time: ${new Date(file.dateTime).toDateString()}`);
console.log(`Unique ID: ${file.uniqueId}`);
console.log(`contentType: ${file.contentType === 'screenshot' ? 'Image' : 'Video'}`);
}
Switch.Album.Unmount();
const imageWidth = 320;
const imageHeight = 180;
Switch.Album.Mount();
for (const { file } of Switch.Album.Files) {
const image = new Image();
image.onload = () => {
if (x + imageWidth >= screen.width) {
x = gap;
y += imageHeight + 40 + gap;
}
ctx.drawImage(image, x, y);
ctx.fillText(file.fileName, x + imageWidth / 2, y + imageHeight + 20, imageWidth);
x += imageWidth + gap;
};
const url = URL.createObjectURL(new Blob([file.thumbnail]));
image.src = url;
}
Switch.Album.Unmount();
Switch.Album.Mount();
for (const app of Switch.Application) {
let appFiles = Switch.Album.Files.filter(x.programid === app.id);
let screenshotCount = appFiles.filter(x => x.contentType == "screenshot").length;
let movieCount = appFiles.filter(x => x.contentType == "movie").length;
let extramovieCount = appFiles.filter(x => x.contentType == "extramovie").length;
console.log(`${app.name}: S=${screenshotCount} M=${movieCount} E=${extramovieCount}`);
}
Switch.Album.Unmount();
I am a developer who only knows how to write JavaScript, and now I am encountering some problems. The error message is 'npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c create-nxjs-app'. How can I solve it? I really hope you can help me answer.
Hey it's me again. Would it be difficult to integrate the following Lib? It would be awesome to be able to spawn a local server.
Expose the Switch software keyboard as a JavaScript API, based on this example: https://github.com/switchbrew/switch-examples/blob/master/applet/libapplets/software-keyboard/source/main.c
Possibly web-based API to implement: https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard
Some kind of Hardware Acceleration with WebGL or WebGPU support would be neat for this.
https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API
Nice work by the way!
import.meta.url
should contain the value of Switch.entrypoint
.
Will be useful for scripts to run on multiple platforms without modification (i.e. for testing against Node, Bun, Deno, the browser, etc.).
First off, wow! This is awesome - I just discovered nx.js!
Secondly, I want to make an application where I'll need to connect the Switch to a PC via a USB cable. I've searched a little through the docs, but couldn't find anything 100% applicable...
Is there a way to communicate over USB using nx.js?
nxjs-pack
is not distributing latest nxjs.nro
.
After updating the runtime the remove file fixes were still broken. I found out that node_modules/nxjs-pack/dist/nxjs.nro
is outdated. After copying the latest release manually everything works as expected!
I'm writing an application related to FTP and using the "basic-ftp" library, but encountering an error. I hope that someday Nx.js will support FTP.
X [ERROR] Could not resolve "net"
node_modules/basic-ftp/dist/FtpContext.js:4:22:
4 │ const net_1 = require("net");
╵ ~~~~~
The package "net" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "--platform=node" to do that, which will remove this error.
X [ERROR] Could not resolve "stream"
node_modules/basic-ftp/dist/transfer.js:5:25:
5 │ const stream_1 = require("stream");
╵ ~~~~~~~~
The package "stream" wasn't found on the file system but is built into node. Are you trying to
bundle for node? You can use "--platform=node" to do that, which will remove this error.
X [ERROR] Could not resolve "fs"
node_modules/basic-ftp/dist/Client.js:4:21:
4 │ const fs_1 = require("fs");
╵ ~~~~
The package "fs" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "--platform=node" to do that, which will remove this error.
X [ERROR] Could not resolve "tls"
node_modules/basic-ftp/dist/transfer.js:6:22:
6 │ const tls_1 = require("tls");
╵ ~~~~~
The package "tls" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "--platform=node" to do that, which will remove this error.
X [ERROR] Could not resolve "tls"
node_modules/basic-ftp/dist/Client.js:6:22:
6 │ const tls_1 = require("tls");
╵ ~~~~~
The package "tls" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "--platform=node" to do that, which will remove this error.
X [ERROR] Could not resolve "tls"
node_modules/basic-ftp/dist/netUtils.js:4:22:
4 │ const tls_1 = require("tls");
╵ ~~~~~
The package "tls" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "--platform=node" to do that, which will remove this error.
Hey,
When I try to call Switch.file(path)
it throws TypeError: not a function
. The tests are also failing for me. Am I missing maybe something?
Does nx.js support video streaming. I plan to play videos through nx.js with m3u8 stream file format
Google translator
Sometimes npm modules which include WASM binary data load that data with the fetch()
function using a base64-encoded data:
URL. Make this work:
import { loadYoga } from 'yoga-layout/wasm-async';
(async () => {
console.log(loadYoga);
const yoga = await loadYoga();
console.log(yoga);
})().catch(console.error);
I want to export an nsp file to post to tinfoil Host but don't know how.
From google translate
Add unzip API
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.