Giter Site home page Giter Site logo

orhanobut / hawk Goto Github PK

View Code? Open in Web Editor NEW
4.0K 99.0 388.0 967 KB

✔️ Secure, simple key-value storage for Android

License: Apache License 2.0

Java 51.86% Kotlin 48.14%
hawk storage android key-value-store encryption security sharedpreferences preferences

hawk's Introduction

Android Arsenal API Join the chat at https://gitter.im/orhanobut/hawk Build Status

Hawk 2.0

Secure, simple key-value storage for android

Important Note

This version has no backward compatibility with Hawk 1+ versions. If you still want to use old versions, check here

Download

compile "com.orhanobut:hawk:2.0.1"

Initialize

Hawk.init(context).build();

Usage

Save any type (Any object, primitives, lists, sets, maps ...)

Hawk.put(key, T);

Get the original value with the original type

T value = Hawk.get(key);

Delete any entry

Hawk.delete(key);

Check if any key exists

Hawk.contains(key);

Check total entry count

Hawk.count();

Get crazy and delete everything

Hawk.deleteAll();

How does Hawk work?

More options

  • Everything is pluggable, therefore you can change any layer with your custom implementation.
  • NoEncryption implementation is provided out of box If you want to disable crypto.
Hawk.init(context)
  .setEncryption(new NoEncryption())
  .setLogInterceptor(new MyLogInterceptor())
  .setConverter(new MyConverter())
  .setParser(new MyParser())
  .setStorage(new MyStorage())
  .build();

License

Copyright 2016 Orhan Obut

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

hawk's People

Contributors

blangel avatar bosgood avatar carlonzo avatar gitter-badger avatar hamen avatar kardeslik avatar marwinxxii avatar mricefox avatar oobut avatar orhanobut avatar pavelsynek avatar rubengees avatar sferra avatar shenghaiyang avatar tslamic avatar yekmer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hawk's Issues

Cache

Instead of reading all values from the file, it would be nice to cache and reuse it. It will give a good performance hit.

How remove by key+value only?

Hello,
I need store by key+(value1,2,3..n) and remove only one key+value1, but not all values.

The document says: Hawk.remove remove immediately all branch keys :(

OR NOT?

ghmm. i can set unique key and remove only that key ;\

Save heavy List freeze UI

I have a class like this:

public class TestClass {
//This got 2 Strings as property
}

Then i made a List of 8000 "TestClass" ... T
When i try to save it to Hawk it freeze the UI.

How to handle this?

Thanks!

NPE on multidex

I have my Application class extended by MultiDexApplication, and because of this, with my first activity I get NPE for any call for Hawk, probably caused by delay of creating multiple dex files (I think). Did you guys encounter such a situation?

09-14 14:42:23.848 5425-5425/com.myapp W/System.err: java.lang.NullPointerException 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.orhanobut.hawk.Hawk.get(Hawk.java:128) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.orhanobut.hawk.Hawk.get(Hawk.java:151) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.myapp.preference.Configuration.getBool(Configuration.java:62) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.myapp.activity.SplashActivity.onCreate(SplashActivity.java:58) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.Activity.performCreate(Activity.java:5008) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.os.Looper.loop(Looper.java:137) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.myapp.App.startCatcher(App.java:100) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.myapp.App.onCreate(App.java:60) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4151) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.access$1300(ActivityThread.java:130) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1255) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.os.Looper.loop(Looper.java:137) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at java.lang.reflect.Method.invokeNative(Native Method) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at java.lang.reflect.Method.invoke(Method.java:511) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 09-14 14:42:23.852 5425-5425/com.myapp W/System.err: at dalvik.system.NativeStart.main(Native Method) 09-14 14:42:23.872 5425-5429/com.myapp D/dalvikvm: GC_CONCURRENT freed 396K, 12% free 8945K/10055K, paused 11ms+0ms, total 14ms 09-14 14:42:23.976 5425-5429/com.myapp D/dalvikvm: GC_CONCURRENT freed 310K, 10% free 9087K/10055K, paused 13ms+11ms, total 33ms 09-14 14:42:24.008 5425-5429/com.myapp D/dalvikvm: GC_CONCURRENT freed 306K, 9% free 9180K/10055K, paused 11ms+0ms, total 15ms 09-14 14:42:24.036 5425-5429/com.myapp D/dalvikvm: GC_CONCURRENT freed 354K, 10% free 9261K/10183K, paused 11ms+0ms, total 16ms 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp/com.myapp.activity.SplashActivity}: java.lang.NullPointerException 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.access$600(ActivityThread.java:130) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.os.Looper.loop(Looper.java:137) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.myapp.App.startCatcher(App.java:100) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.myapp.App.onCreate(App.java:60) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4151) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.access$1300(ActivityThread.java:130) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1255) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.os.Looper.loop(Looper.java:137) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4745) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at java.lang.reflect.Method.invokeNative(Native Method) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at java.lang.reflect.Method.invoke(Method.java:511) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at dalvik.system.NativeStart.main(Native Method) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: Caused by: java.lang.NullPointerException 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.orhanobut.hawk.Hawk.get(Hawk.java:128) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.orhanobut.hawk.Hawk.get(Hawk.java:151) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.myapp.preference.Configuration.getString(Configuration.java:49) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.myapp.preference.Configuration.getAuthEmail(Configuration.java:121) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at com.myapp.activity.SplashActivity.onCreate(SplashActivity.java:76) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.Activity.performCreate(Activity.java:5008) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 09-14 14:42:24.040 5425-5425/com.myapp W/System.err: ... 19 more 09-14 14:42:24.052 5425-5425/com.myapp W/Hawk: key is generating without password 09-14 14:42:24.052 5425-5425/com.myapp W/Hawk: key is generated without password

Min SDK

I like to know if there is any reason hawk is using min SDK as 10? Thanks!

java.lang.IllegalStateException

Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.

So, since i got an OOM problem with the low memory devices when try to retrieve objects i have saved to Hawk, i'm now using Sqlite option like this:

  1. in my class that extends Application : Hawk.init(this)
    .setStorage(HawkBuilder.newSqliteStorage(this))
    .setLogLevel(LogLevel.FULL)
    .build();
  2. Save the objects to Hawk : Hawk.put("a", listOfFoo);
  3. Hawk.get("a"); <- This cause that problem...

Why this? Thanks!

Crash on return from background

Hi there,
I have been having a crash when the app returns from background, specifically after a few hours. It seems Hawk instance is removed and it becomes null. Throwing exception

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object com.orhanobut.hawk.Storage.get(java.lang.String)' on a null object reference
at com.orhanobut.hawk.Hawk.get

I have tried re-initializing Hawk onResume but does'nt seem to help.

Any suggestions?

Thanks

SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found

Thanks for creating this.

I am trying to use Hawk in one of my projects but getting the bellow error on some Samsung devices:

java.lang.RuntimeException: java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found

Any workaround for that?.
Thanks.

Can't get List<Foo> from Hawk.get

Hi there,
I defined a Class named Foo.

public class Foo {

    private String carSeries;
    private Uri carImageUri;
    private String carType;


    public String getCarSeries() {
        return carSeries;
    }

    public void setCarSeries(String carSeries) {
        this.carSeries = carSeries;
    }

    public Uri getCarImageUri() {
        return carImageUri;
    }

    public void setCarImageUri(Uri carImageUri) {
        this.carImageUri = carImageUri;
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType;
    }

    @Override
    public String toString() {
        return "Foo{" +
            "carSeries='" + carSeries + '\'' +
            ", carImageUri=" + carImageUri +
            ", carType='" + carType + '\'' +
            '}';
    }
}

List<Foo> foos = new ArrayList<Foo>();
foos.add(new Foo());
foos.add(new Foo());
Hawk.put(Constant.PREF_FOO, foos);

but Hawk.get(Constant.PREF_FOO, new ArrayList<Foo>()); always return list which size is 0(default value).

Datetime issue

Hi,

Hawk does not support to save DateTime object which is made by Jodatime. Can you please fix this issue?

README.md typo

The README.md reads ANYTYPE result = Hawk.get(key, T); but i think it should be T result = Hawk.get(key, T); otherwise passing in the type wouldn't make sense.

Object with polymorphic types

I think GSON used for serializa and deserializa the objects we want to save using Hawk, got a problem with the polymorphic types.
Using Jackson there is no problem

Is there a way to let us change GSON used for parsing with other like Jackson?

Thanks.

Multi processing

As per title, is hawk support multi processing? E.g. One is displaying data and another one is doing damage to the data at the same time, accessing the same data but from different threads.

Can't find some method and classes

I import the jar with compile 'com.orhanobut:hawk:1.16' in Android Studio, But I can't find some methods and classes like HawkBuilder.
![Uploading 2~LPJE_{JS0TT]BH3$SHZXN.jpg…]()

NPE again...

Caused by: java.lang.NullPointerException
at com.orhanobut.hawk.AesCbcWithIntegrity.decrypt(AesCbcWithIntegrity.java:368)
at com.orhanobut.hawk.AesEncryption.decrypt(AesEncryption.java:61)
at com.orhanobut.hawk.Hawk.get(Hawk.java:220)
at com.orhanobut.hawk.Hawk.get(Hawk.java:237)

Hawk.put app Freeze

App if freezing and what i am doing is :
Hawk.put("test", true);

Why this?

Disable encryption

Consider an option to disable encryption? I saw an old issue with the same thought but had been disabled. I may need it because the AES encryption causing me unrecoverable error sometimes on Samsung GT-I9100G.

Provides alternative encryption like Facebook Conceal might be a good idea.

Key in source - security issue

First of all, great job - looks nice.

From a quick look it seems that you key is based upon a constant in the Hawk source

final class AesEncryption implements Encryption {
    private static final String KEY_SALT = "asdf3242klj";
    private static final String PASSWORD = "asdf39230234242klj";
...

This is not really that secure. Granted better than storing prefs in plain text but not really great practise and should probably be documented in the README.

Maybe I have missed something and you have already done the below. Improvement suggestions would be to

a) base the encryption key on some user entered info, i.e. a pin or pass
b) utilise the OS level key storage so you are not storing your key in the code

This seems to be the fundamental error made with in-app encryption.

Apologies if you have accounted for this somewhere and I have missed it. Again, may be worth documenting as this is the primary function of an encryption library and the details are important.

Value not persistent after reopening app

Hi.
i have a problem that when i put a value, it is there until i reopen the app. when i do it, Hawk.contains("key") returns true but Hawk.get("key", -1) returns -1.

i use version 1.1 and initialize it with Hawk.init(context).

Multiple Hawk instances

First of all, great start to this library- I sense a real need for a solid encrypted key/value store in the Android ecosystem.

I'm working on a use case that requires a set of encrypted stores, where one is semi-secure (encrypted by a secret in the app binary) and another is encrypted using a value inputted from the user. Hawk has most of the features I need but I think its singleton nature is a limitation here.

Some ideas:

Questions for you:

  • Do you still see the need for a singleton instance of Hawk? Is it good enough to let users create one with new Hawk() and manage that object themselves? Or maybe have 1 global instance (Hawk.getInstance()) as well as a public constructor?
  • Logger becomes an issue if Hawk is no longer a singleton, because the Logger instance must be passed down the object hierarchy.

I've already started some of this, but was interested in your feedback.

Class序列化问题

您好,我看了下您的代码。对于下面代码有一些分歧。

HawkEncoder.java

    public <T> T decode(String value) throws Exception {
        if (value == null) {
            return null;
        }
        DataInfo info = DataUtil.getDataInfo(value);
        boolean isList = info.isList();

        byte[] bytes = encryption.decrypt(info.getCipherText());
        //if any exception occurs during decrypt, bytes will be null
        if (bytes == null) {
            return null;
        }

        // if the value is not list and serializable, then use the normal deserialize
        if (!isList && info.isSerializable()) {
            return toSerializable(bytes);
        }

        // convert to the string json
        String json = new String(bytes);

        Class<?> type = info.getClazz();
        if (!isList) {
            return parser.fromJson(json, type);
        }

        return fromJsonList(json, type);
    }

DataUtil.java

    static String addTypeAsObject(String cipherText, Class clazz) {
        String className = clazz.getCanonicalName();
        char serializable = Serializable.class.isAssignableFrom(clazz) ? FLAG_SERIALIZABLE : FLAG_NON_SERIALIZABLE;
        return className + TYPE_OBJECT + serializable + DELIMITER + cipherText;
    }

DataInfo中存储了被序列化的Class的一些信息。而在数据保存使用知识简单的使用 clazz.getCanonicalName();来存储Class的信息,我觉的这样是不安全的。

比如在实际的App开发中,App的配置信息为
com.xxx.ooo.app.Config.java
但是在后面的版本升级中可能会修改成
com.xxx.ooo.config.AppConfig.java
那么在升级过了,就可能会有异常发生。

还有的就是。
HaswkEncoder.java

    public <T> String encode(T value) {
        if (value == null) {
            return null;
        }

        byte[] bytes;
        if (value instanceof Serializable) {
            bytes = fromSerializable((Serializable) value);
        } else {
            String json = parser.toJson(value);
            bytes = json.getBytes();
        }

        if (bytes == null) {
            return null;
        }

        return encryption.encrypt(bytes);
    }

我觉的尽可能的使用json来保存Value的信息,同样是序列化的问题。
Class的package可能会修改,Class的字段可能会有增加、减少、修改。
同时序列化的版本号也会有所修改,这些问题在序列处理的时候,会比较麻烦。

@bosgood

E文不好,麻烦翻译下。^_^

Disable Encryption

  • Hawk.init() should also have "disable encryption" function
  • Hawk.put() should also have "don't encrypt" parameter

Parser interface is not public

Hi Orhan,

The interface Parser doesn't seems to be public, for now we can't set are own Parser.
Thanks for this new 1.19 update, this library is really useful !

Is storing list faster in hawk than using Shared Preference

Hello,

I seem to like this library, and I got an obvious question.

To store an List specifically ArrayList I use GSON library & then store it into the SharedPreference.
While Hawk has an direct method to save a List so which would be faster ?

Thank you.

Hawk.contains()

Would be good to have a method to check if the key exists

Hawk.contains(key)

Hawk should follow the common 'getInstance(...)' way of initialising and using the singleton instead of 'init(...)'

This would change the syntax from Hawk.init(...) and Hawk.put(...) to Hawk.getInstance(...).put(...) and so on. It's a much safer way to work with singletons because we let the Hawk instance initialise itself when required, because right now if we don't call 'init' and try to call Hawk.put(...) we get a NPE.

This also enables us to implement extra functionality like closing the instance when no longer required.

How does it Work??

Well u see if I use Hawk.put(key, T); in onCreate() method and I change its value afterwards then again if the activity is started, Will its Value change??

Feature Request: method returning all key-value pairs in storage

Can you implement a method returning all key-value pairs currently in storage?

I have just a few entries with Hawk (all wrapped as my own SettingsItem object) and i want to iterate over them without explicitely get every entry by key name. Something like a getAll()/toArray()/... method:

Hawk.put("key1", new SettingsItem());
Hawk.put("key2", new SettingsItem());

for (Object obj : Hawk.getAll()) {
   if(obj instanceof SettingsItem) {
      // do something
   }
}

I hope this can help generally and not only for my problem, perhaps you have a better (more general) idea.

Thanks for this easy to implement SharedPreference solution!

Storage interface methods return types

I think put, remove, and clear methods of Storage class can return the result of the operation because the user may want to take some action according to success or failure.

There should be a way of using password based encryption and not requiring to store the password variable in memory (in the HawkBuilder singleton instance)

This could be implemented by adding functionality to the Hawk class like resetPassword() and setPassword(String) when required, that would then set the password for the HawkBuilder instance. Or maybe put/get methods that take an extra password parameter.

This would be useful in apps that need to quickly put or get some secure info using Hawk and do not want the password used in encryption exposed to attackers (A rooted attacker could read the HawkBuilder object instance from memory and get the password variable value).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.