This commit is contained in:
Daniel Vassallo
2019-10-31 10:26:27 -07:00
parent 1e421126cb
commit f191382659
20 changed files with 588 additions and 27 deletions

52
package-lock.json generated
View File

@@ -1718,6 +1718,12 @@
"object.assign": "^4.1.0"
}
},
"babel-plugin-prismjs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-prismjs/-/babel-plugin-prismjs-1.1.1.tgz",
"integrity": "sha512-MmwxA//jBpXH0IhJ2FbpBJmd6Bvq5rBe3UD3udUqfkkOdh6lmQeYxoVGpkIvLuuXecrynWjpPqwM0JPxErebpQ==",
"dev": true
},
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
@@ -2373,6 +2379,17 @@
}
}
},
"clipboard": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz",
"integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==",
"optional": true,
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -3167,6 +3184,12 @@
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"optional": true
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -4905,6 +4928,15 @@
}
}
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"optional": true,
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
@@ -7947,6 +7979,14 @@
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
"dev": true
},
"prismjs": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
"integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==",
"requires": {
"clipboard": "^2.0.0"
}
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -8636,6 +8676,12 @@
"ajv-keywords": "^3.1.0"
}
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
"optional": true
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -9629,6 +9675,12 @@
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"optional": true
},
"tinycolor2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",

View File

@@ -19,6 +19,7 @@
"@fullhuman/postcss-purgecss": "^1.3.0",
"autoprefixer": "^9.6.0",
"babel-loader": "^8.0.6",
"babel-plugin-prismjs": "^1.1.1",
"babel-polyfill": "^6.26.0",
"cross-env": "^6.0.3",
"css-loader": "^2.1.1",
@@ -33,6 +34,7 @@
"opn-browser-webpack-plugin": "0.0.7",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"postcss-loader": "^3.0.0",
"prismjs": "^1.17.1",
"source-map-loader": "^0.2.4",
"tailwindcss": "^1.0.4",
"terser-webpack-plugin": "^1.3.0",

View File

@@ -1,5 +1,18 @@
import './style.css'
import Prism from 'prismjs'
import 'prismjs/themes/prism-coy.css'
import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-javascript'
import 'prismjs/plugins/line-numbers/prism-line-numbers'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'
import './prism.css'
Prism.highlightAll();
window.displayMailChimpStatus = function (data) {
if (!data.result || !data.msg) return

12
src/pages/docs.html Normal file
View File

@@ -0,0 +1,12 @@
<div class="section">
<h2 id="getting-started">Docs</h2>
<ul>
<li><a href="/docs/getting-started" class="font-semibold">Getting started</a></li>
<li><a href="/docs/sdk" class="font-semibold">SDK</a></li>
<li><a href="https://github.com/encrypted-dev/userbase/blob/ugliest-tutorial/docs/examples/ugliest-todo-app/tutorial.md" class="font-semibold">Tutorial</a></li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,33 @@
<div class="section">
<h2><a href="/docs">Docs</a> : Getting Started</h2>
<h3>Create a free Userbase account</h3>
<p>First you need a Userbase account. You will be able to create a free account when Userbase gets launched. No credit card required.</p>
<h3>Install the SDK</h3>
<p>Then you need to include the Userbase SDK into your web app.</p>
<p>You can either include the SDK with a &lt;script&gt; tag:</p>
<pre>
<code class="language-html">&lt;script type="text/javascript"
src="https://userbase-public.s3-us-west-2.amazonaws.com/userbase-js/userbase.js"&gt;
&lt;/script&gt;</code>
</pre>
<p>Or else you can include the SDK into your build pipeline:</p>
<pre>
<code class="language-bash">npm --install --save userbase-js</code>
</pre>
<h3>Set the Application ID</h3>
<p>From your Userbase account, create a new App and get the Application ID. Then you just need to configure the Userbase SDK to use it:</p>
<pre>
<code class="language-bash">userbase.configure({ appId: 'a43ae910-fc89-43fe-a7a3-a11a53b49325' })</code>
</pre>
<p>And you're all set.</p>
</div>
<hr>

26
src/pages/docs_sdk.html Normal file
View File

@@ -0,0 +1,26 @@
<div class="section">
<h2><a href="/docs">Docs</a> : SDK</h2>
<p>You can use Userbase through a simple JavaScript SDK in the browser. The following is the complete set of Userbase APIs that let you create user accounts, handle logins, and persist user data.</p>
<h3 id="zero-management-database">Users</h3>
<p>Use these APIs to create user accounts, handle logins and logouts, and resume sessions when a user returns to your web app.</p>
<ul>
<li><a href="/docs/sdk/sign-up" class="font-semibold">SignUp</a></li>
<li><a href="/docs/sdk/sign-in" class="font-semibold">SignIn</a></li>
<li><a href="/docs/sdk/sign-in-with-session" class="font-semibold">SignInWithSession</a></li>
<li><a href="/docs/sdk/sign-out" class="font-semibold">SignOut</a></li>
</ul>
<h3 id="user-accounts">Data</h3>
<p>Use these APIs to store and retrieve user data. All data handled by these APIs is highly-durable, immediately consistent, and end-to-end encrypted.</p>
<ul>
<li><a href="/docs/sdk/open-database" class="font-semibold">OpenDatabase</a></li>
<li><a href="/docs/sdk/insert" class="font-semibold">Insert</a></li>
<li><a href="/docs/sdk/update" class="font-semibold">Update</a></li>
<li><a href="/docs/sdk/delete" class="font-semibold">Delete</a></li>
<li><a href="/docs/sdk/transaction" class="font-semibold">Transaction</a></li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,39 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : Delete</h2>
<p><span class="font-semibold">Delete</span> lets your delete an item from a user's database. This API with will return a promise that gets resolved once the item has been durably deleted from the database.</p>
<pre>
<code class="language-javascript">userbase.delete(databaseName, itemId)
.then(() => {
// item deleted
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">databaseName</span> [string | Len: 1-50] - The database name to use.
</li>
<li>
<span class="field">itemId</span> [string | Len: 1-100] - The unique identifier of the item to delete.
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>DatabaseNotOpen</li>
<li>ItemIdCannotBeBlank</li>
<li>ItemIdMustBeString</li>
<li>ItemDoesNotExist</li>
<li>UpdateConflict</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,43 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : Insert</h2>
<p><span class="font-semibold">Insert</span> lets your add items to a user's database. This API with will return a promise that gets resolved once the item has been durably inserted into the database.</p>
<pre>
<code class="language-javascript">userbase.insert(databaseName, itemId, item)
.then(() => {
// item inserted
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">databaseName</span> [string | Len: 1-50] - The database name to use.
</li>
<li>
<span class="field">itemId</span> [string | Len: 1-100] - The item's unique identifier.
</li>
<li>
<span class="field">item</span> [object | Max size: 100KB] - The item to insert.
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>DatabaseNotOpen</li>
<li>ItemIdCannotBeBlank</li>
<li>ItemIdTooLong</li>
<li>ItemIdMustBeString</li>
<li>ItemTooLarge</li>
<li>ItemAlreadyExists</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,49 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : OpenDatabase</h2>
<p><span class="font-semibold">OpenDatabase</span> lets your retrieve data stored by the users of your web app. You also need to have a database open before storing or modify user data. This API with will return a promise that gets resolved once the database becomes available for use.</p>
<pre>
<code class="language-javascript">userbase.openDatabase(databaseName, changeHandler)
.then(() => {
// the database can now be used
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">databaseName</span> [string | Len: 1-50] - The database name to use.
</li>
<li>
<span class="field">changeHandler</span> [function] - A callback that gets invoked when the database gets modified.
<ul>
<li>
<span class="field">items</span> [object] - The full collection of items in the database, in insertion order.
<ul>
<li><span class="field">itemId</span> [string] - The item's unique identifier.</li>
<li><span class="field">item</span> [object] - The stored item.</li>
<li><span class="field">creationTime</span> [Date] - The timestamp when the item was created.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>DatabaseAlreadyOpen</li>
<li>DatabaseNameCannotBeBlank</li>
<li>DatabaseNameTooLong</li>
<li>DatabaseNameMustBeString</li>
<li>ChangeHandlerMustBeFunction</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,45 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : SignInWithSession</h2>
<p><span class="font-semibold">SignInWithSession</span> lets you automatically log in a user using the last used session. This API with will return a promise that gets resolved once the session has been validated. If the session is valid, the user gets automatically logged in.</p>
<pre>
<code class="language-javascript">userbase.signInWithSession()
.then((session) => {
if (session.user) {
// there is a valid active session
console.log(session.user.username)
}
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="result">Result</h3>
<ul>
<li>
<span class="field">session</span> [object] - Contains information about the last used session.
<ul>
<li>
<span class="field">user</span> [object] - If set, this contains information about the logged in user.
<ul>
<li><span class="field">username</span> [string] - The user's username.</li>
<li><span class="field">seed</span> [string] - The user's encryption key.</li>
<li><span class="field">creationTime</span> [Date] - The timestamp when the user was created.</li>
</ul>
</li>
<li><span class="field">lastUsedUsername</span> [string] - If set, this is the username of the last user that was logged in.</li>
</ul>
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,55 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : SignIn</h2>
<p><span class="font-semibold">SignIn</span> lets your users log into your web app. This API with will return a promise that gets resolved once the user has been logged in.</p>
<pre>
<code class="language-javascript">userbase.signIn(username, password)
.then((user) => {
// user logged in
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">username</span> [string | Len: 1-50] - The username for the account to be created.
</li>
<li>
<span class="field">password</span> [string | Len: 6-1000] - The password for the account to be created.
</li>
</ul>
<h3 id="result">Result</h3>
<ul>
<li>
<span class="field">user</span> [object] - Contains information about the logged in user.
<ul>
<li><span class="field">username</span> [string] - The user's username.</li>
<li><span class="field">seed</span> [string] - The user's encryption key.</li>
<li><span class="field">creationTime</span> [Date] - The timestamp when the user was created.</li>
</ul>
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>UsernameOrPasswordMismatch</li>
<li>UsernameCannotBeBlank</li>
<li>UsernameTooLong</li>
<li>UsernameMustBeString</li>
<li>PasswordCannotBeBlank</li>
<li>PasswordTooShort</li>
<li>PasswordTooLong</li>
<li>PasswordMustBeString</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,23 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : SignOut</h2>
<p><span class="font-semibold">SignOut</span> lets your users log out of your web app. This API with will return a promise that gets resolved once the user has been logged out.</p>
<pre>
<code class="language-javascript">userbase.signOut()
.then(() => {
// user logged out
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="errors">Errors</h3>
<ul>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,55 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : SignUp</h2>
<p><span class="font-semibold">SignUp</span> lets you create user accounts for your web app. This API with will return a promise that gets resolved once the user account has been created.</p>
<pre>
<code class="language-javascript">userbase.signUp(username, password)
.then((user) => {
// user account created
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">username</span> [string | Len: 1-50] - The username for the account to be created.
</li>
<li>
<span class="field">password</span> [string | Len: 6-1000] - The password for the account to be created.
</li>
</ul>
<h3 id="result">Result</h3>
<ul>
<li>
<span class="field">user</span> [object] - Contains information about the new user.
<ul>
<li><span class="field">username</span> [string] - The user's username.</li>
<li><span class="field">seed</span> [string] - The user's encryption key.</li>
<li><span class="field">creationTime</span> [Date] - The timestamp when the user was created.</li>
</ul>
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>UsernameAlreadyExists</li>
<li>UsernameCannotBeBlank</li>
<li>UsernameTooLong</li>
<li>UsernameMustBeString</li>
<li>PasswordCannotBeBlank</li>
<li>PasswordTooShort</li>
<li>PasswordTooLong</li>
<li>PasswordMustBeString</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,40 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : Transaction</h2>
<pre>
<code class="language-javascript">userbase.transaction(databaseName, operations)
.then(() => {
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">databaseName</span> [string | Len: 1-50] - The database name to use.
</li>
<li>
<span class="field">operations</span> [Array] - The Insert, Update, or Delete operations to execute in an atomic transaction.
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>DatabaseNotOpen</li>
<li>ItemIdCannotBeBlank</li>
<li>ItemIdTooLong</li>
<li>ItemIdMustBeString</li>
<li>ItemTooLarge</li>
<li>ItemAlreadyExists</li>
<li>ItemDoesNotExist</li>
<li>UpdateConflict</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

View File

@@ -0,0 +1,43 @@
<div class="section">
<h2><a href="/docs">Docs</a> : <a href="/docs/sdk">SDK</a> : Update</h2>
<p><span class="font-semibold">Update</span> lets your modify an existing item in a user's database. This API with will return a promise that gets resolved once the item has been durably updated into the database.</p>
<pre>
<code class="language-javascript">userbase.update(databaseName, itemId, item)
.then(() => {
// item updated
})
.catch((e) => console.error(e))</code>
</pre>
<h3 id="params">Parameters</h3>
<ul>
<li>
<span class="field">databaseName</span> [string | Len: 1-50] - The database name to use.
</li>
<li>
<span class="field">itemId</span> [string | Len: 1-100] - The unique identifier of the item to replace.
</li>
<li>
<span class="field">item</span> [object | Max size: 100KB] - The object to overwrite the existing item with.
</li>
</ul>
<h3 id="errors">Errors</h3>
<ul>
<li>DatabaseNotOpen</li>
<li>ItemIdCannotBeBlank</li>
<li>ItemIdMustBeString</li>
<li>ItemTooLarge</li>
<li>ItemDoesNotExist</li>
<li>UpdateConflict</li>
<li>AppIdNotSet</li>
<li>ServiceUnavailable</li>
</ul>
</div>
<hr>

20
src/prism.css Normal file
View File

@@ -0,0 +1,20 @@
pre[class*="language-"]:before, pre[class*="language-"]:after {
content: normal;
}
pre[class*="language-"], :not(pre) > code[class*="language-"], pre[class*="language-"] {
margin: 0;
line-height: 0.6em;
}
code[class*="language"] {
padding-top: 1em;
padding-bottom: 1em;
}
pre[class*="language-"]>code {
background-color: #f6f6f6;
box-shadow: none;
background-image: none;
font-size: 0.7em;
}

View File

@@ -62,7 +62,7 @@ h3 {
}
h2 {
@apply text-5xl;
@apply text-4xl;
}
h3 {
@@ -70,6 +70,12 @@ h3 {
}
}
@screen lg {
h2 {
@apply text-5xl;
}
}
ul {
@apply list-disc mb-4 ml-8;
}
@@ -100,4 +106,8 @@ ul {
background-image: linear-gradient(119deg, rgb(255, 255, 255), rgb(255, 246, 151) 10.5%, #fdf59d 85.29%, #ffffff);
}
.field {
@apply font-semibold
}
@tailwind utilities;

View File

@@ -31,16 +31,16 @@
</header>
<div class="container mx-auto max-w-4xl px-4">
<%= require('html-loader!./pages/' + page + '.html') %>
<footer class="sm:flex sm:justify-between sm:items-center py-4 tracking-tight text-xs">
<div class="flex items-center justify-center sm:justify-between">
<div class="flex-shrink-0">
<div class="flex items-center justify-between">Copyright © 2019 Encrypted Development LLC</div>
</div>
<footer class="text-center py-4 tracking-tight text-sm">
<div>
<nav class="pt-2 pb-4 text-center menu">
<a href="http://github.com/encrypted-dev/userbase" class="py-2 leading-none px-2">GitHub</a>
<a href="https://twitter.com/UserbaseHQ" class="py-2 leading-none px-2">Twitter</a>
</nav>
</div>
<div class="text-gray-500 text-xs">
Copyright © 2019 Encrypted Development LLC
</div>
<nav class="pt-2 pb-4 sm:flex sm:p-0 text-center sm:text-right menu">
<a href="http://github.com/encrypted-dev/userbase" class="block py-2 leading-none sm:px-2">GitHub</a>
<a href="https://twitter.com/UserbaseHQ" class="block py-2 leading-none sm:px-2">Twitter</a>
</nav>
</footer>
</div>
</body>

View File

@@ -3,16 +3,17 @@ module.exports = {
extend: {
colors: {
yellowish: '#ffe77a',
blackish: '#1a2a30'
blackish: '#1a2a30',
blue: '#358ccb'
},
width: {
'72': '18rem',
'84': '21rem',
'96': '24rem'
},
fontFamily: {
'logo': 'Tahoma, Geneva, Verdana, sans-serif'
}
},
fontFamily: {
'logo': 'Tahoma, Geneva, Verdana, sans-serif'
}
},
variants: {},

View File

@@ -16,11 +16,21 @@ module.exports = (env, argv) => {
fs.readdirSync('./src/pages/').forEach(file => {
const page = file.split('.')[0]
let filename = './'
if (page !== 'index') {
const pagePath = page.split('_')
for (let i = 0; i < pagePath.length; i++) {
filename += pagePath[i] + '/'
}
}
filename += 'index.html'
pages.push(new HtmlWebPackPlugin({
template: './src/template.html',
filename: './' + file,
templateParameters() { return { page: file.split('.')[0] } }
filename,
templateParameters() { return { page } }
}))
})
@@ -98,17 +108,7 @@ module.exports = (env, argv) => {
hot: true,
inline: true,
host: '0.0.0.0',
port: 3000,
historyApiFallback: {
rewrites: [
{
from: /^\/.*$/,
to: function (context) {
return '/' + context.parsedUrl.pathname + '.html';
}
}
]
}
port: 3000
}
config.plugins.push(new webpack.HotModuleReplacementPlugin())