hooklift / node-libvirt Goto Github PK
View Code? Open in Web Editor NEWlibvirt bindings for google v8 javascript engine (nodejs addon)
Home Page: http://c4milo.github.io/node-libvirt/
libvirt bindings for google v8 javascript engine (nodejs addon)
Home Page: http://c4milo.github.io/node-libvirt/
Hello,
I'm passing by some troubles with 'defineDomain', 'createDomain' and 'lookupDomainByName'. When I execute that functions I get error like this:
libvirt: error : invalid connection pointer in virGetDomain libvirt: error : invalid connection pointer in virDomainLookupByName lookupDomain.start(function(err, result) { ^ TypeError: Object #<Hypervisor> has no method 'start' at index.js:14:18
I took a look at source code but didn't find anything useful.
Any ideas?
All the functions doing IO should use libuv's uv_queue_work
function in order to not block Node.js main thread.
Some useful references:
Is this project still being developed?
We are looking into using it for http://nodester.com and would be interested in adding to it.
I am getting the following error with a nodejs crash when calling domain.attachDevice:
#
# Fatal error in ../deps/v8/src/api.h, line 297
# CHECK(allow_empty_handle || that != __null) failed
#
This gist contains the full stack trace:
https://gist.github.com/bocajspear1/b40f92685e8a0b8b5b3a
When the line calling attachDevice is commented out, all other calls using the current domain work properly.
NodeJS version: v0.10.26
Thanks.
I have a running domain on my KVM.
hayashis@soichi7:~/test/nodejs $ sudo virsh list --all
Id Name State
----------------------------------------------------
6 ubuntu14 running
which I can query via the listActiveDomains
hypervisor_object.listActiveDomains(function(err, info) {
console.log(info);
});
[ 6 ]
However, when I try to query by the id
hypervisor_object.listActiveDomains(function(err, info) {
info.forEach(function(id) {
console.log("quering "+id);
hypervisor_object.lookupDomainById(id, function(err, domain) {
console.dir(err);
console.dir(domain);
});
});
});
I get empty object from lookupDomainById
quering 6
null
{}
I also get an empty object if I do lookupDomainByName("ubuntu14")...
What am I missing?
Such a useful method and it's bummer it's not done. Is there a similar method in the codebase we could base lookupStorageVolumeByVolume
on?
Took me a while to nail it down to this simple test case.
Couple of things:
'use strict';
var virt = require('libvirt');
let hypervisor = new virt.Hypervisor('qemu:///system');
if(!process.env.TEST_POOL_NAME) {
console.log('Provide a TEST_POOL_NAME environment variable, to trigger a crash it needs to have a couple of volumes');
process.exit(1);
}
hypervisor.connectAsync(() => {
return hypervisor.lookupStoragePoolByNameAsync(process.env.TEST_POOL_NAME).then(pool => {
pool.getVolumes((err, volumes) => {
volumes.forEach((volumeName, idx) => {
// below line intentionally queries missing storage volumes every 2 times
let volumeNameToQuery = volumeName + ((idx % 2) ? 'INTENTIONAL_BREAK' : '');
return pool.lookupStorageVolumeByNameAsync(volumeNameToQuery).then(volume => {
return volume.getInfoAsync();
});
})
});
});
});
Stacktrace:
#0 0x00007ffff6bf228a in strlen () from /lib64/libc.so.6
#1 0x00000000008eb435 in v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::NewStringType, int) ()
#2 0x00007ffff48f9ebe in Nan::imp::Factory<v8::String>::New (value=0x0, length=-1) at ../../nan/nan_implementation_12_inl.h:265
#3 0x00007ffff48fd881 in Nan::New<v8::String, char const*> (arg0=0x0) at ../../nan/nan_new.h:208
#4 0x00007ffff48fa007 in Nan::New (value=0x0) at ../../nan/nan_new.h:313
#5 0x00007ffff49111a2 in NLV::Error::Getter (property=..., info=...) at ../src/error.cc:180
#6 0x00007ffff490a218 in Nan::imp::GetterCallbackWrapper (property=..., info=...) at ../../nan/nan_callbacks_12_inl.h:190
#7 0x0000000000904210 in v8::internal::PropertyCallbackArguments::Call(void (*)(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&), v8::Local<v8::Name>) ()
#8 0x0000000000bef85d in v8::internal::Object::GetPropertyWithAccessor(v8::internal::LookupIterator*, v8::internal::LanguageMode) ()
#9 0x0000000000c04d23 in v8::internal::Object::GetProperty(v8::internal::LookupIterator*, v8::internal::LanguageMode) ()
#10 0x0000000000c048c3 in v8::internal::Object::GetPropertyOrElement(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Name>, v8::internal::LanguageMode) ()
#11 0x0000000000ca4759 in v8::internal::BasicJsonStringifier::Result v8::internal::BasicJsonStringifier::Serialize_<false>(v8::internal::Handle<v8::internal::Object>, bool, v8::internal::Handle<v8::internal::Object>) ()
#12 0x0000000000ca5248 in v8::internal::Runtime_BasicJSONStringify(int, v8::internal::Object**, v8::internal::Isolate*) ()
A trivial fix for src/error.cc:180
to account for error_->message
being NULL:
return info.GetReturnValue().Set(Nan::New(error_->message ? error_->message : "(NULL)").ToLocalChecked());
works around the issue but I'd rather seek a real solution. @mbroadst - any ideas?
Hi,
I am trying to destroy a domain using the following code
var libvirt = require('node-libvirt');
var hypervisor = new libvirt.Hypervisor('vbox:///session');
var domain = hypervisor.lookupDomainByName('ubuntu1204');
console.log(domain.start());
setTimeout(console.log(domain.stop()), 5000);
setTimeout(console.log(domain.start()), 5000);
But it seems to be giving me this error
true
true
libvir: Domain error : invalid domain pointer in virDomainCreate
/Users/Subho/Documents/Workshop/Megh/test.js:12
setTimeout(console.log(domain.start()), 5000);
^
[object Error]
What is the problem here?
Cheers,
Subho
Does the project build correctly?
I am getting these errors
13:18:40 Subho@Turing-Machine:~/Documents/Workshop/node-libvirt > node-waf configure
Checking for program g++ or c++ : /usr/bin/g++
Checking for program cpp : /usr/bin/cpp
Checking for program ar : /usr/bin/ar
Checking for program ranlib : /usr/bin/ranlib
Checking for g++ : ok
Checking for node path : not found
Checking for node prefix : ok /usr/local/Cellar/node/0.8.5
Checking for program node : /usr/local/bin/node
Checking for libvirt >= 0.8.4 : yes
'configure' finished successfully (1.160s)
13:18:48 Subho@Turing-Machine:~/Documents/Workshop/node-libvirt > node-waf build
Waf: Entering directory `/Users/Subho/Documents/Workshop/node-libvirt/build'
[ 1/13] cxx: src/error.cc -> build/Release/src/error_1.o
[ 2/13] cxx: src/hypervisor.cc -> build/Release/src/hypervisor_1.o
[ 3/13] cxx: src/stream.cc -> build/Release/src/stream_1.o
[ 4/13] cxx: src/network.cc -> build/Release/src/network_1.o
[ 5/13] cxx: src/node_libvirt.cc -> build/Release/src/node_libvirt_1.o
../src/hypervisor.cc: In static member function ‘static void NodeLibvirt::Hypervisor::Initialize(v8::Handle<v8::Object>)’:
../src/hypervisor.cc:341: error: ‘VIR_DOMAIN_EVENT_ID_LAST’ was not declared in this scope
[ 6/13] cxx: src/domain.cc -> build/Release/src/domain_1.o
Waf: Leaving directory `/Users/Subho/Documents/Workshop/node-libvirt/build'
Build failed: -> task failed (err #1):
{task: cxx hypervisor.cc -> hypervisor_1.o}
Hello,
I am trying to get a domain by uuid.
hypervisor.lookupDomainByUUID('581053b6-2a12-4b20-b4a5-fc06c1d25cf5',function(e2,d2){
console.log(e2);
console.log(d2);
});
it says :
libvirt: QEMU Driver error : Domain not found: no domain with matching uuid '35383130-3533-6236-2d32-6131322d3462'
Ok, you didn't find 35383blabla , but i didn't want this.
Is there a typo problem in this function ?
I think every function should expect a callback to keep things asynchronous. uv_async_*
stuff will probably be necessary.
I'm getting a rather obscure error. I keep getting it when I run my script:
libvirt: error : An error occurred, but the cause is unknown
I am wondering what would be a way to get more information from the system so I can actually figure out what is going on. I've tried debugging libvirt itself, but it seems okay, I've tried everything I can think of, except use a debug version of node. It appears to pop up when I call child_process.exec.
Node Version: v0.10.25
I am using a build of this module I made today
Any advice would be helpful
Thanks
Have installed npm install --global --production windows-build-tools
npm install -g failed
run node-gyp.cmd rebuild manully lack of header files
put header files into windows10/kits/ucrt cause error like unmatching source files and header files.
For more information, please refer to:
https://groups.google.com/forum/#!topic/v8-users/6kSAbnUb-rQ
Hello.
I get following error when I try to install it on RHEL 6.7 KVM host.
make: Entering directory `/home/hayashis/git/node-libvirt/build'
CXX(target) Release/obj.target/libvirt/src/domain.o
In file included from ../src/error.h:5,
from ../src/domain.cc:3:
../node_modules/nan/nan.h:328: error: ‘REPLACE_INVALID_UTF8’ is not a member of ‘v8::String’
In file included from ../src/domain.cc:4:
Is it possible to list all domains/running domains by name rather than ID? so rather than .listActiveDomains()
we could have .listActiveDomainsByName()
If it exists, I'm just not seeing it :/
Thanks in advance
When the API encounters an error, it generally calls virGetLastError() and "stashes" the pointer to the libvirt error object, which is returned to the user, wrapped up an an Error object. The getters on the Error object look at the various fields of the "stashed" virErrorPtr struct.
However, according to the libvirt documentation:
The error object is kept in thread local storage so separate threads can safely use this function concurrently. Note that it does not take a copy, so error information can be lost if the current thread obtains this pointer, calls another libvirt function, and then tries to access this pointer.
So if the same worker thread gets re-used before the consumer has "read" the error object, the information gets lost.
I want my ios app receive the event of my virtual machine, so i need to monitor all the event. But I encounter an issue when I use this function registerDomainEvent .Could anyone help me? Very thanks!
[root@TEST-LC-NC-0-0-31 ~]# node event_cb.js
libvirt: Remote Driver error : adding cb to list
/root/event_cb.js:14
hyper.registerDomainEvent(event);
^
[object Error]
[root@TEST-LC-NC-0-0-31 ~]#
My code as follows:
1 var libvirt = require('libvirt');
2
3 var Hypervisor = libvirt.Hypervisor;
4 var hyper = new Hypervisor('qemu:///system');
5
6 var domain = hyper.lookupDomainById(173);
7
8 var event = { 'evtype': hyper.VIR_DOMAIN_EVENT_ID_REBOOT ,
9 'domain':domain,
10 'callback': function(hyp, dom, data) {
11 console.log('callback');
12 }
13 };
14 hyper.registerDomainEvent(event);
When using life cycle events to detect reboots and shutdowns, it crashes very often (segfaults) in the C++ handler.
It crashes all the time with Node 11.x, a little bit less with Node 10.x.
Anyone using life cycle events successfully and reliably ?
This includes to get rid of EventEmitter altogether and using ObjectWrap instead.
Consider this simplistic case case that can cause Segmentation fault:
var hypervisor = new libvirt.Hypervisor('qemu://system');
function createStorageVolume(xml) {
hypervisor.lookupStoragePoolByNameAsync('some-pool').then(function(pool) {
// at this point of time pool is referenced for the last time,
// after createVolumeAsync starts, the garbage collector is
// free to free the native object any time
return pool.createVolumeAsync(xml);
});
}
Solution that fixes it is:
var hypervisor = new libvirt.Hypervisor('qemu://system');
function createStorageVolume(xml) {
hypervisor.lookupStoragePoolByNameAsync('some-pool').then(function(pool) {
return pool.createVolumeAsync(xml).then(function(volume) {
var _pool = pool; // keep reference of pool until the method finishes
return volume;
});;
});
}
I am yet to devise a pure node-libvirt test case. Anyway, a way to test it is to try to create many volumes in parallel using the above pattern and preferably call node with node --expose-gc
, furthermore add code if(global.gc) setInterval(global.gc, 1);
which should make sure the GC kicks in.
I think it may be somehow possible to increase the refcount in node-libvirt itself but it's hard for me to wrap my head around all those wrapper classes.
diff --git src/domain.cc src/domain.cc
index 2a4011a..5b8e0c7 100644
--- src/domain.cc
+++ src/domain.cc
@@ -156,6 +156,8 @@ namespace NodeLibvirt {
Domain::Start);
NODE_SET_PROTOTYPE_METHOD(t, "suspend",
Domain::Suspend);
+ NODE_SET_PROTOTYPE_METHOD(t, "sendKey",
+ Domain::SendKey);
NODE_SET_PROTOTYPE_METHOD(t, "attachDevice",
Domain::AttachDevice);
NODE_SET_PROTOTYPE_METHOD(t, "detachDevice",
@@ -282,6 +284,9 @@ namespace NodeLibvirt {
NODE_DEFINE_CONSTANT(object_tmpl, VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN);
NODE_DEFINE_CONSTANT(object_tmpl, VIR_DOMAIN_EVENT_WATCHDOG_DEBUG);
+
+ NODE_DEFINE_CONSTANT(object_tmpl, VIR_DOMAIN_SEND_KEY_MAX_KEYS);
+
state_symbol = NODE_PSYMBOL("state");
max_memory_symbol = NODE_PSYMBOL("max_memory");
memory_symbol = NODE_PSYMBOL("memory");
@@ -937,6 +942,41 @@ namespace NodeLibvirt {
return True();
}
+ Handle<Value> Domain::SendKey(const Arguments& args) {
+ HandleScope scope;
+ int ret = -1;
+
+ if(args.Length() == 0) {
+ return ThrowException(Exception::TypeError(
+ String::New("You must specify arguments to invoke this function")));
+ }
+
+ if(!args[0]->IsArray()) {
+ return ThrowException(Exception::TypeError(
+ String::New("Argument must be an array of objects")));
+ }
+
+ Domain *domain = ObjectWrap::Unwrap<Domain>(args.This());
+
+ unsigned int keycodes[VIR_DOMAIN_SEND_KEY_MAX_KEYS];
+
+ Local<Array> keycodes_ = Local<Array>::Cast(args[0]);
+
+ unsigned int length = keycodes_->Length();
+
+ for(unsigned int i = 0; i < length; i++) {
+ keycodes[i] = (unsigned int) keycodes_->Get(Integer::New(i))->Int32Value();
+ }
+
+ ret = virDomainSendKey(domain->domain_, 0, 150, keycodes, length, 0);
+
+ if(ret == -1) {
+ ThrowException(Error::New(virGetLastError()));
+ return False();
+ }
+ return True();
+ }
+
Handle<Value> Domain::GetVcpus(const Arguments& args) {
HandleScope scope;
diff --git src/domain.h src/domain.h
index e914942..07595bd 100644
--- src/domain.h
+++ src/domain.h
@@ -55,6 +55,7 @@ namespace NodeLibvirt {
static Handle<Value> Shutdown(const Arguments& args);
static Handle<Value> Start(const Arguments& args);
static Handle<Value> Destroy(const Arguments& args);
+ static Handle<Value> SendKey(const Arguments& args);
static Handle<Value> GetVcpus(const Arguments& args);
static Handle<Value> SetVcpus(const Arguments& args);
static Handle<Value> Migrate(const Arguments& args);
Hello,
When you try :
c.registerDomainEvent({evtype: c.VIR_DOMAIN_EVENT_ID_LIFECYCLE, callback: function() {
console.log("lifecycle event");
}});
you get a libvirt error : "could not initialize domain event timer"
In order to use libvirt events, an event "manager" has to be defined using virEventRegisterImpl. This function must provide function pointers for various task (http://libvirt.org/html/libvirt-libvirt.html#virEventRegisterImpl).
For example virEventAddHandleFunc receive a FD, so it can be integrated with libuv (fd poll).
Anthony.
In particular, domain lookup by UUID is unusable in the version in npm. Can another release be made?
Great work guys! I started using the library today and it is impressive. Especially the simplicity. However I am running into some issues... I have stuff working as long as they dont deal with devices. But anything that deals with devices, things like "getNodeDevicesNames", "lookupNodeDeviceByName" fail with an error that says that the function is not supported by the connection driver. Thoughts?
Thanks,
Vik.
I've noticed there are really any docs and the readme doesn't matchup all that well with the code anymore. I'd love to volunteer to maintain this repo and get it back to a working order.
@c4milo I know you're busy and that's kinda why I'm pinging you.
When going through the initial instructions on a debian setup you need some additional dependency's which are not stated in the instructions maybe add something like:
You need the libvirt-dev on debian stable ( apt-get install libvirt-dev ) and maybe the libicu-dev package ( apt-get install libicu-dev )
After download these packages go to the cloned repo and run "npm install nan"
now you can continue building using the gyp command ( node-gyp configure )
How can I clone an entire vm with node-libvirt ?
I search an equivalent of virt-clone, can I do that with node-libvirt ?
Thanks.
It will be more consistent with libvirt API. See http://libvirt.org/html/libvirt-libvirt.html#virDomainDestroy
Hi, very interesting project.
Any examples on how to use ?
There are two servers in this environment, both running KVM on Ubuntu 14.04 LTS
The following virsh command completes successfully:
virsh migrate TP0002 qemu+ssh://192.168.1.202/system --live --p2p --tunnelled --compressed --persistent --undefinesource
The following node code fails with Segmentation fault
'use strict'
const virt = require('libvirt');
let hv = virt.createHypervisor('qemu:///system'),
destination = {
dest_uri: 'qemu://192.168.1.202/system',
dest_name: 'test1',
flags: virt.VIR_MIGRATE_LIVE |
virt.VIR_MIGRATE_PEER2PEER |
virt.VIR_MIGRATE_TUNNELLED |
virt.VIR_MIGRATE_PERSIST_DEST |
virt.VIR_MIGRATE_UNDEFINE_SOURCE
};
return hv.connectAsync()
.then(() => hv.lookupDomainByNameAsync('TP0001'))
.then(domain => domain.migrateAsync(destination))
.then(() => {
console.log('success');
process.exit(0);
})
.catch(err => {
console.error('error', err);
process.exit(1);
});
Hi,
I am trying to write an app that will notify when a new VM is added to a HV.
How can I listen to all events from the hypervisor?
I know the Domain object has RegisterEventAsync but I don't want to register events from a specific domain.
This is what I am trying to do:
libvirt = require("libvirt")
libvirt.startEventLoop()
async function foo () {
hv = new libvirt.Hypervisor("qemu:///system")
await hv.connectAsync()
hv.registerDomainEvent(...)
}
foo()
from gitter:
@Rush and I have been discussing breaking API changes for the v2 release, including removing the current promise api (wrapping all methods in Async variants) in favor of one of two options:
It would be great to hear if any of you have opinions on the issue
I have found the following issues when testing secrets (for Ceph storage pools)
setValue
will clip the passed keyvirsh
retrieves the data base64 transposedconst Promise = require('bluebird'),
exec = Promise.promisify(require('child_process').exec),
virt = require('libvirt'),
uuid = require('uuid');
let secretUUID = uuid.v4(),
secretXml = `<secret ephemeral="no" private="no"><uuid>${secretUUID}</uuid><usage type="ceph">` +
'<name>client.test secret</name></usage></secret>',
key = 'do not tell anyone',
secret;
let hv = virt.createHypervisor('qemu:///system');
hv.connectAsync()
.then(() => hv.defineSecretAsync(secretXml))
.then(_secret => {
secret = _secret;
secret.setValueAsync(key);
})
.then(() => secret.getValueAsync())
.then(value => console.log(`setValue('${key}'), while getValue() returns '${value}'`))
.then(() => exec(`virsh secret-get-value ${secretUUID}`))
.then(stdout => console.log(`virsh reads the secret value as '${stdout.trim()}', which is base64 transposed of the cropped key`))
.then(() => secret.undefineAsync())
.then(() => hv.disconnectAsync());
When trying to install it hangs. Log is below, any clue?
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | linux | x64
gyp info spawn python
gyp info spawn args [ '/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/jmarceno/Documents/nodeJS/node-libvirt/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/jmarceno/.node-gyp/0.10.26/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/jmarceno/.node-gyp/0.10.26',
gyp info spawn args '-Dmodule_root_dir=/home/jmarceno/Documents/nodeJS/node-libvirt',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
Traceback (most recent call last):
File "/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py", line 18, in
sys.exit(gyp.script_main())
AttributeError: 'module' object has no attribute 'script_main'
gyp ERR! configure error
gyp ERR! stack Error: gyp
failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/usr/local/lib/node_modules/node-gyp/lib/configure.js:340:16)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:797:12)
gyp ERR! System Linux 3.11.0-18-generic
gyp ERR! command "node" "/usr/local/bin/node-gyp" "configure"
gyp ERR! cwd /home/jmarceno/Documents/nodeJS/node-libvirt
gyp ERR! node -v v0.10.26
gyp ERR! node-gyp -v v0.13.0
gyp ERR! not ok
Hello.
I get following error when I try to node-gyp build node-libvirt on Centos 7, node 15.2, npm 7.0.8, node-gyp 7.1.2, python 3.6.8 and libvirt 6.5. node-gyp configure returns ok.
make: Entering directory `/home/userName/projectName/node_modules/libvirt/build'
CXX(target) Release/obj.target/libvirt/src/domain.o
In file included from /home/userName/.cache/node-gyp/15.2.0/include/node/node.h:63:0,
from ../src/nan.h:56,
from ../src/node_libvirt.h:8,
from ../src/error.h:5,
from ../src/domain.cc:3:
/home/userName/.cache/node-gyp/15.2.0/include/node/v8.h: In member function 'void v8::TracedReferenceBase::SetSlotThreadSafe(T*)':
/home/userName/.cache/node-gyp/15.2.0/include/node/v8.h:912:22:error: expected type-specifier reinterpret_cast<std::atomic<T*>*>(&val_)->store(new_val,
I have a piece of code:
vapp.hyperv = new virt.Hypervisor(vapp.hyperv_string)
vapp.hyperv.connectAsync()
.then(() =>
vapp.domain = vapp.hyperv.lookupDomainByNameAsync(name)
)
.then((domain) => {
vapp.domain = domain
vapp.ev_lifecycle = domain.registerEvent(
{evtype:virt.VIR_DOMAIN_EVENT_ID_LIFECYCLE},
function (hyp, dom, data) {
console.log(hyp, dom, data)
})
return vapp.domain.getInfoAsync()
})
...
After running the above I get the following error:
libvirt: error : internal error: could not initialize domain event timer
Why is it so?
Hello,
i would like to inform you that getActiveDomains() return a list of ids not names. The function getDefinedDomains() return the name. Example:
hypervisor.getActiveDomains(): 4
hypervisor.getDefinedDomains(): example
It would be nice if you could have a look at it.
Thanks and best regards,
Thomas
Not so long ago I decided to try to write something like a management class for virtual machines, there was no implementation of libvirt in JS. I see that the last publications were a long time ago, but maybe the library has remained relevant?
It becomes very complicated start to use and contribute to this project, because it lacks documentation, apparently referring to unit testing, as if it were an appropriate way to start, but they are not.
Maybe for beginners like me it is complicated, but the idea is that everyone can contribute, or at least try.
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.