can-connect
Advanced tools
Comparing version 1.4.0 to 1.4.1
@@ -5,2 +5,4 @@ var QUnit = require("steal-qunit"); | ||
var baseMap = require("can-connect/can/base-map/"); | ||
var GLOBAL = require("can-util/js/global/global"); | ||
var stealClone = require("steal-clone"); | ||
@@ -59,1 +61,30 @@ QUnit.module("can-connect/can/base-map"); | ||
}); | ||
QUnit.test("uses jQuery if loaded", 2, function() { | ||
stop(); | ||
var old$ = GLOBAL().$; | ||
var fake$ = { | ||
ajax: function() {} | ||
}; | ||
GLOBAL().$ = fake$; | ||
stealClone({}).import("can-connect/can/base-map/base-map").then(function(baseMap) { | ||
var connection = baseMap({ | ||
Map: function() {}, | ||
List: function() {}, | ||
url: "/fake" | ||
}); | ||
QUnit.equal(connection.ajax, fake$.ajax, "ajax is set from existing $"); | ||
}).then(function() { | ||
GLOBAL().$ = undefined; | ||
return stealClone({}).import("can-connect/can/base-map/base-map"); | ||
}).then(function(baseMap) { | ||
var connection = baseMap({ | ||
Map: function() {}, | ||
List: function() {}, | ||
url: '' | ||
}); | ||
QUnit.equal(connection.ajax, undefined, "ajax is not set when no $"); | ||
GLOBAL().$ = old$; | ||
start(); | ||
}); | ||
}); |
@@ -13,5 +13,6 @@ var connect = require("can-connect"); | ||
var callbacksOnce = require("../../constructor/callbacks-once/callbacks-once"); | ||
var GLOBAL = require("can-util/js/global/global"); | ||
var $ = require("jquery"); | ||
var $ = GLOBAL().$; | ||
@@ -18,0 +19,0 @@ connect.baseMap = function(options){ |
@@ -36,2 +36,5 @@ var set = require("can-set"); | ||
ok(false,"Error "+e); | ||
setTimeout(function(){ | ||
throw e; | ||
},1); | ||
start(); | ||
@@ -61,3 +64,4 @@ }; | ||
due: "*", | ||
createdId: "*" | ||
createdId: "*", | ||
destroyed: "any" | ||
}); | ||
@@ -363,3 +367,3 @@ var TodoList = List.extend({ | ||
isSaving.bind("change", function(ev, newVal, oldVal){ | ||
isSaving.on("change", function(ev, newVal, oldVal){ | ||
isSavingCalls++; | ||
@@ -386,3 +390,3 @@ if(isSavingCalls === 1) { | ||
isDestroying.bind("change", function(ev, newVal, oldVal){ | ||
isDestroying.on("change", function(ev, newVal, oldVal){ | ||
isDestroyingCalls++; | ||
@@ -410,3 +414,3 @@ if(isSavingCalls === 1) { | ||
start(); | ||
}); | ||
}, logErrorAndStart); | ||
equal( todo.isSaving(), false, "isSaving is false" ); | ||
@@ -510,1 +514,56 @@ equal( todo.isDestroying(), true, "isDestroying is true" ); | ||
}); | ||
QUnit.asyncTest("instances bound before create are moved to instance store (#296)", function(){ | ||
var todoAlgebra = new set.Algebra( | ||
set.props.boolean("complete"), | ||
set.props.id("id"), | ||
set.props.sort("sort") | ||
); | ||
var todoStore = fixture.store([ | ||
{ name: "mow lawn", complete: false, id: 5 }, | ||
{ name: "dishes", complete: true, id: 6 }, | ||
{ name: "learn canjs", complete: false, id: 7 } | ||
], todoAlgebra); | ||
fixture("/theapi/todos", todoStore); | ||
var Todo = Map.extend({ | ||
id: "string", | ||
name: "string", | ||
complete: {type: "boolean", value: false} | ||
}); | ||
Todo.List = List.extend({ | ||
"#": Todo | ||
}); | ||
Todo.connection = connect([ | ||
constructor, | ||
canMap, | ||
constructorStore, | ||
dataCallbacks, | ||
dataUrl], | ||
{ | ||
url: "/theapi/todos", | ||
Map: Todo, | ||
List: Todo.List, | ||
name: "todo", | ||
algebra: todoAlgebra | ||
}); | ||
var newTodo = new Todo({name: "test superMap"}); | ||
newTodo.on("name", function(){}); | ||
newTodo.save().then(function(savedTodo){ | ||
Todo.get({id: savedTodo.id}).then(function(t){ | ||
QUnit.equal(t._cid, newTodo._cid); // NOK | ||
QUnit.start(); | ||
}); | ||
}); | ||
}); |
@@ -290,3 +290,6 @@ "use strict"; | ||
* Updates the instance with `props` and dispatches a | ||
* "created" event on the map and the map's constructor function. | ||
* "created" event on the map and the map's constructor function. Calls | ||
* [can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore] | ||
* to ensure instances "referenced" before being created are moved into the | ||
* [can-connect/constructor/store/store.instanceStore]. | ||
* | ||
@@ -339,2 +342,6 @@ * @param {Map} instance a Map instance | ||
} | ||
// This happens in constructor/store, but we don't call base, so we have to do it ourselves. | ||
if(funcName === "created" && this.moveCreatedInstanceToInstanceStore) { | ||
this.moveCreatedInstanceToInstanceStore(instance); | ||
} | ||
@@ -511,3 +518,6 @@ canMapBehavior.callbackInstanceEvents(funcName, instance); | ||
callCanReadingOnIdRead = false; | ||
connection.addInstanceReference(this); | ||
if(connection.addInstanceReference) { | ||
connection.addInstanceReference(this); | ||
} | ||
callCanReadingOnIdRead = true; | ||
@@ -520,3 +530,5 @@ return base.apply(this, arguments); | ||
callCanReadingOnIdRead = false; | ||
connection.deleteInstanceReference(this); | ||
if(connection.deleteInstanceReference) { | ||
connection.deleteInstanceReference(this); | ||
} | ||
callCanReadingOnIdRead = true; | ||
@@ -715,3 +727,5 @@ return base.apply(this, arguments); | ||
return function(){ | ||
connection.addListReference(this); | ||
if(connection.addListReference) { | ||
connection.addListReference(this); | ||
} | ||
if(base) { | ||
@@ -724,3 +738,5 @@ return base.apply(this, arguments); | ||
return function(){ | ||
connection.deleteListReference(this); | ||
if(connection.deleteListReference) { | ||
connection.deleteListReference(this); | ||
} | ||
if(base) { | ||
@@ -783,6 +799,5 @@ return base.apply(this, arguments); | ||
[ | ||
'id', 'get', 'updatedList', 'destroy', 'save', 'getList', 'deleteListReference', 'addListReference', | ||
'addInstanceReference' | ||
'id', 'get', 'updatedList', 'destroy', 'save', 'getList' | ||
] | ||
); | ||
//!steal-remove-end | ||
//!steal-remove-end |
var QUnit = require("steal-qunit"); | ||
var fixture = require("can-fixture"); | ||
var Map = require("can-map"); | ||
var DefineMap = require("can-define/map/map"); | ||
var DefineList = require("can-define/list/list"); | ||
var superMap = require("can-connect/can/super-map/"); | ||
var set = require("can-set"); | ||
var GLOBAL = require("can-util/js/global/global"); | ||
var stealClone = require("steal-clone"); | ||
QUnit.module("can-connect/can/super-map"); | ||
QUnit.module("can-connect/can/super-map",{ | ||
setup: function(){ | ||
localStorage.clear(); | ||
} | ||
}); | ||
@@ -115,1 +123,30 @@ QUnit.test("uses idProp", function(){ | ||
}); | ||
QUnit.test("uses jQuery if loaded", 2, function() { | ||
stop(); | ||
var old$ = GLOBAL().$; | ||
var fake$ = { | ||
ajax: function() {} | ||
}; | ||
GLOBAL().$ = fake$; | ||
stealClone({}).import("can-connect/can/super-map/super-map").then(function(superMap) { | ||
var connection = superMap({ | ||
Map: function() {}, | ||
List: function() {}, | ||
url: '' | ||
}); | ||
QUnit.equal(connection.ajax, fake$.ajax, "ajax is set from existing $"); | ||
}).then(function() { | ||
GLOBAL().$ = undefined; | ||
return stealClone({}).import("can-connect/can/super-map/super-map"); | ||
}).then(function(superMap) { | ||
var connection = superMap({ | ||
Map: function() {}, | ||
List: function() {}, | ||
url: '' | ||
}); | ||
QUnit.equal(connection.ajax, undefined, "ajax is not set when no $"); | ||
GLOBAL().$ = old$; | ||
start(); | ||
}); | ||
}); |
@@ -16,6 +16,6 @@ var connect = require("can-connect"); | ||
var callbacksOnce = require("../../constructor/callbacks-once/callbacks-once"); | ||
var GLOBAL = require("can-util/js/global/global"); | ||
var $ = GLOBAL().$; | ||
var $ = require("jquery"); | ||
connect.superMap = function(options){ | ||
@@ -22,0 +22,0 @@ |
@@ -355,2 +355,3 @@ | ||
var cid = this._cid++; | ||
// cid is really a token to be able to reference this transaction. | ||
this.cidStore.addReference(cid, instance); | ||
@@ -357,0 +358,0 @@ |
@@ -266,1 +266,34 @@ var QUnit = require("steal-qunit"); | ||
}); | ||
QUnit.asyncTest("instances bound before create are moved to instance store (#296)", function(){ | ||
var connection = connect([ | ||
function(){ | ||
var calls = 0; | ||
return { | ||
getData: function(){ | ||
return Promise.resolve({name: "test store", id: "abc"}); | ||
}, | ||
createData: function(){ | ||
return Promise.resolve({name: "test store", id: "abc"}); | ||
} | ||
}; | ||
}, | ||
constructor, | ||
instanceStore], | ||
{}); | ||
var todo = {name: "test store"}; | ||
connection.addInstanceReference(todo); | ||
connection.save(todo).then(function(savedTodo){ | ||
connection.get({id: savedTodo.id}).then(function(t){ | ||
QUnit.ok(t === todo, "instances the same"); | ||
QUnit.start(); | ||
}); | ||
}); | ||
}); |
@@ -5,4 +5,5 @@ /** | ||
* @group can-connect/constructor/store/store.stores 0 stores | ||
* @group can-connect/constructor/store/store.crud 1 crud methods | ||
* @group can-connect/constructor/store/store.hydrators 2 hydrators | ||
* @group can-connect/constructor/store/store.callbacks 1 crud callbacks | ||
* @group can-connect/constructor/store/store.crud 2 crud methods | ||
* @group can-connect/constructor/store/store.hydrators 3 hydrators | ||
* | ||
@@ -84,2 +85,3 @@ * Supports saving and retrieving lists and instances in a store. | ||
var WeakReferenceMap = require("can-connect/helpers/weak-reference-map"); | ||
var WeakReferenceSet = require("can-connect/helpers/weak-reference-set"); | ||
var sortedSetJSON = require("can-connect/helpers/sorted-set-json"); | ||
@@ -133,2 +135,5 @@ var canEvent = require("can-event"); | ||
instanceStore: new WeakReferenceMap(), | ||
// This really should be a set ... we just need it "weak" so we know how many references through binding | ||
// it has. | ||
newInstanceStore: new WeakReferenceSet(), | ||
/** | ||
@@ -232,4 +237,53 @@ * @property {can-connect/helpers/weak-reference-map} can-connect/constructor/store/store.listStore listStore | ||
addInstanceReference: function(instance, id) { | ||
this.instanceStore.addReference( id || this.id(instance), instance ); | ||
var ID = id || this.id(instance); | ||
if(ID === undefined) { | ||
// save in the newInstanceStore store temporarily. | ||
this.newInstanceStore.addReference(instance); | ||
} else { | ||
this.instanceStore.addReference( ID, instance ); | ||
} | ||
}, | ||
/** | ||
* @function can-connect/constructor/store/store.callbacks.createdInstance createdInstance | ||
* @parent can-connect/constructor/store/store.callbacks | ||
* | ||
* Updates the instance being created with the result of [can-connect/connection.createData]. | ||
* | ||
* @signature `connection.createdInstance( instance, props )` | ||
* | ||
* Calls the base behavior. Then calls [can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore]. | ||
* | ||
* @param {can-connect/Instance} instance The instance to update. | ||
* | ||
* @param {Object} props The data from [can-connect/connection.createData]. | ||
*/ | ||
createdInstance: function(instance, props){ | ||
// when an instance is created, and it is in the newInstance store | ||
// transfer it to the instanceStore | ||
baseConnection.createdInstance.apply(this, arguments); | ||
this.moveCreatedInstanceToInstanceStore(instance); | ||
}, | ||
/** | ||
* @function can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore moveCreatedInstanceToInstanceStore | ||
* @parent can-connect/constructor/store/store.stores | ||
* | ||
* Moves recently created instances into the [can-connect/constructor/store/store.instanceStore]. | ||
* | ||
* @signature `connection.createdInstance( instance )` | ||
* | ||
* Checks if an instance has an `id` and is in the `newInstanceStore`. If it does, moves it into the | ||
* [can-connect/constructor/store/store.instanceStore]. | ||
* | ||
* @param {can-connect/Instance} instance An instance. If it was "referenced" (bound to) prior to | ||
* being created, this will check for that condition and move this instance into the [can-connect/constructor/store/store.instanceStore]. | ||
*/ | ||
moveCreatedInstanceToInstanceStore: function(instance){ | ||
var ID = this.id(instance); | ||
if(this.newInstanceStore.has(instance) && ID !== undefined) { | ||
var referenceCount = this.newInstanceStore.referenceCount(instance); | ||
this.newInstanceStore.delete(instance); | ||
this.instanceStore.addReference( ID, instance, referenceCount ); | ||
} | ||
}, | ||
addInstanceMetaData: function(instance, name, value){ | ||
@@ -284,3 +338,10 @@ var data = this.instanceStore.set[this.id(instance)]; | ||
deleteInstanceReference: function(instance) { | ||
this.instanceStore.deleteReference( this.id(instance), instance ); | ||
var ID = this.id(instance); | ||
if(ID === undefined) { | ||
// if there is no id, remove this from the newInstanceStore | ||
this.newInstanceStore.deleteReference(instance); | ||
} else { | ||
this.instanceStore.deleteReference( this.id(instance), instance ); | ||
} | ||
}, | ||
@@ -287,0 +348,0 @@ /** |
@@ -5,2 +5,3 @@ var QUnit = require("steal-qunit"); | ||
var $ = require("jquery"); | ||
var set = require("can-set"); | ||
@@ -247,1 +248,49 @@ QUnit.module("can-connect/data/url",{ | ||
}); | ||
QUnit.asyncTest("fixture stores work with data (#298)", function(){ | ||
var todoStore = fixture.store([{ | ||
id: "1", | ||
name: "todo 1" | ||
}]); | ||
fixture("/v1/places/todos/{id}", todoStore); | ||
var connection = persist({ | ||
url: "/v1/places/todos/{id}" | ||
}); | ||
connection.getData({id: 1}).then(function(todo){ | ||
QUnit.equal(todo.name, "todo 1"); | ||
}).then(function(){ | ||
var algebra = new set.Algebra( | ||
set.props.id("_todoId") | ||
); | ||
var todoStore = fixture.store([{ | ||
_todoId: "1", | ||
name: "todo 1" | ||
}], algebra); | ||
fixture("/v2/places/todos", todoStore); | ||
var connection = persist({ | ||
url: "/v2/places/todos", | ||
algebra: algebra | ||
}); | ||
connection.getData({_todoId: "1"}).then(function(todo){ | ||
QUnit.equal(todo.name, "todo 1"); | ||
QUnit.start(); | ||
}); | ||
}); | ||
}); |
@@ -105,3 +105,6 @@ /** | ||
var connect = require("can-connect"); | ||
var makeRest = require("can-make-rest"); | ||
var defaultRest = makeRest("/resource/{id}"); | ||
var makePromise = require("can-util/js/make-promise/make-promise"); | ||
@@ -113,15 +116,21 @@ | ||
var urlBehavior = connect.behavior("data/url", function(baseConnection) { | ||
var behavior = {}; | ||
each(pairs, function(reqOptions, name) { | ||
behavior[name] = function(params) { | ||
each(defaultRest, function(defaultData, dataInterfaceName){ | ||
behavior[dataInterfaceName] = function(params) { | ||
var meta = methodMetaData[dataInterfaceName]; | ||
if(typeof this.url === "object") { | ||
if(typeof this.url[reqOptions.prop] === "function") { | ||
if(typeof this.url[dataInterfaceName] === "function") { | ||
return makePromise(this.url[reqOptions.prop](params)); | ||
return makePromise(this.url[dataInterfaceName](params)); | ||
} | ||
else if(this.url[reqOptions.prop]) { | ||
return makePromise(makeAjax(this.url[reqOptions.prop], params, reqOptions.type, this.ajax || ajax, findContentType(this.url), reqOptions)); | ||
else if(this.url[dataInterfaceName]) { | ||
var promise = makeAjax( | ||
this.url[dataInterfaceName], | ||
params, | ||
defaultData.method, | ||
this.ajax || ajax, | ||
findContentType(this.url), | ||
meta); | ||
return makePromise(promise); | ||
} | ||
@@ -133,8 +142,9 @@ } | ||
var idProps = getIdProps(this); | ||
return makePromise(makeAjax( createURLFromResource(resource, idProps[0] , | ||
reqOptions.prop ), | ||
params, reqOptions.type, | ||
var resourceWithoutTrailingSlashes = resource.replace(/\/+$/, ""); | ||
var result = makeRest(resourceWithoutTrailingSlashes, idProps[0])[dataInterfaceName]; | ||
return makePromise(makeAjax( result.url, | ||
params, result.method, | ||
this.ajax || ajax, | ||
findContentType(this.url), | ||
reqOptions)); | ||
meta)); | ||
} | ||
@@ -231,7 +241,5 @@ | ||
// ## pairs | ||
// The functions that will be created mapped to an object with: | ||
// - prop - the property to look for in connection.url for a url | ||
// - type - the default http method if one is not provided in the url | ||
var pairs = { | ||
// ## methodMetaData | ||
// Metadata on different methods that is passed to makeAjax | ||
var methodMetaData = { | ||
/** | ||
@@ -251,3 +259,3 @@ * @function can-connect/data/url/url.getListData getListData | ||
*/ | ||
getListData: {prop: "getListData", type: "GET"}, | ||
getListData: {}, | ||
/** | ||
@@ -267,3 +275,3 @@ * @function can-connect/data/url/url.getData getData | ||
*/ | ||
getData: {prop: "getData", type: "GET"}, | ||
getData: {}, | ||
/** | ||
@@ -285,3 +293,3 @@ * @function can-connect/data/url/url.createData createData | ||
*/ | ||
createData: {prop: "createData", type: "POST"}, | ||
createData: {}, | ||
/** | ||
@@ -302,3 +310,3 @@ * @function can-connect/data/url/url.updateData updateData | ||
*/ | ||
updateData: {prop: "updateData", type: "PUT"}, | ||
updateData: {}, | ||
/** | ||
@@ -319,3 +327,3 @@ * @function can-connect/data/url/url.destroyData destroyData | ||
*/ | ||
destroyData: {prop: "destroyData", type: "DELETE", includeData: false} | ||
destroyData: {includeData: false} | ||
}; | ||
@@ -381,12 +389,2 @@ | ||
var createURLFromResource = function(resource, idProp, name) { | ||
var url = resource.replace(/\/+$/, ""); | ||
if (name === "getListData" || name === "createData") { | ||
return url; | ||
} else { | ||
return url + "/{" + idProp + "}"; | ||
} | ||
}; | ||
module.exports = urlBehavior; | ||
@@ -397,2 +395,2 @@ | ||
module.exports = validate(urlBehavior, ['url']); | ||
//!steal-remove-end | ||
//!steal-remove-end |
@@ -32,2 +32,3 @@ // return wrapped can-connect behavior mixin that validates interface of the input behavior being extended | ||
// change to 'BehaviourInterfaceError extends Error' once we drop support for pre-ES2015 | ||
@@ -38,9 +39,17 @@ function BehaviorInterfaceError(baseBehavior, extendingBehavior, missingProps) { | ||
message = 'can-connect: Extending behavior "' + extendingName + '" found base behavior "' + baseName | ||
+ '" was missing required properties: ' + JSON.stringify(missingProps.related); | ||
+ '" was missing required properties: ' + JSON.stringify(missingProps.related), | ||
instance = new Error(message); | ||
this.name = 'BehaviorInterfaceError'; | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
if (Object.setPrototypeOf){ | ||
Object.setPrototypeOf(instance, Object.getPrototypeOf(this)); | ||
} | ||
return instance; | ||
} | ||
BehaviorInterfaceError.prototype = Object.create(Error.prototype); | ||
BehaviorInterfaceError.prototype.constructor = BehaviorInterfaceError; | ||
BehaviorInterfaceError.prototype = Object.create(Error.prototype, { | ||
constructor: {value: Error} | ||
}); | ||
if (Object.setPrototypeOf){ | ||
Object.setPrototypeOf(BehaviorInterfaceError, Error); | ||
} else { | ||
BehaviorInterfaceError.__proto__ = Error; | ||
} |
@@ -66,6 +66,8 @@ var assign = require("can-util/js/assign/assign"); | ||
*/ | ||
addReference: function(key, item){ | ||
addReference: function(key, item, referenceCount){ | ||
// !steal-remove-start | ||
if (typeof key === 'undefined'){ | ||
return; | ||
throw new Error("can-connect: You must provide a key to store a value in a WeakReferenceMap"); | ||
} | ||
// !steal-remove-end | ||
var data = this.set[key]; | ||
@@ -79,4 +81,10 @@ if(!data) { | ||
} | ||
data.referenceCount++; | ||
data.referenceCount += (referenceCount || 1); | ||
}, | ||
referenceCount: function(key) { | ||
var data = this.set[key]; | ||
if(data) { | ||
return data.referenceCount; | ||
} | ||
}, | ||
/** | ||
@@ -83,0 +91,0 @@ * @function can-connect/helpers/weak-reference-map.prototype.deleteReference deleteReference |
{ | ||
"name": "can-connect", | ||
"version": "1.4.0", | ||
"version": "1.4.1", | ||
"description": "Data connection middleware and utilities", | ||
@@ -12,2 +12,3 @@ "main": "can-connect.js", | ||
"can-list": "^3.0.1", | ||
"can-make-rest": "0.0.2", | ||
"can-map": "^3.0.3", | ||
@@ -21,6 +22,5 @@ "can-namespace": "1.0.0", | ||
"can-util": "^3.7.0", | ||
"can-validate-interface": "0.x", | ||
"can-validate-interface": "0.1.0", | ||
"can-view-callbacks": "^3.0.2", | ||
"can-view-nodelist": "^3.0.2", | ||
"jquery": "2.x - 3.x", | ||
"steal-stache": "^3.0.3" | ||
@@ -35,2 +35,3 @@ }, | ||
"jshint": "^2.9.4", | ||
"jquery": "2.x - 3.x", | ||
"steal": "^1.0.1", | ||
@@ -37,0 +38,0 @@ "steal-css": "^1.0.0", |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
507819
146
13353
0
8
+ Addedcan-make-rest@0.0.2
+ Addedcan-make-rest@0.0.2(transitive)
+ Addedcan-validate-interface@0.1.0(transitive)
- Removedjquery@2.x - 3.x
- Removedcan-validate-interface@0.1.2(transitive)
Updatedcan-validate-interface@0.1.0