W3C

TIBET URIs

wins

  • Leverage W3C standards to refer to local and remote resources.
  • Read/write data using a wide variety of standardized path languages.
  • Locally bind, cache, snapshot, rollback, refresh, or sync with ease.
  • Customize handling of different resources by location or MIME.
  • Reduce conceptual complexity by using well-known URI semantics.

concepts

Introduction

The TP.uri.URI type and its subtypes are central to development with TIBET.

Everything in TIBET can be referenced via a URI, from the data you work with on a remote server to the data cached in the client to the elements in your UI. Access to these objects is provided by leveraging the features of the TP.uri.URI type and its subtypes.

In TIBET a URI instance isn't just a parsed string, it's a fully-featured object you can configure with respect to caching, updating, undo/redo, and a number of other "data management" features. You can configure based on patterns or configure individual URIs to meet your requirements.

URIs, thanks to TIBET's support for XPointer, also provide the foundation for querying into your data using powerful query languages including JSONPath, XPath, and TIBET paths.

When you query a TIBET URL you will automatically receive back an instance of one of TIBET's Content Types specific to the data being accessed. These content types let you manage your data in an encapsulated fashion, ensuring you don't have hard-coded paths throughout your code and allowing you to write whatever function methods your data might require.

Thanks to the combination of URI-based data management, custom content types, and powerful query and slicing syntax you can use Data Binding to bind data with little or no code.

Best of all, most of your work with URIs happens transparently, you just need to be familiar with the syntax of URLs, URNs, and query paths to use TIBET's data features.

TIBET URIs

A URI, or uniform resource identifier, is the top-most concept the W3 standard defines with respect to resource identification.

In TIBET, the TP.uri.URI type represents a top-level URI and is actually what TIBET calls an abstract type in that you can't create a concrete instance of that type, you can only create instances of non-abstract subtypes of TP.uri.URI (or any abstract type for that matter).

The primary subtypes of TP.uri.URI are TP.uri.URL and TP.uri.URN, which represent uniform resource locators and uniform resource names respectively.

TIBET's URI construct call and its shortcut TP.uc are implemented such that you never need to worry about using a specific constructor for a subtype, you can invoke TP.uri.URI.construct or TP.uc and you will receive the proper concrete subtype instance in return:

//  Returns the proper subtype based on load scheme and URI text.
url = TP.uc('~/tibet.json');

In the example above if you're running over HTTP you'll get back a TP.uri.HTTPURL instance. If, however, you were running off the file system you would receive an instance of TP.uri.FileURL. TIBET automatically adjusts the subtype based on load context and the URI text itself.

As mentioned earlier, often you don't need to interact with TP.uri.URI or its subtypes directly. You mention them in your application markup and TIBET automatically manages the data for you.

In the 'hello world!' example below we:

  • fetch the content of /tibet.json (via an unseen TP.uri.HTTPURL).
  • assign it to a TP.uri.TIBETURN with the name urn:tibet:tibet_json.
  • query it via a JSONPath built from $.project + name to get 'hello'.

<hello:app id="app">

<tibet:service href="/tibet.json" id="urn:tibet:tibet_json"
    on:attach="UIActivate"/>

<div bind:scope="urn:tibet:tibet_json">
    <div bind:scope="$.project">
        <xctrls:button on:click="ClickMe">
        <xctrls:label>[[name]] world!</xctrls:label>
        <xctrls:hint>Click me ;)</xctrls:hint>
        </xctrls:button>
    </div>
</div>

</hello:app>

Accessing data, naming it for easy reference, and querying it, all without a single line of JavaScript or any direct interaction with a TP.uri.URI instance.

TIBET URLs

TP.uri.URL is the root for most common URIs including those for the http: and file: schemes most web developers are familiar with.

Most of the time when you're working with a data source you're working with an instance of some concrete TP.uri.URL subtype such as TP.uri.HTTPURL or TP.uri.FileURL.

To get a sense of functionality for a TP.uri.HTTPURL let's look at the output of the tibet reflect command line tool for that type:

$ tibet reflect TP.uri.HTTPURL
# Loading TIBET platform at 2019-07-23T02:13:48.635Z
# TIBET reflection suite loaded and active in 7394ms

# Type: TP.uri.HTTPURL
# Supertypes: TP.uri.URL TP.uri.URI TP.lang.Object TP.lang.RootObject Object

# TP.uri.HTTPURL
TP.uri.HTTPURL.Inst
TP.uri.HTTPURL.Type
TP.uri.HTTPURL.localName
TP.uri.HTTPURL.nsPrefix
TP.uri.HTTPURL.nsRoot

# TP.uri.HTTPURL.Type
TP.uri.HTTPURL.Type.SCHEME
TP.uri.HTTPURL.Type.mode
TP.uri.HTTPURL.Type.supportedModes

# TP.uri.HTTPURL.Inst
TP.uri.HTTPURL.Inst.commObject
TP.uri.HTTPURL.Inst.getCommObject
TP.uri.HTTPURL.Inst.getCommStatusCode
TP.uri.HTTPURL.Inst.getCommStatusText
TP.uri.HTTPURL.Inst.hostname
TP.uri.HTTPURL.Inst.httpConnect
TP.uri.HTTPURL.Inst.httpDelete
TP.uri.HTTPURL.Inst.httpGet
TP.uri.HTTPURL.Inst.httpHead
TP.uri.HTTPURL.Inst.httpOptions
TP.uri.HTTPURL.Inst.httpPatch
TP.uri.HTTPURL.Inst.httpPost
TP.uri.HTTPURL.Inst.httpPut
TP.uri.HTTPURL.Inst.httpTrace
TP.uri.HTTPURL.Inst.location
TP.uri.HTTPURL.Inst.password
TP.uri.HTTPURL.Inst.port
TP.uri.HTTPURL.Inst.query
TP.uri.HTTPURL.Inst.queryDict
TP.uri.HTTPURL.Inst.user

./public/TIBET-INF/tibet/src/tibet/kernel/TIBETURITypes.js

As the tibet reflect output shows the HTTPURL type has methods supporting each of the HTTP verbs as well as a few other utility functions. It also inherits a significant amount of functionality from TP.uri.URI which is not shown above.

TIBET URNs

TP.uri.URN (urn:*) is the typical URI type for "named objects" such as types in the TIBET system or other objects for which a public name is needed. Most URNs in TIBET use a namespace ID (NID) of tibet so most URN instances start off with urn:tibet: followed by the actual name string. Instances of TP.uri.URN are typically instances of an NID-specific subtype so that each subtype can process the namespace specific string (NSS) portion in a namespace-specific fashion. TP.uri.TIBETURN is the most common TP.uri.URN subtype.

TP.uri.TIBETURN (urn:tibet:*) is a TIBET-specific URL type which provides extensions to the general URI addressing model. In particular, TIBET URLs allow for dynamic resolution and targeting of objects in "browser space". TIBET URLs will be created when a virtual URI path is specified (i.e. one that uses a leading ~ prefix to create paths such as ~lib/ or ~app/ which refer to "the TIBET library root" and "the current application root" respectively.

TIBET URNs serve a particularly powerful role in TIBET development since they make it easy to name any piece of data and get a handle back to it using that name from anywhere in TIBET. (TIBET URIs are uniqued. Any reference to the same path returns the same instance).

Any time you alter the data in an TIBET URN it signals that change to any observers. The result is that TIBET URNs work like "value holders" which are an essential element of building true MVC and MVVC front-ends. This is clearly visible when binding to a shared URN.

URI Caching

TIBET's URI types each have the ability to manage a cache for their data so that bandwidth can be managed efficiently. The focal point for caching is the URI instance itself, which also manages header and content data for all access to that instance's target resource. URI caching for things like client-side templates and common lookup code tables is a typical use case.

URI "Xtensions"

URI-related standards like XInclude and XPointer are also supported by the appropriate URI subtypes. These standards provide additional ways to help you modularize your application for better maintainability and performance. By leveraging XPointer for example, you can slice content from template files or access portions of a REST response with ease. The TIBET Paths documentation shows how to leverage XPointers to query into your TIBET URI data.

Virtual URIs

Note that the underlying 'URI primitives' capability of TIBET, in addition to standard URI 'slicing and dicing' operations, also support what are known as "virtual URIs".

Virtual URIs are URIs that have a leading tilde ('~') prefix and that resolve to a value at run time using the built in configuration system. For instance, a path of ~lib_xsl' will use the value in the configuration system named path.lib_xsl`. There are a number of shortcuts that can be used with virtual URIs:

~/      The application root
~app    The application root
~lib    The TIBET library root

See the reference section for a full list of paths at the time of this writing.

cookbook

Create A URI Instance

To create a URI instance use TP.uc or TP.uri.URI.construct:

url = TP.uc('~/tibet.json');

// or

url = TP.uri.URI.construct('~/tibet.json');

Create A URN Instance

To create a URN instance use TP.uc or TP.uri.URI.construct:

url = TP.uc('urn:tibet:foo');

// or

url = TP.uri.URI.construct('urn:tibet:foo');

Assign Data To A URN

For a URN instance the easiest thing to do is assign the data when you create the instance. (You can actually do this with any URI instance).

For example, we can set the data of urn:tibet:foo to 123 as follows:

urn = TP.uc('urn:tibet:foo', 123);
urn.getContent();
123

Fetch URL Data

Use the uri instance's getContent method:

url = TP.uc('~/tibet.json');
content = url.getContent();     //  <- TP.core.JSONContent

Assign Data To A URL

Once you have a URI instance you can use setContent to put new content into it.

The one caveat here is that if you are passing "raw" content rather than a new Content instance the original Content instance will try to verify the new data is appropriate for that content type.

In the example below since the URLs content is initially a JSONContent instance we need to set the content to a valid JSON string:

url = TP.uc('~/tibet.json');
url.setContent('{ "this": "is JSON content" }');
url.getContent();               //  <- TP.core.JSONContent
{
    "this": "is JSON content"
}

To set a completely different type of data we need to construct a new content instance and pass that instead:

url = TP.uc('~/tibet.json');
content = TP.core.TextContent.construct('any darn string');
url.setContent(content);
url.getContent();               // <- TP.core.TextContent
'any darn string'

Refresh URL Content

Let's assume in the previous example we made a mistake and want to reset the URL's content to it's original state (or at least the state on the server). We can do that by passing a "request" (or TP.core.Hash) with refresh set to true:

url = TP.uc('~/tibet.json');
url.getContent(TP.hc('refresh', true));     // <- TP.core.JSONContent

reference

NOTE: the information here is static. Use the commands utilized to produce each list below to get current reflection data from your specific version of TIBET.

TP.uri.URI Methods

TP.uri.URI has an extensive API. The most common methods used at this level are getContent and setContent which fetch and set the content of the target resource.

Below we target the instance methods via tibet reflect:

$ tibet reflect TP.uri.URI.Inst --methods
# Loading TIBET platform at 2019-07-23T02:22:20.755Z
# TIBET reflection suite loaded and active in 6133ms

# Prototype
TP.uri.URI.Inst.addResource
TP.uri.URI.Inst.asDumpString
TP.uri.URI.Inst.asHTMLString
TP.uri.URI.Inst.asJSONSource
TP.uri.URI.Inst.asPrettyString
TP.uri.URI.Inst.asSource
TP.uri.URI.Inst.asString
TP.uri.URI.Inst.asTP_uri.URI
TP.uri.URI.Inst.asXMLString
TP.uri.URI.Inst.canReuseContentForInspector
TP.uri.URI.Inst.clearCaches
TP.uri.URI.Inst.constructRequest
TP.uri.URI.Inst.constructSubrequest
TP.uri.URI.Inst.empty
TP.uri.URI.Inst.equalTo
TP.uri.URI.Inst.expire
TP.uri.URI.Inst.getChildTypeForCanvas
TP.uri.URI.Inst.getConcreteURI
TP.uri.URI.Inst.getConfigForInspector
TP.uri.URI.Inst.getContent
TP.uri.URI.Inst.getContentForInspector
TP.uri.URI.Inst.getContentForToolbar
TP.uri.URI.Inst.getDataForInspector
TP.uri.URI.Inst.getEntryAt
TP.uri.URI.Inst.getEntryLabel
TP.uri.URI.Inst.getFragment
TP.uri.URI.Inst.getFragmentAccessPath
TP.uri.URI.Inst.getFragmentAccessPathType
TP.uri.URI.Inst.getFragmentExpr
TP.uri.URI.Inst.getFragmentParameters
TP.uri.URI.Inst.getFragmentPath
TP.uri.URI.Inst.getFragmentWeight
TP.uri.URI.Inst.getHeader
TP.uri.URI.Inst.getID
TP.uri.URI.Inst.getLastUpdateDate
TP.uri.URI.Inst.getLocalPath
TP.uri.URI.Inst.getLocation
TP.uri.URI.Inst.getName
TP.uri.URI.Inst.getNativeObject
TP.uri.URI.Inst.getOriginalSource
TP.uri.URI.Inst.getPathPartsForInspector
TP.uri.URI.Inst.getPrimaryLocation
TP.uri.URI.Inst.getPrimaryURI
TP.uri.URI.Inst.getResource
TP.uri.URI.Inst.getRoot
TP.uri.URI.Inst.getRootAndPath
TP.uri.URI.Inst.getScheme
TP.uri.URI.Inst.getSecondaryURIs
TP.uri.URI.Inst.getSize
TP.uri.URI.Inst.getSubURIs
TP.uri.URI.Inst.getSuperURIWithResourceType
TP.uri.URI.Inst.getURI
TP.uri.URI.Inst.getValue
TP.uri.URI.Inst.getVirtualLocation
TP.uri.URI.Inst.getWebPath
TP.uri.URI.Inst.handleChangeFromANYWhenANY
TP.uri.URI.Inst.hasFragment
TP.uri.URI.Inst.init
TP.uri.URI.Inst.isDirty
TP.uri.URI.Inst.isExpired
TP.uri.URI.Inst.isHTTPBased
TP.uri.URI.Inst.isLoaded
TP.uri.URI.Inst.isPrimaryURI
TP.uri.URI.Inst.refreshFromRemoteResource
TP.uri.URI.Inst.register
TP.uri.URI.Inst.remap
TP.uri.URI.Inst.resourcesAreAlike
TP.uri.URI.Inst.rewrite
TP.uri.URI.Inst.rewriteRequestMode
TP.uri.URI.Inst.setContent
TP.uri.URI.Inst.setLastUpdateDate
TP.uri.URI.Inst.setResource
TP.uri.URI.Inst.setResourceToResultOf
TP.uri.URI.Inst.setValue
TP.uri.URI.Inst.shouldSignalChange
TP.uri.URI.Inst.stubResourceContent
TP.uri.URI.Inst.transform
TP.uri.URI.Inst.unregister
TP.uri.URI.Inst.updateHeaders

./public/TIBET-INF/tibet/src/tibet/kernel/TIBETURITypes.js

Copy and paste a line from the output above onto tibet reflect to view its comment.

Here we look at the comment for the getContent method:

$ tibet reflect TP.uri.URI.Inst.getContent
# Loading TIBET platform at 2019-07-23T02:25:16.428Z
# TIBET reflection suite loaded and active in 6057ms

TP.uri.URI.Inst.getContent

function getContent(aRequest)

/**
 * @method getContent
 * @summary Returns the URI's resource, forcing any fetch to be synchronous.
 *     If you need async access use getResource.
 * @returns {Object} The immediate value of the receiver's resource result.
 */

./public/TIBET-INF/tibet/src/tibet/kernel/TIBETURITypes.js

Note all tibet reflect output includes the source file used for the data.

List Virtual URI Paths

The full list of virtual URIs is effectively found via the tibet config path command:

"~": "/Users/ss/temporary/hello",
"~app": "~/public",
"~lib": "/Users/ss/temporary/hello/node_modules/tibet",
"path.app": "~app_root",
"path.app_bin": "~app/bin",
"path.app_boot": "~app_inf/boot",
"path.app_build": "~app/build",
"path.app_cache": "~app_tmp/cache",
"path.app_cfg": "~app_inf/cfg",
"path.app_change": "~app_src/changes",
"path.app_cmd": "~/cmd",
"path.app_dat": "~app_inf/dat",
"path.app_deps": "~app/deps",
"path.app_dna": "~app_inf/dna",
"path.app_etc": "~app/etc",
"path.app_fonts": "~app/fonts",
"path.app_inf": "~app/TIBET-INF",
"path.app_keyrings": "~app_dat/keyrings.xml",
"path.app_lib": "~app/lib",
"path.app_log": "~/logs",
"path.app_media": "~app/media",
"path.app_npm": "~/node_modules",
"path.app_schema": "~app/schema",
"path.app_src": "~app/src",
"path.app_styles": "~app/styles",
"path.app_tags": "~app_src/tags",
"path.app_test": "~app/test",
"path.app_tmp": "~app_inf/tmp",
"path.app_tsh": "~app_inf/tsh",
"path.app_vcards": "~app_dat/vcards.xml",
"path.app_xhtml": "~app/xhtml",
"path.app_xml": "~app_inf/xml",
"path.app_xmlbase": "~app_xhtml",
"path.app_xsl": "~app_inf/xsl",
"path.blank_page": "~lib_xhtml/blank.xhtml",
"path.boot_fonts": "~app_boot/fonts",
"path.boot_media": "~app_boot/media",
"path.boot_styles": "~app_boot/styles",
"path.boot_xhtml": "~app_boot/xhtml",
"path.couchapp": "~/couch/tws",
"path.ide_root": "~lib_src/tibet/tools/sherpa",
"path.ide_src": "~ide_root/src",
"path.iframe_page": "~app_boot/xhtml/blank.xhtml",
"path.lib": "~lib_root",
"path.lib_bin": "~lib/bin",
"path.lib_boot": "~tibet_src/boot",
"path.lib_build": "~lib_lib/src",
"path.lib_cfg": "~lib_lib/cfg",
"path.lib_cmd": "~lib/cmd",
"path.lib_dat": "~lib_lib/dat",
"path.lib_demo": "~lib/demo",
"path.lib_deps": "~lib/deps",
"path.lib_dna": "~lib/dna",
"path.lib_etc": "~lib/etc",
"path.lib_fonts": "~lib_lib/fonts",
"path.lib_inf": "~lib/TIBET-INF",
"path.lib_keyrings": "~lib_dat/keyrings.xml",
"path.lib_lib": "~lib/lib",
"path.lib_media": "~lib_lib/media",
"path.lib_npm": "~lib/node_modules",
"path.lib_schema": "~lib_lib/schema",
"path.lib_src": "~lib/src",
"path.lib_styles": "~lib_lib/styles",
"path.lib_test": "~lib/test",
"path.lib_tsh": "~lib_lib/tsh",
"path.lib_vcards": "~lib_dat/vcards.xml",
"path.lib_version_latest": "http://www.technicalpursuit.com/tibet/latest.js",
"path.lib_xhtml": "~lib_lib/xhtml",
"path.lib_xml": "~lib_lib/xml",
"path.lib_xsl": "~lib_lib/xsl",
"path.npm_dir": "node_modules",
"path.npm_file": "package.json",
"path.release_version_target": "~lib/src/tibet/kernel/TIBETVersion.js",
"path.release_version_template": "~lib/src/tibet/kernel/TIBETVersionTemplate.js",
"path.sherpa_screen_0": "~boot_xhtml/home.xhtml",
"path.tds_couch_defs": "~/couch/app",
"path.tds_file": "~/tds.json",
"path.tds_plugins": "~/plugins",
"path.tds_processors": "~tds_plugins/processors",
"path.tds_task_defs": "~/couch/tws",
"path.tds_tasks": "~tds_plugins/tasks",
"path.tds_templates": "~tds_tasks/templates",
"path.tibet": "~lib_root",
"path.tibet_file": "~app/tibet.json",
"path.tibet_inf": "TIBET-INF",
"path.tibet_lib": "tibet",
"path.tibet_src": "~lib_src/tibet",
"path.tws": "~/couch/tws",
"path.uiboot_page": "~app_boot/xhtml/UIBOOT.xhtml",
"path.uiroot_page": "~app_boot/xhtml/UIROOT.xhtml",
"path.user_file": "~/users.json",
"path.xctrls_src": "~lib_src/xctrls",
"path.xpath_parser": "~lib_deps/xpath-tpi.js",
"path.xslt_boilerplate": "~lib_src/tsh/xsl/tsh_template_template.xsl"

code

The OO layer implementation for the core URI types is found in:

~lib/src/tibet/kernel/TIBETURITypes.js

Primitives specific to working with URIs can be found in:

  • ~lib/src/tibet/kernel/TIBETURIPrimitivesPre.js
  • ~lib/src/tibet/kernel/TIBETURIPrimitivesBase.js
  • ~lib/src/tibet/kernel/TIBETURIPrimitivesPlatform.js
  • ~lib/src/tibet/kernel/TIBETURIPrimitivesPost.js

See TIBET Content Types for content-related code references.