I'm writing a discord bot using the nyxx library and want use dynamic file import for load command info and handler. But, after 5 hours of searching with Google, I didn't find anything to help me do that.
In Node.js, I can use require()
or import()
for it: Does the dart have something like that?
A small code snippet, showing what I want do:
this.commands = new Collection();
fs.readdirSync('./src/commands').filter(( f ) => f.endsWith( '.js' )).forEach((file) => {
const command = require(`../commands/${file}`);
this.commands.set( command.info.name, command );
});
Is it possible to do this or not? (I don't like to write many imports for commands and register it in lib.)
CodePudding user response:
You can in theory use Isolate.spawnUri
to spawn external Dart programs to run in its own Isolate
instances that can then communicate back to the main program using SendPort
.
It does, however, come with some limitations. E.g. it is very limited what types of objects you can send though SendPort
when using spawnUri
since the two programs does not share any type information (compared to Isolate.spawn
which does allow you to send your own custom types). The documented types you can send can be found here:
- Null
- bool
- int
- double
- String
- List or Map (whose elements are any of these)
- TransferableTypedData
- SendPort
- Capability
https://api.dart.dev/stable/2.17.6/dart-isolate/SendPort/send.html
But it does allow us to make some kind of protocol and you can create some helper class around this to handle the conversion of a known object structure into e.g. Map<String, Object>
.
A small example that works with Dart VM would be:
Your command implemented as: command.dart
import 'dart:isolate';
void main(List<String> arguments, Map<String, Object> message) {
final userName = message['username'] as String;
final sendPort = message['port'] as SendPort;
sendPort.send('Hi $userName. '
'You got a message from my external command program!');
}
Your server that calls your command: server.dart
import 'dart:isolate';
void main() {
final recievePort = ReceivePort();
recievePort.listen((message) {
print('Got the following message: $message');
recievePort.close();
});
Isolate.spawnUri(Uri.file('command.dart'), [], {
'username': 'julemand101',
'port': recievePort.sendPort,
});
}
If running this with: dart server.dart
you, hopefully, get:
Got the following message: Hi julemand101. You got a message from my external command program!
If you want to compile your application, you can do so by doing the following. You need to compile the command.dart
, since a compiled Dart program does not understand how to read Dart code.
dart compile exe server.dart
dart compile aot-snapshot command.dart
You should here change Uri.file('command.dart')
to Uri.file('command.aot')
since the file-extension for aot-snapshot
are .aot
.
If everything works, you should be able to see:
> .\server.exe
Got the following message: Hi julemand101. You got a message from my external command program!