Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

knockout-sync

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

knockout-sync - npm Package Compare versions

Comparing version 0.1.14 to 0.1.15

.travis.yml

3

Gruntfile.js

@@ -106,4 +106,5 @@ /*global module:false */

grunt.registerTask('build-dev', ['sweepout']);
grunt.registerTask('build', ['sweepout', 'requirejs']);
grunt.registerTask('test', ['simplemocha']);
grunt.registerTask('default', ['jshint', 'test']);
grunt.registerTask('travis', ['build-dev', 'jshint', 'test']);
};

@@ -18,2 +18,6 @@ var require = {

location: '../../lib/js/shimney/JSON'
},
{
name: 'jquery',
location: '../../lib/js/shimney/jquery'
}

@@ -20,0 +24,0 @@ ]

{
"name": "knockout-sync",
"version": "0.1.14",
"version": "0.1.15",
"description": "A small backend using knockout mapping to sync entities with a RESTful Backend",

@@ -10,3 +10,3 @@ "main": "Gruntfile.js",

"scripts": {
"test": "grunt test"
"test": "grunt travis"
},

@@ -13,0 +13,0 @@ "repository": {

@@ -1,4 +0,9 @@

knockout-sync
=============
# knockout-sync [![Build Status](https://travis-ci.org/webforge-labs/knockout-sync.svg)](https://travis-ci.org/webforge-labs/knockout-sync)
A small backend using knockout mapping to sync entities with a RESTful Backend
## installation
npm install knockout-sync
use the files as Asynchronous Module Definitions (for example with requirejs).

@@ -280,5 +280,6 @@ define(['./Exception', './EntityModel', 'lodash', 'knockout', 'knockout-mapping'], function(Exception, EntityModel, _, ko, koMapping) {

_.each(entityMeta.properties, function(property) {
var propertyEntityMeta;
if (that.isRelatedEntity(property)) {
var propertyEntityMeta = that.getEntityMeta(property.type);
propertyEntityMeta = that.getEntityMeta(property.type);

@@ -329,2 +330,12 @@ mapping[property.name] = {

};
} else if (that.isRelatedEntityCollection(property)) {
propertyEntityMeta = that.getEntityMeta(property.type);
mapping[property.name] = {
create: function(options) {
var fqn = that.getEntityFQNFromData(propertyEntityMeta, options.data); // this will always return propertyEntityMeta.fqn per default
return that.findOrHydrate(fqn, options.data);
}
};
}

@@ -340,2 +351,6 @@ });

this.isRelatedEntityCollection = function(property) {
return property.type && that.hasEntityMeta(property.type) && property.isCollection;
};
this.isMappedEntity = function(entity) {

@@ -342,0 +357,0 @@ return _.isObject(entity) && ko.isObservable(entity.id) && entity.fqn;

@@ -22,2 +22,3 @@ /* jshint expr:true */

var AuthorModel = requirejs('ACME/Blog/Entities/AuthorModel');
var PostModel = requirejs('ACME/Blog/Entities/PostModel');
var TagModel = requirejs('ACME/Blog/Entities/TagModel');

@@ -196,3 +197,65 @@ var ko = requirejs('knockout');

var postWithTagsResponse = {
"posts": [{
"id": 1,
"title": "Working with associations",
"author": {
"id": 2,
"name": "Alice",
"email": "alice@ps-webforge.com"
},
"tags": [
{
label: "doctrine"
},
{
label: "ORM"
}
]
}]
};
it("can get a mapped result to a single entity without attaching it", function() {
var posts = em.getMappedResponse('ACME.Blog.Entities.Post', postWithTagsResponse);
expect(ko.unwrap(posts)).to.have.length(1);
var expectPost = function(post) {
expect(post).to.have.property('id');
expect(post.id()).to.be.equal(1);
expect(post).to.have.property('author');
expect(post.author).to.be.an.instanceOf(AuthorModel);
expect(post.author.id()).to.be.equal(2);
expect(post).to.have.property('tags');
expect(ko.isObservable(post.tags) && post.tags.indexOf !== undefined, 'post.tags should be an observable array').to.be.ok;
expect(post.tags()).to.have.length(2);
expect(em.find('ACME.Blog.Entities.Post', 1), 'entity should not be attached from getMappedResponse').to.be.not.ok;
};
expectPost(posts()[0]);
var post = em.getSingleMappedResponse('ACME.Blog.Entities.Post', postWithTagsResponse);
expectPost(post);
});
it("maps entity collections of an entity to a collection of entities", function() {
var posts = em.getMappedResponse('ACME.Blog.Entities.Post', postWithTagsResponse);
expect(ko.unwrap(posts)).to.have.length(1);
var post = posts()[0];
expect(post).to.have.property('tags');
expect(ko.isObservable(post.tags) && post.tags.indexOf !== undefined, 'post.tags should be an observable array').to.be.ok;
var tag = post.tags()[0];
expect(tag, 'tag should be an entity of ACME.Blog.Entities.Tag').to.be.instanceOf(TagModel);
});
it.skip("do map carefully too nested responses", function() {
var response = {

@@ -206,3 +269,19 @@ "posts": [{

"name": "Alice",
"email": "alice@ps-webforge.com"
"email": "alice@ps-webforge.com",
"posts": [{
"id": 1,
"title": "Working with associations",
"author": null,
"tags": [
{
label: "doctrine"
},
{
label: "ORM"
}
]
}]
},

@@ -224,21 +303,18 @@

var expectPost = function(post) {
expect(post).to.have.property('id');
expect(post.id()).to.be.equal(1);
var post = posts()[0];
expect(post).to.have.property('author');
expect(post.author.id()).to.be.equal(2);
expect(post).to.have.property('author');
expect(post.author).to.be.an.instanceOf(AuthorModel);
expect(post).to.have.property('tags');
expect(post.tags()).to.have.length(2);
expect(post.author).to.have.property('posts');
expect(em.find('ACME.Blog.Entities.Post', 1), 'entity should not be attached from getMappedResponse').to.be.not.ok;
};
var nestedPosts = post.author.posts;
expect(ko.isObservable(nestedPosts) && nestedPosts.indexOf !== undefined, 'post[0].author.posts should be an observable array').to.be.ok;
expectPost(posts()[0]);
var nestedPost = nestedPosts()[0];
var post = em.getSingleMappedResponse('ACME.Blog.Entities.Post', response);
expectPost(post);
expect(nestedPost).to.be.an.instanceOf(PostModel);
});
it("throws an error in getSingleMappedResponse when more than one root entity is defined", function() {

@@ -245,0 +321,0 @@ var response = {

@@ -36,17 +36,25 @@ {

},
"content":{
"name":"content",
"type":"MarkupText"
},
"author":{
"name":"author",
"type":"ACME\\Blog\\Entities\\Author"
"type":"ACME\\Blog\\Entities\\Author",
"isCollection":false
},
"revisor":{
"name":"revisor",
"type":"ACME\\Blog\\Entities\\Author"
"type":"ACME\\Blog\\Entities\\Author",
"isCollection":false
},
"categories":{
"name":"categories",
"type":"ACME\\Blog\\Entities\\Category"
"type":"ACME\\Blog\\Entities\\Category",
"isCollection":true
},
"tags":{
"name":"tags",
"type":"ACME\\Blog\\Entities\\Tag"
"type":"ACME\\Blog\\Entities\\Tag",
"isCollection":true
},

@@ -57,2 +65,6 @@ "active":{

},
"relevance":{
"name":"relevance",
"type":"Float"
},
"created":{

@@ -79,7 +91,9 @@ "name":"created",

"name":"writtenPosts",
"type":"ACME\\Blog\\Entities\\Post"
"type":"ACME\\Blog\\Entities\\Post",
"isCollection":true
},
"revisionedPosts":{
"name":"revisionedPosts",
"type":"ACME\\Blog\\Entities\\Post"
"type":"ACME\\Blog\\Entities\\Post",
"isCollection":true
}

@@ -103,3 +117,4 @@ }

"name":"posts",
"type":"ACME\\Blog\\Entities\\Post"
"type":"ACME\\Blog\\Entities\\Post",
"isCollection":true
}

@@ -128,7 +143,7 @@ }

{
"name":"ContentStream\\Paragraph",
"fqn":"ACME\\Blog\\Entities\\ContentStream\\Paragraph",
"singular":"content-stream_paragraph",
"plural":"content-stream_paragraphs",
"tableName":"content_stream_paragraphs",
"name":"Page",
"fqn":"ACME\\Blog\\Entities\\Page",
"singular":"page",
"plural":"pages",
"tableName":"pages",
"extends":null,

@@ -141,5 +156,10 @@ "description":null,

},
"content":{
"name":"content",
"slug":{
"name":"slug",
"type":"String"
},
"contentStreams":{
"name":"contentStreams",
"type":"ACME\\Blog\\Entities\\ContentStream\\Entry",
"isCollection":true
}

@@ -161,9 +181,71 @@ }

},
"paragraphs":{
"name":"paragraphs",
"type":"ACME\\Blog\\Entities\\ContentStream\\Paragraph"
"entries":{
"name":"entries",
"type":"ACME\\Blog\\Entities\\ContentStream\\Entry",
"isCollection":true
},
"page":{
"name":"page",
"type":"ACME\\Blog\\Entities\\Page",
"isCollection":false
}
}
},
{
"name":"ContentStream\\Entry",
"fqn":"ACME\\Blog\\Entities\\ContentStream\\Entry",
"singular":"content-stream_entry",
"plural":"content-stream_entries",
"tableName":"content_stream_entries",
"extends":null,
"description":null,
"properties":{
"id":{
"name":"id",
"type":"Id"
},
"contentStream":{
"name":"contentStream",
"type":"ACME\\Blog\\Entities\\ContentStream\\Stream",
"isCollection":false
}
}
},
{
"name":"ContentStream\\Paragraph",
"fqn":"ACME\\Blog\\Entities\\ContentStream\\Paragraph",
"singular":"content-stream_paragraph",
"plural":"content-stream_paragraphs",
"tableName":"content_stream_paragraphs",
"extends":"ACME\\Blog\\Entities\\ContentStream\\Entry",
"description":null,
"properties":{
"content":{
"name":"content",
"type":"String"
}
}
},
{
"name":"ContentStream\\TextBlock",
"fqn":"ACME\\Blog\\Entities\\ContentStream\\TextBlock",
"singular":"content-stream_text-block",
"plural":"content-stream_text-blocks",
"tableName":"content_stream_text_blocks",
"extends":"ACME\\Blog\\Entities\\ContentStream\\Entry",
"description":null,
"properties":{
"paragraph1":{
"name":"paragraph1",
"type":"ACME\\Blog\\Entities\\ContentStream\\Paragraph",
"isCollection":false
},
"paragraph2":{
"name":"paragraph2",
"type":"ACME\\Blog\\Entities\\ContentStream\\Paragraph",
"isCollection":false
}
}
}
]
}

@@ -24,7 +24,9 @@ {

"id": { "type": "DefaultId" },
"content": { "type": "MarkupText" },
"author": { "type": "Author" },
"revisor": { "type": "Author", "nullable": true },
"categories": { "type": "Collection<Category>", "isOwning": true },
"categories": { "type": "Collection<Category>", "isOwning": true, "cascade": ["persist", "remove"] },
"tags": { "type": "Collection<Tag>" },
"active": { "type": "Boolean" },
"relevance": { "type": "Float", "nullable": true },
"created": { "type": "DateTime" },

@@ -68,12 +70,13 @@ "modified": { "type": "DateTime", "nullable": true }

{
"name": "ContentStream\\Paragraph",
"name": "Page",
"properties": {
"id": { "type": "DefaultId" },
"content": { "type": "String" }
"slug": { "type": "String" },
"contentStreams": { "type": "Collection<ContentStream\\Entry>" }
},
"constructor": ["content"]
"constructor": ["slug"]
},

@@ -87,8 +90,41 @@

"paragraphs": { "type": "Collection<ContentStream\\Paragraph>" }
"entries": { "type": "Collection<ContentStream\\Entry>" },
"page": { "type": "Page", "nullable": true, "onDelete": "cascade" }
},
"constructor": []
},
{
"name": "ContentStream\\Entry",
"properties": {
"id": { "type": "DefaultId" },
"contentStream": { "type": "ContentStream\\Stream" }
}
},
{
"name": "ContentStream\\Paragraph",
"extends": "ContentStream\\Entry",
"properties": {
"content": { "type": "String" }
},
"constructor": ["content"]
},
{
"name": "ContentStream\\TextBlock",
"extends": "ContentStream\\Entry",
"properties": {
"paragraph1": { "type": "ContentStream\\Paragraph", "relation": "ManyToOne" },
"paragraph2": { "type": "ContentStream\\Paragraph" }
}
}
]
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc