179 lines
5.8 KiB
GDScript
179 lines
5.8 KiB
GDScript
## @meta-authors TODO
|
|
## @meta-authors TODO
|
|
## @meta-version 2.3
|
|
## A reference to a Firestore Collection.
|
|
## Documentation TODO.
|
|
@tool
|
|
class_name FirestoreCollection
|
|
extends Node
|
|
|
|
signal error(error_result)
|
|
|
|
const _AUTHORIZATION_HEADER : String = "Authorization: Bearer "
|
|
|
|
const _separator : String = "/"
|
|
const _query_tag : String = "?"
|
|
const _documentId_tag : String = "documentId="
|
|
|
|
var auth : Dictionary
|
|
var collection_name : String
|
|
|
|
var _base_url : String
|
|
var _extended_url : String
|
|
var _config : Dictionary
|
|
|
|
var _documents := {}
|
|
|
|
# ----------------------- Requests
|
|
|
|
## @args document_id
|
|
## @return FirestoreTask
|
|
## used to GET a document from the collection, specify @document_id
|
|
func get_doc(document_id : String, from_cache : bool = false, is_listener : bool = false) -> FirestoreDocument:
|
|
if from_cache:
|
|
# for now, just return the child directly; in the future, make it smarter so there's a default, if long, polling time for this
|
|
for child in get_children():
|
|
if child.doc_name == document_id:
|
|
return child
|
|
|
|
var task : FirestoreTask = FirestoreTask.new()
|
|
task.action = FirestoreTask.Task.TASK_GET
|
|
task.data = collection_name + "/" + document_id
|
|
var url = _get_request_url() + _separator + document_id.replace(" ", "%20")
|
|
|
|
_process_request(task, document_id, url)
|
|
var result = await Firebase.Firestore._handle_task_finished(task)
|
|
if result != null:
|
|
for child in get_children():
|
|
if child.doc_name == document_id:
|
|
child.replace(result, true)
|
|
result = child
|
|
break
|
|
else:
|
|
print("get_document returned null for %s %s" % [collection_name, document_id])
|
|
|
|
return result
|
|
|
|
## @args document_id, fields
|
|
## @arg-defaults , {}
|
|
## @return FirestoreDocument
|
|
## used to ADD a new document to the collection, specify @documentID and @data
|
|
func add(document_id : String, data : Dictionary = {}) -> FirestoreDocument:
|
|
var task : FirestoreTask = FirestoreTask.new()
|
|
task.action = FirestoreTask.Task.TASK_POST
|
|
task.data = collection_name + "/" + document_id
|
|
var url = _get_request_url() + _query_tag + _documentId_tag + document_id
|
|
|
|
_process_request(task, document_id, url, JSON.stringify(Utilities.dict2fields(data)))
|
|
var result = await Firebase.Firestore._handle_task_finished(task)
|
|
if result != null:
|
|
for child in get_children():
|
|
if child.doc_name == document_id:
|
|
child.free() # Consider throwing an error for this since it shouldn't already exist
|
|
break
|
|
|
|
result.collection_name = collection_name
|
|
add_child(result, true)
|
|
return result
|
|
|
|
## @args document
|
|
## @return FirestoreDocument
|
|
# used to UPDATE a document, specify the document
|
|
func update(document : FirestoreDocument) -> FirestoreDocument:
|
|
var task : FirestoreTask = FirestoreTask.new()
|
|
task.action = FirestoreTask.Task.TASK_PATCH
|
|
task.data = collection_name + "/" + document.doc_name
|
|
var url = _get_request_url() + _separator + document.doc_name.replace(" ", "%20") + "?"
|
|
for key in document.keys():
|
|
url+="updateMask.fieldPaths={key}&".format({key = key})
|
|
|
|
url = url.rstrip("&")
|
|
|
|
for key in document.keys():
|
|
if document.get_value(key) == null:
|
|
document._erase(key)
|
|
|
|
var temp_transforms
|
|
if document._transforms != null:
|
|
temp_transforms = document._transforms
|
|
document._transforms = null
|
|
|
|
var body = JSON.stringify({"fields": document.document})
|
|
|
|
_process_request(task, document.doc_name, url, body)
|
|
var result = await Firebase.Firestore._handle_task_finished(task)
|
|
if result != null:
|
|
for child in get_children():
|
|
if child.doc_name == result.doc_name:
|
|
child.replace(result, true)
|
|
break
|
|
|
|
if temp_transforms != null:
|
|
result._transforms = temp_transforms
|
|
|
|
return result
|
|
|
|
|
|
## @args document
|
|
## @return Dictionary
|
|
# Used to commit changes from transforms, specify the document with the transforms
|
|
func commit(document : FirestoreDocument) -> Dictionary:
|
|
var task : FirestoreTask = FirestoreTask.new()
|
|
task.action = FirestoreTask.Task.TASK_COMMIT
|
|
var url = get_database_url("commit")
|
|
|
|
document._transforms.set_config(
|
|
{
|
|
"extended_url": _extended_url,
|
|
"collection_name": collection_name
|
|
}
|
|
) # Only place we can set this is here, oofness
|
|
|
|
var body = document._transforms.serialize()
|
|
document.clear_field_transforms()
|
|
_process_request(task, document.doc_name, url, JSON.stringify(body))
|
|
|
|
return await Firebase.Firestore._handle_task_finished(task) # Not implementing the follow-up get here as user may have a listener that's already listening for changes, but user should call get if they don't
|
|
|
|
## @args document_id
|
|
## @return FirestoreTask
|
|
# used to DELETE a document, specify the document
|
|
func delete(document : FirestoreDocument) -> bool:
|
|
var doc_name = document.doc_name
|
|
var task : FirestoreTask = FirestoreTask.new()
|
|
task.action = FirestoreTask.Task.TASK_DELETE
|
|
task.data = document.collection_name + "/" + doc_name
|
|
var url = _get_request_url() + _separator + doc_name.replace(" ", "%20")
|
|
_process_request(task, doc_name, url)
|
|
var result = await Firebase.Firestore._handle_task_finished(task)
|
|
|
|
# Clean up the cache
|
|
if result:
|
|
for node in get_children():
|
|
if node.doc_name == doc_name:
|
|
node.free() # Should be only one
|
|
break
|
|
|
|
return result
|
|
|
|
func _get_request_url() -> String:
|
|
return _base_url + _extended_url + collection_name
|
|
|
|
func _process_request(task : FirestoreTask, document_id : String, url : String, fields := "") -> void:
|
|
if auth == null or auth.is_empty():
|
|
Firebase._print("Unauthenticated request issued...")
|
|
Firebase.Auth.login_anonymous()
|
|
var result : Array = await Firebase.Auth.auth_request
|
|
if result[0] != 1:
|
|
Firebase.Firestore._check_auth_error(result[0], result[1])
|
|
return
|
|
Firebase._print("Client authenticated as Anonymous User.")
|
|
|
|
task._url = url
|
|
task._fields = fields
|
|
task._headers = PackedStringArray([_AUTHORIZATION_HEADER + auth.idtoken])
|
|
Firebase.Firestore._pooled_request(task)
|
|
|
|
func get_database_url(append) -> String:
|
|
return _base_url + _extended_url.rstrip("/") + ":" + append
|