Giter Site home page Giter Site logo

coconut.data's People

Contributors

back2dos avatar benmerckx avatar kevinresol avatar sh-dave avatar testcodespaceerfer avatar

Stargazers

 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

coconut.data's Issues

Typing errors in model does not report the correct position

image

ProductData.hx:6: characters 12-65 : Error#500: Type name ProductResponse is already defined in this module @ #pos((unknown))

Like this, the typing error is reported in the model. But obviously it should be somewhere else.
Because the reported place is not defining any types, opposing to what the error says.

Review guards design.

Guards are a currently undocumented feature, that work roughly like so:

class Example implements Model [
  @:guard(Math.max(0, Math.min(1, next))
  @:editable var volume:Float = 3;
}

The guard is called on every update of an editable or observable property, with prev being the previous and next being the next value. However it's not called upon construction. In this particular case having an abstract over float that does the clamping would be more elegant. Perhaps guards should simply be removed again.

Having $last on multiple inner scopes leads to compile error

I get a compile error when having something like this in a Model (code just written out of the top of my head, sorry):

class MyModel implements Model {
    @:loaded var somethingAmazing:Int = {
        if (incredibleProperty == 0) calculatePlanToConquerWorld($last);
        else if (incredibleProperty == 1) haveBreakfastBeforeConqueringTheWorld($last);
        else conquerWorld();
    };

    @:editable private var incredibleProperty:Int = -1;

    function calculatePlanToConquerWorld(whoKnows:Int) return Future.sync(1);
    function haveBreakfastBeforeConqueringTheWorld(whoKnows:Int) return Future.sync(2);
}

It seems both $lasts are replaced by the same variable that is generated in the same scope as whichever is processed first (assumption based just in the error message and that having a top level $last or single inner scope $last works).

[0.8.1] Cannot read property for external value

Here is the minimal example that should be able to reproduce the issue. Note that 0.7.0 runs fine, problem occurs only in 0.8.1:

static public function main(){
    new Minimal({list: []});
}

class Minimal implements coconut.data.Model {
    @:constant var list:tink.pure.List<String>;
    @:constant var child:MinimalChild = new MinimalChild({list:list});
}

class MinimalChild implements coconut.data.Model {
    @:external var list:tink.pure.List<String>;
}

Data check fails for recursive types

The following code causes a stack overflow:

import coconut.data.*;

class Main {
    static function main() {
        new Data({e:None});
    }
}

class Data implements Model {
    @:constant var e:MyEnum;
}

enum MyEnum {
    None;
    Some(e:MyEnum);
}

Add coconut-specific @:forward

I think coconut could benefit from it's own extended version of tink_lang's @:forward

Limitations of using @:forward now:

  • Doesn't generate an observable for the property
  • If the target field's properties allow write access (e.g. a simple VO with plain vars, marked @:observable), setters will be generated (on the other hand it can be argued that the VOs should be properly defined as immutable)
  • Haven't tried this: if properties are forwarded to a nested coconut model, is every kind of property forwarded correctly?

attr casting broken

The following used to work:

class Main extends coconut.ui.View {
	@:attr var f:Float = 2;
	
  static function main() {}
  
  function render() '<div/>';
}

but now it gives:

src/Main.hx:4: characters 23-24 : Int should be Null<coconut.data.Value<Float>>
src/Main.hx:4: characters 23-24 : For optional function argument 'defaultData'

@:pure meta not respected on intermediate abstract

class Main {
    public static function main() {}
}

class MyModel implements  coconut.data.Model {
    @:constant var color:Hsv;
}

abstract Hsv(Base) {}

@:pure
abstract Base(Array<Float>) {}

error: Hsv is not observable, because Array<Float> is not observable, because Array<Float> is not observable because the field "length" is mutable

Moving @:pure to Hsv will work though.

How to refresh a @:loaded property?

Now I am using a ugly hack:

class Roles implements Model {
	@:observable var date:Date = @byDefault Date.now();
	@:loaded var all:List<RoleResponse> = {date; Remote.fetchData();}
	
	@:transition
	function add(name:String) {
		return Remote.addItem()
			.next(function(_) return {date: Date.now()});
	}
}

ocaml error with coconut data

hi,
with this example that i have created https://github.com/francescoagati/coconut-data-error with haxe 4 rc2 i get this error ocaml

Typing tink.core.SignalTrigger.new
Typing tink.core.SignalTrigger.asSignal
Typing tink.core.Signal.Signal_Impl.trigger
Typing Store.update
Calling macro tink.macro.Types.resolveDirectType (C:\HaxeToolkit\haxe\lib\tink_macro/git/src/tink/macro/Types.hx:233)
Exiting macro tink.macro.Types.resolveDirectType
File "_build/src/macro/eval/evalContext.ml", line 342, characters 2-8: Assertion failed

Array and Map

How to use Array and Map inside Model?

@:editable var aviableLanguages:Array<String> = [];

this code gives me error that its not Observable, right now silenced it with @:skipCheck, but don't feel that is best option.

Thank you

<interface> is not acceptable coconut data

Not sure why interface is rejected while structure is ok

interface MyInterface {
  function myFunc():Void;
}
typedef MyTypedef = {
  function myFunc():Void;
}
class Data implements Model {
  @:constant var myTypedef:MyTypedef; // ok
  @:constant var myInterface:MyInterface; // fail
}

Callback when a model goes out of use.

It should be possible to detect when none of a model's observable/editable properties are in use and so that any underlying subscriptions (to a websocket or something) can be cleaned up.

Introduce a metadata to replace hardcoded considerValid()

static function considerValid(pack:Array<String>, name:String)
return
switch pack.concat([name]).join('.') {
case 'Date' | 'Int' | 'String' | 'Bool' | 'Float': true;
case 'tink.pure.List': true;
case 'tink.Url': true;
default:
switch [pack, name] {
case [['tink', 'core'], 'NamedWith' | 'Pair' | 'Lazy' | 'TypedError' | 'Future' | 'Promise']: true;
default: false;
};
}

This should make it easier to create custom structures.

Add undo/redo support.

  • opt in per model with @:history
  • collate changes on the same model (if they aren't too far apart in time).

Allow for custom constructors.

A way this could work would be:

class Model {
  @:constant var foo:Foo;
  @:constant var bar:Bar;
  public function new(arg1:T1, arg2:T2) {
    // pre-construct
    this = { foo: ..., bar: ... };
    // post-construct
  }
}

//Becomes:

class Model {
  @:constant var foo:Foo;
  @:constant var bar:Bar;
  public function new(arg1:T1, arg2:T2) {
    var initial = __cocoInit(argType);
    // the usual initialization code
    // post-construct
  }
  static function __cocoInit(arg1:T1, arg2:T2):{ foo:Foo, bar:Bar } {
     // pre-construct
     return { foo: ..., bar: ... };
  }

}

This way it'll still be impossible to mess with the model while it's not yet initialized.

Do not generate `initial:{}` in model constructor, if it has no arguments.

This compiles (because of a weird unification rule for {}):

class Example implements Model {
  @:editable var foo:Int = 0;
  @:editable var bar:Int = 0;
}

new Example({
  foo: 12,
  bar: 13,
});

But it certainly doesn't do what's expected. The type of initial should probably be changed to Noise or something else that will cause a compiler error.

Coconut fails to cast abstract from Value<T> in hxx

Consider having the following:

@:forward
abstract LanguageString(String) from String to String {}

typedef DialogData = {
   final header:Value<LanguageString>;
}
//in hxx
@:attr var data:DialogData;
function render() <Text>${data.header}</Text>;

This will give compilation error:
Array<coconut.data.Value<LanguageString>> should be Null<react.ReactFragment>
unless provided with type hint like so <Text>${(item.header:String)}</Text>.

This seem to be a regression as this was working with older versions.

No error when @:transition is used with an @:editable property

I forgot to change @:editable to @:observable when refactoring a coconut model to use a transition function:

@:editable var balance:Float = 0;

@:transition function setBalance(value:Float) return {balance: value};

The code compiles and doesn't cause run-time errors either, it just doesn't update the balance property. It would be nice if mistakes like this would be caught, preferably at compile-time.

Test data validation

We need proper testing for the validation logic:

Here is one, for 3922226

package;

class Main implements coconut.data.Model {
	@:constant var data:Data;
	static function main() {}
}

abstract Data(VarChar<255>) {}

typedef VarChar<@:const P> = String;

Value not created from T in rc5

Problem is that on rc3 Value was created out of T automagically like so

var a:Value<Int>;
a = 42;

and since rc5 this cast gives me compilation error so I have to create it basically from State:

var a:Value<Int>;
a = new State(23); 

Is this expected?

Promised + List = view not updated

import coconut.data.*;
import haxe.Timer.delay;
using tink.CoreApi;
using tink.state.Promised;

class Main {
    static function main() {
        var data = new Data();
        data.observables.details.bind(function(o:tink.state.Promised<Details>) {
            switch o {
                case Loading: 
                case Done(details): 
                    delay(function() {
                        trace('update');
                        details.list.first().orNull().value += 1;
                    }, 1000);
                case Failed(e):
            }
        });
        
        js.Browser.document.body.appendChild(new View({value: data.details.map(function(details) return details.list.first().orNull().value)}).toElement());
    }
}

class View extends coconut.ui.View<{value:Promised<Int>}> {
    function render() '
        <div>
            <switch ${value}>
                <case ${Loading}>
                    Loading
                <case ${Done(value)}>
                    ${Std.string(value)}
                <case ${_}>
            </switch>
        </div>
    ';
}

class Data implements Model {
    @:loaded var details:Details = Future.async(function(cb) delay(cb.bind(new Details()), 1000));
}

class Details implements Model {
    @:constant var list:List<Value> = @byDefault List.fromArray([new Value()]);
}

class Value implements Model {
    @:editable var value:Int = @byDefault 0;
}

Custom constructors

Yes I am back.

Most likely this is needed for some custom init, obviously.

I have been doing something like this many times:
https://github.com/kevinresol/coconut.router/blob/f5c324f/src/coconut/router/RouteData.hx#L14-L15

This is mostly for @:external. While it is named external, it doesn't need to be external (in terms of OOP classes). They are merely non-coconut-managed observables. In the above example, url is @:external and basically it observes window.location.href. And since I need to set up the required listeners, I need an custom constructor like this:

// wished
function new() {
  var state = new State(location.href);
  setupListenerToLocationhref(state);
  super({url: state.observe());
}
// currently
public static function create() {
  var state = new State(location.href);
  setupListenerToLocationhref(state);
  return new Data({url: state.observe());
}

In other words, I am merely trying to prepare the required init inline, and ultimately I am going to pass the init object to super().

I worked around it with a static function. But the problem is that I need to make sure I use it instead of the constructor, otherwise I am doomed.

Model persistence examples?

It would be great with an example or two how to best deal with model persistence, at least from and to json data.

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.