diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..b7f6101 --- /dev/null +++ b/public/index.html @@ -0,0 +1,1345 @@ + + + + + + Archivers API | API Reference + + + + + + + +
+ +
+ +
+
+
+

Archivers API + API Reference +

+
+
+

Api for Archivers records

+
+
+
+
API Endpoint
+
https://api.archivers.space/v0
+
Terms of Service: + https://archivers.space/terms/api +
+ +
Schemes: + https +
+
Version: + 0.0.1 +
+
+
+
+
+

Paths

+ +
+

+ + GET + /collections + +

+
+
+
+

List Collections

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped array of collections

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "array",
+  "meta": "object",
+  "pagination": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /collections/{id} + +

+
+
+
+

Get a Collection

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped Collection Object

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "object",
+  "meta": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /primers + +

+
+
+
+

List Primers

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped array of Primers

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "array",
+  "meta": "object",
+  "pagination": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /primers/{id} + +

+
+
+
+

Get a Primer

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

List

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "object",
+  "meta": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /sources + +

+
+
+
+

List Sources

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped Sources

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "object",
+  "meta": "object",
+  "pagination": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /sources/{id} + +

+
+
+
+

Get a Source

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped Source

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "object",
+  "meta": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /urls + +

+
+
+
+

List Urls

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped List of Urls

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "array",
+  "meta": "object",
+  "pagination": "object"
+}
+
+
+
+
+
+ +
+

+ + GET + /urls/{id} + +

+
+
+
+

Get a Url

+
+
+
+
+
+
+
+
+
+
+
+
+
200 OK
+
+ +
+
+

Enveloped Url

+
+
+
+
+
+
+
Response Example + (200 OK) +
+
{
+  "data": "object",
+  "meta": "object"
+}
+
+
+
+
+
+ +

Models

+
+

+ Collection: + + object + + +

+ +
+
+
+
+
+ id: + string + + +
+
+

version 4 uuid

+
+
+ created: + string + (date-time) + +
+
+

Created timestamp rounded to seconds in UTC

+
+
+ updated: + string + (date-time) + +
+
+

Updated timestamp rounded to seconds in UTC

+
+
+ creator: + string + +
+
+

sha356 multihash of the public key that created this collection

+
+
+ title: + string + +
+
+

human-readable title of the collection

+
+
+ schema: + array + +
+
+

csv column headers, first value must always be "hash"

+
+
+ contents: + array + +
+
+

actual collection contents

+
+
+
+
+
+
+ +
+

+ Metadata: + + object + + +

+ +
+
+
+
+
+ id: + string + (uuidv4) + + +
+
+ hash: + string + +
+
+

sha256 multihash of all other fields in metadata as expressed by Metadata.HashableBytes()

+
+
+ timestamp: + string + (date-time) + +
+
+

Creation timestamp

+
+
+ keyId: + string + +
+
+

Sha256 multihash of the public key that signed this metadata

+
+
+ subject: + string + +
+
+

Sha256 multihash of the content this metadata is describing

+
+
+ prev: + string + +
+
+

Hash value of the metadata that came before this, if any

+
+
+ meta: + object + +
+
+

Acutal stored metadata about the subject, can be any valid json Object

+
+
+
+
+
+
+
+

+ Primer: + + object + + +

+ +
+
+
+
+
+ id: + string + (uuidv4) + + +
+
+ created: + string + (date-time) + +
+
+

timestamp of first addition to the database rounded to seconds in UTC.

+
+
+ updated: + string + (date-time) + +
+
+

timestamp of most recent change rounded to seconds in UTC

+
+
+ shortTitle: + string + +
+
+

shortest possible expression of this primer's name, usually an acronym called shortTitle b/c acronyms collide often & users should feel free to expand on acronyms

+
+
+ title: + string + +
+
+

human-readable title of this primer.

+
+
+ description: + string + +
+
+

long-form description of this primer.

+
+
+ parent: + object + +
+
+

parent primer (if any)

+
+
+ subPrimers: + array + +
+
+

child-primers list

+
+
+ meta: + string + +
+
+

metadata to associate with this primer

+
+
+ stats: + string + +
+
+

statistics about this primer

+
+
+ sources: + string + +
+
+

collection of child sources

+
+
+
+
+
+
+
+

+ Snapshot: + + object + + +

+ +
+
+
+
+
+ url: + string + +
+
+

The url that was requested

+
+
+ created: + string + (date-time) + +
+
+

Time this request was issued

+
+
+ status: + integer + +
+
+

Returned Status

+
+
+ duration: + integer + +
+
+

Time to complete response in milliseconds

+
+
+ headers: + string + +
+
+

Record of all returned headers in [key,value,key,value...]

+
+
+ hash: + string + +
+
+

Multihash of response body (if any)

+
+
+
+
+
+
+
+

+ Source: + + object + + +

+ +
+
+
+

Source is a concreate handle for archiving. Crawlers use source's url as a base of a link tree. Sources are connected to a parent Primer to provide context & organization.

+
+
+
+
+ id: + string + (uuidv4) + + +
+
+ created: + string + (date-time) + +
+
+

timestamp of first addition to the database rounded to seconds in UTC.

+
+
+ updated: + string + (date-time) + +
+
+

timestamp of most recent change rounded to seconds in UTC

+
+
+ title: + string + +
+
+

human-readable title for this source

+
+
+ description: + string + +
+
+

description of the source, ideally one paragraph

+
+
+ url: + string + +
+
+

absolute url to serve as the root of the

+
+
+ primerId: + string + +
+
+

primer this source is connected to

+
+
+ crawl: + string + +
+
+

weather or not this url should be crawled be a web crawler

+
+
+ staleDuration: + string + +
+
+

amount of time before a link within this tree is considered in need of re-checking for changes. currently not in use, but planned.

+
+
+ lastAlertSent: + string + +
+
+

yeah this'll probably get depricated. Part of a half-baked alerts feature idea.

+
+
+ meta: + object + +
+
+

Metadata associated with this source that should be added to all child urls, currently not in use, but planned

+
+
+ stats: + object + +
+
+

Stats about this source

+
+
+
+
+
+
+
+

+ Url: + + object + + +

+ +
+
+
+
+
+ id: + string + (uuidv4) + + +
+
+ created: + string + (date-time) + +
+
+

timestamp of first addition to the database rounded to seconds in UTC.

+
+
+ updated: + string + (date-time) + +
+
+

timestamp of most recent change rounded to seconds in UTC

+
+
+ url: + string + +
+
+

URI string without any normalization. Url strings must always be absolute. unique to each entry

+
+
+ lastGet: + string + (date-time) + +
+
+

timestamp for most recent GET request

+
+
+ lastHead: + string + (date-time) + +
+
+

timestamp for most recent HEAD request

+
+
+ status: + integer + +
+
+

latest returned HTTP response status code

+
+
+ contentType: + string + +
+
+

latest returnd 'Content-Type' HTTP header

+
+
+ contentSniff: + string + +
+
+

Result of mime sniffing to GET response body, as detailed at + https://mimesniff.spec.whatwg.org +

+
+
+ contentLength: + integer + +
+
+ title: + string + +
+
+

HTML Title tag attribute

+
+
+ downloadTook: + integer + +
+
+

Time remote server took to transfer content in miliseconds.

+
+
+ headersTook: + integer + +
+
+

Time taken to in miliseconds. currently not implemented

+
+
+ headers: + string + +
+
+

key-value array of returned headers from most recent HEAD or GET request stored in the form [key,value,key,value...]

+
+
+ meta: + array + +
+
+

any associative metadata for this url

+
+
+ hash: + string + +
+
+

Hash is a multihash sha-256 of the response body of a GET request

+
+
+ contentUrl: + string + +
+
+

Url to saved content

+
+
+
+
+
+
+
+

+ User: + + object + + +

+ +
+
+
+
+
+ id: + string + (uuidv4) + + +
+
+ created: + string + (date-time) + +
+
+

timestamp of first addition to the database rounded to seconds in UTC.

+
+
+ updated: + string + (date-time) + +
+
+

timestamp of most recent change rounded to seconds in UTC

+
+
+ username: + string + +
+
+

handle for the user. min 1 character, max 80. composed of [_,-,a-z,A-Z,1-9]

+
+
+ type: + string + +
+
+

specifies weather this is a user or an organization

+
+
+ name: + string + +
+
+

user name field. could be first[space]last, but not strictly enforced

+
+
+ description: + string + +
+
+

user-filled description of self

+
+
+ homeUrl: + string + +
+
+

url this user wants the world to click

+
+
+ currentKey: + string + +
+
+

sh256 multihash of public key that this user is currently using for signatures

+
+
+
+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/public/javascripts/spectacle.js b/public/javascripts/spectacle.js new file mode 100644 index 0000000..e75fc6a --- /dev/null +++ b/public/javascripts/spectacle.js @@ -0,0 +1,242 @@ +$(function() { + // $(document).foundation(); + + var $sidebar = $('#sidebar'); + if ($sidebar.length) { + var $docs = $('#docs'); + var $nav = $sidebar.find('nav'); + + // + // Setup sidebar navigation + var traverse = new Traverse($nav, { + threshold: 10, + barOffset: $sidebar.position().top + }); + + $nav.on('update.traverse', function(event, element) { + $nav.find('section').removeClass('expand'); + var $section = element.parents('section:first'); + if ($section.length) { + $section.addClass('expand'); + } + }); + + // + // Bind the drawer layout + var $drawerLayout = $('.drawer-layout'), + $drawer = $drawerLayout.find('.drawer'), + closeDrawer = function() { + $drawer.removeClass('slide-right slide-left'); + $drawer.find('.drawer-overlay').remove(); + $drawerLayout.removeClass('drawer-open drawer-slide-left-large drawer-slide-right-large'); + return false; + }; + + // Drawer open buttons + $drawerLayout.find('[data-drawer-slide]').click(function(e) { + var $this = $(this), + direction = $this.data('drawer-slide'); + $drawerLayout.addClass('drawer-open'); + $drawer.addClass('slide-' + direction); + + var $overlay = $('') + $drawer.append($overlay); + $overlay.click(closeDrawer); + + return false; + }); + + // Drawer close buttons + $drawerLayout.find('[data-drawer-close]').click(closeDrawer); + } +}); + +/** + * Creates a new instance of Traverse. + * @class + * @fires Traverse#init + * @param {Object} element - jQuery object to add the trigger to. + * @param {Object} options - Overrides to the default plugin settings. + */ +function Traverse(element, options) { + this.$element = element; + this.options = $.extend({}, Traverse.defaults, this.$element.data(), options); + + this._init(); +} + +/** + * Default settings for plugin + */ +Traverse.defaults = { + /** + * Amount of time, in ms, the animated scrolling should take between locations. + * @option + * @example 500 + */ + animationDuration: 500, + /** + * Animation style to use when scrolling between locations. + * @option + * @example 'ease-in-out' + */ + animationEasing: 'linear', + /** + * Number of pixels to use as a marker for location changes. + * @option + * @example 50 + */ + threshold: 50, + /** + * Class applied to the active locations link on the traverse container. + * @option + * @example 'active' + */ + activeClass: 'active', + /** + * Allows the script to manipulate the url of the current page, and if supported, alter the history. + * @option + * @example true + */ + deepLinking: false, + /** + * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar. + * @option + * @example 25 + */ + barOffset: 0 +}; + +/** + * Initializes the Traverse plugin and calls functions to get equalizer functioning on load. + * @private + */ +Traverse.prototype._init = function() { + var id = this.$element[0].id, // || Foundation.GetYoDigits(6, 'traverse'), + _this = this; + this.$targets = $('[data-traverse-target]'); + this.$links = this.$element.find('a'); + this.$element.attr({ + 'data-resize': id, + 'data-scroll': id, + 'id': id + }); + this.$active = $(); + this.scrollPos = parseInt(window.pageYOffset, 10); + + this._events(); +}; + +/** + * Calculates an array of pixel values that are the demarcation lines between locations on the page. + * Can be invoked if new elements are added or the size of a location changes. + * @function + */ +Traverse.prototype.calcPoints = function(){ + var _this = this, + body = document.body, + html = document.documentElement; + + this.points = []; + this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight)); + this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)); + + this.$targets.each(function(){ + var $tar = $(this), + pt = $tar.offset().top; // Math.round($tar.offset().top - _this.options.threshold); + $tar.targetPoint = pt; + _this.points.push(pt); + }); +}; + +/** + * Initializes events for Traverse. + * @private + */ +Traverse.prototype._events = function() { + var _this = this, + $body = $('html, body'), + opts = { + duration: _this.options.animationDuration, + easing: _this.options.animationEasing + }; + + $(window).one('load', function(){ + _this.calcPoints(); + _this._updateActive(); + + $(this).resize(function(e) { + _this.reflow(); + }).scroll(function(e) { + _this._updateActive(); + }); + }) + + this.$element.on('click', 'a[href^="#"]', function(e) { //'click.zf.traverse' + e.preventDefault(); + var arrival = this.getAttribute('href').replace(".", "\\."), + scrollPos = $(arrival).offset().top - _this.options.barOffset; // - _this.options.threshold / 2 - _this.options.barOffset; + + $body.stop(true).animate({ + scrollTop: scrollPos + }, opts); + }); +}; + +/** + * Calls necessary functions to update Traverse upon DOM change + * @function + */ +Traverse.prototype.reflow = function(){ + this.calcPoints(); + this._updateActive(); +}; + +/** + * Updates the visibility of an active location link, + * and updates the url hash for the page, if deepLinking enabled. + * @private + * @function + * @fires Traverse#update + */ + Traverse.prototype._updateActive = function(){ + var winPos = parseInt(window.pageYOffset, 10), + curIdx; + + if(winPos + this.winHeight === this.docHeight){ curIdx = this.points.length - 1; } + else if(winPos < this.points[0]){ curIdx = 0; } + else{ + var isDown = this.scrollPos < winPos, + _this = this, + curVisible = this.points.filter(function(p, i){ + return isDown ? + p <= (winPos + _this.options.barOffset + _this.options.threshold) : + (p - (_this.options.barOffset + _this.options.threshold)) <= winPos; + // p <= (winPos - (offset - _this.options.threshold)) : + // (p - (-offset + _this.options.threshold)) <= winPos; + }); + curIdx = curVisible.length ? curVisible.length - 1 : 0; + } + + var $prev = this.$active; + var $next = this.$links.eq(curIdx); + this.$active.removeClass(this.options.activeClass); + this.$active = $next.addClass(this.options.activeClass); + + if(this.options.deepLinking){ + var hash = this.$active[0].getAttribute('href'); + if(window.history.pushState){ + window.history.pushState(null, null, hash); + }else{ + window.location.hash = hash; + } + } + + this.scrollPos = winPos; + + // Fire event if the active element was changed + var changed = $prev[0] !== $next[0]; + if (changed) { + this.$element.trigger('update.traverse', [this.$active]); + } + }; diff --git a/public/javascripts/spectacle.min.js b/public/javascripts/spectacle.min.js new file mode 100644 index 0000000..f196234 --- /dev/null +++ b/public/javascripts/spectacle.min.js @@ -0,0 +1 @@ +function Traverse(a,b){this.$element=a,this.options=$.extend({},Traverse.defaults,this.$element.data(),b),this._init()}$(function(){var a=$("#sidebar");if(a.length){var b=($("#docs"),a.find("nav"));new Traverse(b,{threshold:10,barOffset:a.position().top});b.on("update.traverse",function(a,c){b.find("section").removeClass("expand");var d=c.parents("section:first");d.length&&d.addClass("expand")});var c=$(".drawer-layout"),d=c.find(".drawer"),e=function(){return d.removeClass("slide-right slide-left"),d.find(".drawer-overlay").remove(),c.removeClass("drawer-open drawer-slide-left-large drawer-slide-right-large"),!1};c.find("[data-drawer-slide]").click(function(a){var b=$(this),f=b.data("drawer-slide");c.addClass("drawer-open"),d.addClass("slide-"+f);var g=$('');return d.append(g),g.click(e),!1}),c.find("[data-drawer-close]").click(e)}}),Traverse.defaults={animationDuration:500,animationEasing:"linear",threshold:50,activeClass:"active",deepLinking:!1,barOffset:0},Traverse.prototype._init=function(){var a=this.$element[0].id;this.$targets=$("[data-traverse-target]"),this.$links=this.$element.find("a"),this.$element.attr({"data-resize":a,"data-scroll":a,id:a}),this.$active=$(),this.scrollPos=parseInt(window.pageYOffset,10),this._events()},Traverse.prototype.calcPoints=function(){var a=this,b=document.body,c=document.documentElement;this.points=[],this.winHeight=Math.round(Math.max(window.innerHeight,c.clientHeight)),this.docHeight=Math.round(Math.max(b.scrollHeight,b.offsetHeight,c.clientHeight,c.scrollHeight,c.offsetHeight)),this.$targets.each(function(){var b=$(this),c=b.offset().top;b.targetPoint=c,a.points.push(c)})},Traverse.prototype._events=function(){var a=this,b=$("html, body"),c={duration:a.options.animationDuration,easing:a.options.animationEasing};$(window).one("load",function(){a.calcPoints(),a._updateActive(),$(this).resize(function(b){a.reflow()}).scroll(function(b){a._updateActive()})}),this.$element.on("click",'a[href^="#"]',function(d){d.preventDefault();var e=this.getAttribute("href").replace(".","\\."),f=$(e).offset().top-a.options.barOffset;b.stop(!0).animate({scrollTop:f},c)})},Traverse.prototype.reflow=function(){this.calcPoints(),this._updateActive()},Traverse.prototype._updateActive=function(){var a,b=parseInt(window.pageYOffset,10);if(b+this.winHeight===this.docHeight)a=this.points.length-1;else if(b