{"action":"created","comment":{"url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/comments/60470658","id":60470658,"diff_hunk":"@@ -198,18 +202,114 @@ function transformWhere(schema, className, restWhere, options = {validate: true}\n   return mongoWhere;\n }\n \n+const parseObjectKeyValueToMongoObjectKeyValue = (\n+  schema,\n+  className,\n+  restKey,\n+  restValue,\n+  parseFormatSchema\n+) => {\n+  // Check if the schema is known since it's a built-in field.\n+  let transformedValue;\n+  let coercedToDate;\n+  switch(restKey) {\n+  case 'objectId': return {key: '_id', value: restValue};\n+  case '_created_at'://TODO: for some reason, _PushStatus is already transformed when it gets here. For now,\n+  // just pass the _created_at through. Later, we should make sure the push status doesn't get transformed inside Parse Server.\n+  case 'createdAt':\n+    transformedValue = transformAtom(restValue, false);\n+    coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue\n+    return {key: '_created_at', value: coercedToDate};\n+  case 'updatedAt':\n+    transformedValue = transformAtom(restValue, false);\n+    coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue\n+    return {key: '_updated_at', value: coercedToDate};\n+  case 'expiresAt':\n+    transformedValue = transformAtom(restValue, false);\n+    coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue\n+    return {key: 'expiresAt', value: coercedToDate};\n+  case '_id': //TODO: for some reason, _PushStatus is already transformed when it gets here. For now,\n+  // just pass the ID through. Later, we should make sure the push status doesn't get transformed inside Parse Server.\n+  case '_rperm':\n+  case '_wperm':\n+  case '_email_verify_token':\n+  case '_hashed_password':\n+  case '_perishable_token': return {key: restKey, value: restValue};\n+  case 'sessionToken': return {key: '_session_token', value: restValue};\n+  default:\n+    // Auth data should have been transformed already\n+    if (restKey.match(/^authData\\.([a-zA-Z0-9_]+)\\.id$/)) {\n+      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'can only query on ' + restKey);\n+    }\n+    // Trust that the auth data has been transformed and save it directly\n+    if (restKey.match(/^_auth_data_[a-zA-Z0-9_]+$/)) {\n+      return {key: restKey, value: restValue};\n+    }\n+  }\n+  //skip straight to transformAtom for Bytes, they don't show up in the schema for some reason\n+  if (restValue && restValue.__type !== 'Bytes') {\n+    //Note: We may not know the type of a field here, as the user could be saving (null) to a field\n+    //That never existed before, meaning we can't infer the type.\n+    if (parseFormatSchema.fields[restKey] && parseFormatSchema.fields[restKey].type == 'Pointer' || restValue.__type == 'Pointer') {\n+      restKey = '_p_' + restKey;\n+    }\n+  }\n+\n+  // Handle atomic values\n+  var value = transformAtom(restValue, false, { inArray: false, inObject: false });\n+  if (value !== CannotTransform) {\n+    return {key: restKey, value: value};\n+  }\n+\n+  // ACLs are handled before this method is called\n+  // If an ACL key still exists here, something is wrong.\n+  if (restKey === 'ACL') {\n+    throw 'There was a problem transforming an ACL.';\n+  }\n+\n+  // Handle arrays\n+  if (restValue instanceof Array) {\n+    value = restValue.map((restObj) => {\n+      var out = transformKeyValue(schema, className, restKey, restObj, { inArray: true });\n+      return out.value;\n+    });\n+    return {key: restKey, value: value};\n+  }\n+\n+  // Handle update operators\n+  value = transformUpdateOperator(restValue, true);\n+  if (value !== CannotTransform) {\n+    return {key: restKey, value: value};\n+  }\n+\n+  // Handle normal objects by recursing\n+  value = {};\n+  for (var subRestKey in restValue) {\n+    var subRestValue = restValue[subRestKey];\n+    var out = transformKeyValue(schema, className, subRestKey, subRestValue, { inObject: true });\n+    // For recursed objects, keep the keys in rest format\n+    value[subRestKey] = out.value;\n+  }\n+  return {key: restKey, value: value};\n+}\n+\n // Main exposed method to create new objects.\n // restCreate is the \"create\" clause in REST API form.\n-// Returns the mongo form of the object.\n-function parseObjectToMongoObject(schema, className, restCreate) {\n+function parseObjectToMongoObjectForCreate(schema, className, restCreate, parseFormatSchema) {","path":"src/Adapters/Storage/Mongo/MongoTransform.js","position":200,"original_position":200,"commit_id":"740187a63c9ea446ba141a3e5942bd4d36eea89b","original_commit_id":"3fceb228cc30584a302f7fc0c60a6ff853270966","user":{"login":"drew-gross","id":558242,"avatar_url":"https://avatars.githubusercontent.com/u/558242?v=3","gravatar_id":"","url":"https://api.github.com/users/drew-gross","html_url":"https://github.com/drew-gross","followers_url":"https://api.github.com/users/drew-gross/followers","following_url":"https://api.github.com/users/drew-gross/following{/other_user}","gists_url":"https://api.github.com/users/drew-gross/gists{/gist_id}","starred_url":"https://api.github.com/users/drew-gross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drew-gross/subscriptions","organizations_url":"https://api.github.com/users/drew-gross/orgs","repos_url":"https://api.github.com/users/drew-gross/repos","events_url":"https://api.github.com/users/drew-gross/events{/privacy}","received_events_url":"https://api.github.com/users/drew-gross/received_events","type":"User","site_admin":false},"body":"Yes. forUpdate would handle the atomic update operators like increment, pull, pullAll, addUnique, etc. For new object creation, those don't make any sense. Currently they are handled here by translating them to just field creation (eg. increment by 1 just becomes 1), but they probably shouldn't be. Willing to reconsider though, if you have opinions.","created_at":"2016-04-20T19:18:20Z","updated_at":"2016-04-20T19:18:20Z","html_url":"https://github.com/ParsePlatform/parse-server/pull/1569#discussion_r60470658","pull_request_url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569","_links":{"self":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/comments/60470658"},"html":{"href":"https://github.com/ParsePlatform/parse-server/pull/1569#discussion_r60470658"},"pull_request":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569"}}},"pull_request":{"url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569","id":67236287,"html_url":"https://github.com/ParsePlatform/parse-server/pull/1569","diff_url":"https://github.com/ParsePlatform/parse-server/pull/1569.diff","patch_url":"https://github.com/ParsePlatform/parse-server/pull/1569.patch","issue_url":"https://api.github.com/repos/ParsePlatform/parse-server/issues/1569","number":1569,"state":"open","locked":false,"title":"Begin isolating object creation code into an externalizable API.","user":{"login":"drew-gross","id":558242,"avatar_url":"https://avatars.githubusercontent.com/u/558242?v=3","gravatar_id":"","url":"https://api.github.com/users/drew-gross","html_url":"https://github.com/drew-gross","followers_url":"https://api.github.com/users/drew-gross/followers","following_url":"https://api.github.com/users/drew-gross/following{/other_user}","gists_url":"https://api.github.com/users/drew-gross/gists{/gist_id}","starred_url":"https://api.github.com/users/drew-gross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drew-gross/subscriptions","organizations_url":"https://api.github.com/users/drew-gross/orgs","repos_url":"https://api.github.com/users/drew-gross/repos","events_url":"https://api.github.com/users/drew-gross/events{/privacy}","received_events_url":"https://api.github.com/users/drew-gross/received_events","type":"User","site_admin":false},"body":"This makes a copy of transformKeyValue, strips out all the parts not relevant to creating new objects, and uses that for `createObject` in the db adapter. It will still require some more tweaks later.","created_at":"2016-04-20T18:33:46Z","updated_at":"2016-04-20T19:18:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"15877f847c366efed52b25f90d62d1319fe1829b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569/commits","review_comments_url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569/comments","review_comment_url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ParsePlatform/parse-server/issues/1569/comments","statuses_url":"https://api.github.com/repos/ParsePlatform/parse-server/statuses/740187a63c9ea446ba141a3e5942bd4d36eea89b","head":{"label":"drew-gross:kill-isPointer","ref":"kill-isPointer","sha":"740187a63c9ea446ba141a3e5942bd4d36eea89b","user":{"login":"drew-gross","id":558242,"avatar_url":"https://avatars.githubusercontent.com/u/558242?v=3","gravatar_id":"","url":"https://api.github.com/users/drew-gross","html_url":"https://github.com/drew-gross","followers_url":"https://api.github.com/users/drew-gross/followers","following_url":"https://api.github.com/users/drew-gross/following{/other_user}","gists_url":"https://api.github.com/users/drew-gross/gists{/gist_id}","starred_url":"https://api.github.com/users/drew-gross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drew-gross/subscriptions","organizations_url":"https://api.github.com/users/drew-gross/orgs","repos_url":"https://api.github.com/users/drew-gross/repos","events_url":"https://api.github.com/users/drew-gross/events{/privacy}","received_events_url":"https://api.github.com/users/drew-gross/received_events","type":"User","site_admin":false},"repo":{"id":51231720,"name":"parse-server","full_name":"drew-gross/parse-server","owner":{"login":"drew-gross","id":558242,"avatar_url":"https://avatars.githubusercontent.com/u/558242?v=3","gravatar_id":"","url":"https://api.github.com/users/drew-gross","html_url":"https://github.com/drew-gross","followers_url":"https://api.github.com/users/drew-gross/followers","following_url":"https://api.github.com/users/drew-gross/following{/other_user}","gists_url":"https://api.github.com/users/drew-gross/gists{/gist_id}","starred_url":"https://api.github.com/users/drew-gross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drew-gross/subscriptions","organizations_url":"https://api.github.com/users/drew-gross/orgs","repos_url":"https://api.github.com/users/drew-gross/repos","events_url":"https://api.github.com/users/drew-gross/events{/privacy}","received_events_url":"https://api.github.com/users/drew-gross/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/drew-gross/parse-server","description":"Parse-compatible API server module for Node/Express","fork":true,"url":"https://api.github.com/repos/drew-gross/parse-server","forks_url":"https://api.github.com/repos/drew-gross/parse-server/forks","keys_url":"https://api.github.com/repos/drew-gross/parse-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/drew-gross/parse-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/drew-gross/parse-server/teams","hooks_url":"https://api.github.com/repos/drew-gross/parse-server/hooks","issue_events_url":"https://api.github.com/repos/drew-gross/parse-server/issues/events{/number}","events_url":"https://api.github.com/repos/drew-gross/parse-server/events","assignees_url":"https://api.github.com/repos/drew-gross/parse-server/assignees{/user}","branches_url":"https://api.github.com/repos/drew-gross/parse-server/branches{/branch}","tags_url":"https://api.github.com/repos/drew-gross/parse-server/tags","blobs_url":"https://api.github.com/repos/drew-gross/parse-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/drew-gross/parse-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/drew-gross/parse-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/drew-gross/parse-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/drew-gross/parse-server/statuses/{sha}","languages_url":"https://api.github.com/repos/drew-gross/parse-server/languages","stargazers_url":"https://api.github.com/repos/drew-gross/parse-server/stargazers","contributors_url":"https://api.github.com/repos/drew-gross/parse-server/contributors","subscribers_url":"https://api.github.com/repos/drew-gross/parse-server/subscribers","subscription_url":"https://api.github.com/repos/drew-gross/parse-server/subscription","commits_url":"https://api.github.com/repos/drew-gross/parse-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/drew-gross/parse-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/drew-gross/parse-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/drew-gross/parse-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/drew-gross/parse-server/contents/{+path}","compare_url":"https://api.github.com/repos/drew-gross/parse-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/drew-gross/parse-server/merges","archive_url":"https://api.github.com/repos/drew-gross/parse-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/drew-gross/parse-server/downloads","issues_url":"https://api.github.com/repos/drew-gross/parse-server/issues{/number}","pulls_url":"https://api.github.com/repos/drew-gross/parse-server/pulls{/number}","milestones_url":"https://api.github.com/repos/drew-gross/parse-server/milestones{/number}","notifications_url":"https://api.github.com/repos/drew-gross/parse-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/drew-gross/parse-server/labels{/name}","releases_url":"https://api.github.com/repos/drew-gross/parse-server/releases{/id}","deployments_url":"https://api.github.com/repos/drew-gross/parse-server/deployments","created_at":"2016-02-07T01:58:26Z","updated_at":"2016-02-07T01:58:27Z","pushed_at":"2016-04-20T19:15:45Z","git_url":"git://github.com/drew-gross/parse-server.git","ssh_url":"git@github.com:drew-gross/parse-server.git","clone_url":"https://github.com/drew-gross/parse-server.git","svn_url":"https://github.com/drew-gross/parse-server","homepage":null,"size":1700,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"ParsePlatform:master","ref":"master","sha":"59b4047de84c3889bf77915ef83c142ada0541bd","user":{"login":"ParsePlatform","id":1294580,"avatar_url":"https://avatars.githubusercontent.com/u/1294580?v=3","gravatar_id":"","url":"https://api.github.com/users/ParsePlatform","html_url":"https://github.com/ParsePlatform","followers_url":"https://api.github.com/users/ParsePlatform/followers","following_url":"https://api.github.com/users/ParsePlatform/following{/other_user}","gists_url":"https://api.github.com/users/ParsePlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/ParsePlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ParsePlatform/subscriptions","organizations_url":"https://api.github.com/users/ParsePlatform/orgs","repos_url":"https://api.github.com/users/ParsePlatform/repos","events_url":"https://api.github.com/users/ParsePlatform/events{/privacy}","received_events_url":"https://api.github.com/users/ParsePlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":50603846,"name":"parse-server","full_name":"ParsePlatform/parse-server","owner":{"login":"ParsePlatform","id":1294580,"avatar_url":"https://avatars.githubusercontent.com/u/1294580?v=3","gravatar_id":"","url":"https://api.github.com/users/ParsePlatform","html_url":"https://github.com/ParsePlatform","followers_url":"https://api.github.com/users/ParsePlatform/followers","following_url":"https://api.github.com/users/ParsePlatform/following{/other_user}","gists_url":"https://api.github.com/users/ParsePlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/ParsePlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ParsePlatform/subscriptions","organizations_url":"https://api.github.com/users/ParsePlatform/orgs","repos_url":"https://api.github.com/users/ParsePlatform/repos","events_url":"https://api.github.com/users/ParsePlatform/events{/privacy}","received_events_url":"https://api.github.com/users/ParsePlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ParsePlatform/parse-server","description":"Parse-compatible API server module for Node/Express","fork":false,"url":"https://api.github.com/repos/ParsePlatform/parse-server","forks_url":"https://api.github.com/repos/ParsePlatform/parse-server/forks","keys_url":"https://api.github.com/repos/ParsePlatform/parse-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ParsePlatform/parse-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ParsePlatform/parse-server/teams","hooks_url":"https://api.github.com/repos/ParsePlatform/parse-server/hooks","issue_events_url":"https://api.github.com/repos/ParsePlatform/parse-server/issues/events{/number}","events_url":"https://api.github.com/repos/ParsePlatform/parse-server/events","assignees_url":"https://api.github.com/repos/ParsePlatform/parse-server/assignees{/user}","branches_url":"https://api.github.com/repos/ParsePlatform/parse-server/branches{/branch}","tags_url":"https://api.github.com/repos/ParsePlatform/parse-server/tags","blobs_url":"https://api.github.com/repos/ParsePlatform/parse-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ParsePlatform/parse-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ParsePlatform/parse-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/ParsePlatform/parse-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ParsePlatform/parse-server/statuses/{sha}","languages_url":"https://api.github.com/repos/ParsePlatform/parse-server/languages","stargazers_url":"https://api.github.com/repos/ParsePlatform/parse-server/stargazers","contributors_url":"https://api.github.com/repos/ParsePlatform/parse-server/contributors","subscribers_url":"https://api.github.com/repos/ParsePlatform/parse-server/subscribers","subscription_url":"https://api.github.com/repos/ParsePlatform/parse-server/subscription","commits_url":"https://api.github.com/repos/ParsePlatform/parse-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/ParsePlatform/parse-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/ParsePlatform/parse-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/ParsePlatform/parse-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/ParsePlatform/parse-server/contents/{+path}","compare_url":"https://api.github.com/repos/ParsePlatform/parse-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ParsePlatform/parse-server/merges","archive_url":"https://api.github.com/repos/ParsePlatform/parse-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ParsePlatform/parse-server/downloads","issues_url":"https://api.github.com/repos/ParsePlatform/parse-server/issues{/number}","pulls_url":"https://api.github.com/repos/ParsePlatform/parse-server/pulls{/number}","milestones_url":"https://api.github.com/repos/ParsePlatform/parse-server/milestones{/number}","notifications_url":"https://api.github.com/repos/ParsePlatform/parse-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ParsePlatform/parse-server/labels{/name}","releases_url":"https://api.github.com/repos/ParsePlatform/parse-server/releases{/id}","deployments_url":"https://api.github.com/repos/ParsePlatform/parse-server/deployments","created_at":"2016-01-28T18:29:14Z","updated_at":"2016-04-20T19:02:23Z","pushed_at":"2016-04-20T19:15:46Z","git_url":"git://github.com/ParsePlatform/parse-server.git","ssh_url":"git@github.com:ParsePlatform/parse-server.git","clone_url":"https://github.com/ParsePlatform/parse-server.git","svn_url":"https://github.com/ParsePlatform/parse-server","homepage":null,"size":3218,"stargazers_count":8496,"watchers_count":8496,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2050,"mirror_url":null,"open_issues_count":69,"forks":2050,"open_issues":69,"watchers":8496,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569"},"html":{"href":"https://github.com/ParsePlatform/parse-server/pull/1569"},"issue":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/issues/1569"},"comments":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/issues/1569/comments"},"review_comments":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569/comments"},"review_comment":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/pulls/1569/commits"},"statuses":{"href":"https://api.github.com/repos/ParsePlatform/parse-server/statuses/740187a63c9ea446ba141a3e5942bd4d36eea89b"}}}}