-
Notifications
You must be signed in to change notification settings - Fork 12
Adstream.data backend node
Called once during instantiation of the service endpoint (i.e. adstream_data()
). Establishes the routing to the individual handlers by calling methods get()
, update()
, create()
and del()
on its argument. At this time, only get()
is implemented:
arg
.get(
rel\_url, handler, depth)
- Associates user-defined method handler with
get
operation on the schema object determined by the pattern in rel\_url, or - Marks the schema object pointed to by rel\_url as not supporting the
get
operation (if handler is omitted).
HTTP GETs are processed by recursively collecting and calling the user-supplied get
handlers, starting at the URL the GET request was directed to. The order in which the handlers are executed depends on the URL patterns passed into get()
which are described below. If a schema object is marked as not supporting get
, the process stops at it — its descendants may still be accessed by GETs directed to their respective URLs.
The third, optional, argument depth may be used to indicate that the handler will be supplying not just the schema object it is associated with but also depth layers of its descendants. In this case, get
handlers associated with those descendant objects will not be invoked and the recursive process will resume below them in the hierarchy.
The URL patterns should always contain substitution placeholders in positions corresponding to the IDs of items within containers. There are two types of substitution placeholders:
- Fixed: “
:
placeholder\_name” - Variable: “
\*
” (forget
anddel
handlers) or “\*
placeholder_name” (forcreate
andupdate
handlers).
Fixed placeholders are bound to specific values once per a call to handler. They are passed into the handler as named properties of its key argument. The handler may be called multiple times in the course of processing a single request with fixed placeholders bound to different values.
Variable placeholders are used to imply the values that will be filled in by the handler and/or to allow the handler to process the corresponding objects from the request body in one batch.
Fixed placeholders must precede any variable placeholders in any URL pattern. The sequence of fixed placeholders in a URL pattern constitutes its fixed prefix which determines the order in which the handlers are executed:
All handlers with fixed prefixes of identical length execute in parallel (i.e. they are activated together in unspecified order and the process does not continue until all of them complete). Groups of handlers with identical fixed prefix length execute in the order of their lengths: earlier handlers are expected to populate the response
object with sufficient data so that longer fixed prefixes can be bound using the corresponding IDs from the response.
All handlers receive an object of this type as their first argument. Conceptually, the key corresponds to the URL pattern associated with the handler with its fixed placeholders already bound. The values of the fixed placeholders are available as named properties on the key object.
key.url(
args…)
This method binds zero or more of the variable placeholders in the pattern and returns the resulting URL. If the number of arguments passed into the call is fewer than the number of the variable placeholders, the URL is cut off at the first non-bound placeholders. Note that fixed placeholders are pre-bound and should not be supplied as arguments for the url()
call.
All handlers other than get
receive an object of this type — or an array of such objects, if they have at least one variable placeholder in their URL pattern — as their second argument. An item
object encapsulates the values of the variable placeholders — available as its named properties — along with the corresponding object from the request body and its exact URL.
item.url(
args…)
Returns URL of the object from the request body held by item
. As in key.url()
, arguments can be used to bind variable placeholders in the URL pattern. The difference is that in item
they are pre-bound to begin with and supplying arguments to this method re-binds last N placeholders leaving others alone. This is normally used to replace temporary IDs in create
handlers with the real ones.
item.data()
Returns the object from the request body held by item
.
Returns a shallow copy of the object from the request body that will not include any known children, only the properties. The metadata property (\_
) is also shallow-copied. If the item has temporary ID (@
<<_ID_>>), the replaces
metadata property is automatically injected into the copy.
The constructor function passed into the call to adstream_data()
is used to create context objects for every HTTP request being processed. Two properties, request
and response
are automatically injected into the context objects after construction. All handler methods installed by App.configure()
will be executed with this
pointing to the appropriate context object.
All handler functions are called in the scope of the context object and can access this.request
and this.response
. A handler may return a non-promise value (which is ignored; using false
as result is suggested) if it completes synchronously or a promise if it requires asynchronous processing.
get\_
XXX: function(
key)
add\_
XXX: function(
key, items)
The second argument is an array of item
objects: the create
handlers should always have at least one (usually exactly one) variable placeholder in the URL pattern.
The important thing about create
handlers is the processing of the temporary item IDs (@
<<_ID_>>) from the request. There will never be any temporary IDs in the key URL. Item URLs (and placeholders) will contain at least one temporary ID: the last of the variable placeholders. After the handler completes, all replaces
metadata properties of the objects it inserts into the response body are automatically collected to map temporary IDs that’s been bound for other create
handlers lower in the tree.
del\_
XXX: function(
key, item\or\items)
The second argument is either an item
object or an array of such objects, depending on the presence of variable placeholders in the pattern. The value returned by item.data()
could be null
if the request does not specify version, or an empty object with the following metadata (_
property) structure:
{code}{
delete: true,
version: SomeValue
}
{code}
Note that del
handlers are not collected from the tree recursively: only the handler at the URL designated in the request gets executed and not the handlers below it.
An object that can be used to access the query string arguments from the URL as well as the request body.
this.request.get(
rel\_url, metadata)
Returns the object at rel\_url from the request body (or undefined
). If the metadata prototype is supplied, the object will be created if not already present and its _
property filled in with the combination of properties already present in the request body, query string arguments and the default values supplied in the prototype.
The metadata prototype is a one-to-two level dictionary corresponding to the adstream.data
metadata structure. The properties with string, numeric, boolean or null
values are considered leaves and are matched against the dictionary of arguments from the query string as follows:
-
null
property in the prototype: matching query string argument is removed from the set and added as a string metadata property. If there’s no matching argument, nothing is added to metadata; - String property in the prototype: matching query string argument is removed from the set and added as a string metadata property. If there’s no matching argument, the value from the prototype is added to metadata;
- Numeric property: matching query string argument is removed from the set and added as a numeric metadata property (non-numeric values cause an exception). If there’s no matching argument, the value from the prototype is added to metadata unless it is equal to
NaN
, in which case nothing happens; - Boolean property: matching query string argument is added as
false
if it is empty or equal to"0"
,"false"
,"n"
or"no"
(character case ignored), otherwise astrue
. If there’s no matching argument, the value from the prototype is added to metadata.
Note that if any metadata are successfully collected from the query string or the template, get()
will always create the requested object within request
and return it.
this.request.arg(
name)
Removes specified argument from the query string and returns it; returns null
if argument is not present. It is preferable to use metadata collection mechanism in get()
instead in most cases.
An object that can be used to build the response body as well as signal errors.
this.response.set(
rel\_url, value, metadata)
Mixes in all properties from value into the response object at rel\_url, creating one if necessary. If metadata is passed in, also mixes in its content into the _
property of the object. Note that if you pass in the metadata as part of value_, it will overwrite the current content of @, if any, without mixing it. Method @set()
returns the resulting response object so it can be directly modified by the user code if necessary.
this.response.fail(
http\code, message, http\headers)
bq.this.response.fail(
promise, http\code, message, http\headers)
Terminates the handler by throwing an exception (first form) or signaling an error via the promise object (second form); passes the resulting HTTP status code, descriptive message and (optionally) a dictionary of HTTP headers to be returned as part of response.