From f89d169ef399b1cf1b5cf10b1763b0244626c56c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 11:30:42 +0200 Subject: [PATCH 1/8] provide library entry point that provides convenient reexports of the public classes --- package.json | 2 +- src/lib.ts | 33 ++++++++++++++++++++++++++++++ src/sdk.ts | 58 ---------------------------------------------------- 3 files changed, 34 insertions(+), 59 deletions(-) create mode 100644 src/lib.ts delete mode 100644 src/sdk.ts diff --git a/package.json b/package.json index 52eb38af..65e72801 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hydrogen-web", "version": "0.2.16", "description": "A javascript matrix client prototype, trying to minize RAM usage by offloading as much as possible to IndexedDB", - "main": "index.js", + "main": "src/lib.ts", "directories": { "doc": "doc" }, diff --git a/src/lib.ts b/src/lib.ts new file mode 100644 index 00000000..54b8b4f8 --- /dev/null +++ b/src/lib.ts @@ -0,0 +1,33 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// types need to bootstrap a SessionContainer +export {SessionContainer} from "./matrix/SessionContainer.js"; +export {Session} from "./matrix/Session.js"; +export {Sync} from "./matrix/Sync.js"; +export {Room} from "./matrix/room/Room.js"; +export {Timeline} from "./matrix/room/timeline/Timeline.js"; +export {createNavigation, createRouter} from "./domain/navigation/index.js"; +export {Platform} from "./platform/web/Platform.js"; +// export main view & view models +export {RootViewModel} from "./domain/RootViewModel.js"; +export {RootView} from "./platform/web/ui/RootView.js"; +export {SessionViewModel} from "./domain/session/SessionViewModel.js"; +export {SessionView} from "./platform/web/ui/session/SessionView.js"; +export {RoomViewModel} from "./domain/session/room/RoomViewModel.js"; +export {RoomView} from "./platform/web/ui/session/room/RoomView.js"; +export {TimelineViewModel} from "./domain/session/room/timeline/TimelineViewModel.js"; +export {TimelineView} from "./platform/web/ui/session/room/TimelineView"; diff --git a/src/sdk.ts b/src/sdk.ts deleted file mode 100644 index 0754b2ab..00000000 --- a/src/sdk.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2020 Bruno Windels -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay.js"; -import {SessionContainer} from "./matrix/SessionContainer.js"; -import {RootViewModel} from "./domain/RootViewModel.js"; -import {createNavigation, createRouter} from "./domain/navigation/index.js"; -// Don't use a default export here, as we use multiple entries during legacy build, -// which does not support default exports, -// see https://github.com/rollup/plugins/tree/master/packages/multi-entry -export async function main(platform) { - try { - // to replay: - // const fetchLog = await (await fetch("/fetchlogs/constrainterror.json")).json(); - // const replay = new ReplayRequester(fetchLog, {delay: false}); - // const request = replay.request; - - // to record: - // const recorder = new RecordRequester(createFetchRequest(clock.createTimeout)); - // const request = recorder.request; - // window.getBrawlFetchLog = () => recorder.log(); - const navigation = createNavigation(); - platform.setNavigation(navigation); - const urlRouter = createRouter({navigation, history: platform.history}); - urlRouter.attach(); - const olmPromise = platform.loadOlm(); - const workerPromise = platform.loadOlmWorker(); - - const vm = new RootViewModel({ - createSessionContainer: () => { - return new SessionContainer({platform, olmPromise, workerPromise}); - }, - platform, - // the only public interface of the router is to create urls, - // so we call it that in the view models - urlCreator: urlRouter, - navigation, - }); - await vm.load(); - platform.createAndMountRootView(vm); - } catch(err) { - console.error(`${err.message}:\n${err.stack}`); - } -} From aac0e74b9dd1fe408d3fc14a29e325b9fd480c8b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 12:49:30 +0200 Subject: [PATCH 2/8] also export LoadStatus --- src/lib.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.ts b/src/lib.ts index 54b8b4f8..27290fb5 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -15,7 +15,7 @@ limitations under the License. */ // types need to bootstrap a SessionContainer -export {SessionContainer} from "./matrix/SessionContainer.js"; +export {SessionContainer, LoadStatus} from "./matrix/SessionContainer.js"; export {Session} from "./matrix/Session.js"; export {Sync} from "./matrix/Sync.js"; export {Room} from "./matrix/room/Room.js"; From d2eeaab5f572590b290fa61c0f71b5c759c4fc49 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 12:49:41 +0200 Subject: [PATCH 3/8] get assets paths with import "asset?url" specifically for vitejs --- src/sdk/paths/vite.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/sdk/paths/vite.ts diff --git a/src/sdk/paths/vite.ts b/src/sdk/paths/vite.ts new file mode 100644 index 00000000..c3ce3188 --- /dev/null +++ b/src/sdk/paths/vite.ts @@ -0,0 +1,12 @@ +import downloadSandboxPath from "../../../assets/download-sandbox.html?url"; +import olmWasmPath from "../../../lib/olm/olm.wasm?url"; +import olmJsPath from "../../../lib/olm/olm.js?url"; +import olmLegacyJsPath from "../../../lib/olm/olm_legacy.js?url"; + +export const olmPaths = { + wasm: olmWasmPath, + legacyBundle: olmLegacyJsPath, + wasmBundle: olmJsPath, +}; + +export const downloadSandbox = downloadSandboxPath; From c1d20cb9f9f021340f52d9f59634d35079aaa0e2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 12:56:36 +0200 Subject: [PATCH 4/8] also call this -Path --- src/sdk/paths/vite.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdk/paths/vite.ts b/src/sdk/paths/vite.ts index c3ce3188..e38648eb 100644 --- a/src/sdk/paths/vite.ts +++ b/src/sdk/paths/vite.ts @@ -1,4 +1,4 @@ -import downloadSandboxPath from "../../../assets/download-sandbox.html?url"; +import _downloadSandboxPath from "../../../assets/download-sandbox.html?url"; import olmWasmPath from "../../../lib/olm/olm.wasm?url"; import olmJsPath from "../../../lib/olm/olm.js?url"; import olmLegacyJsPath from "../../../lib/olm/olm_legacy.js?url"; @@ -9,4 +9,4 @@ export const olmPaths = { wasmBundle: olmJsPath, }; -export const downloadSandbox = downloadSandboxPath; +export const downloadSandboxPath = _downloadSandboxPath; From 193a0e1a4fedf88bed15d119a5bd7c18bcc8a6fb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 13:26:03 +0200 Subject: [PATCH 5/8] move UI docs to doc folder --- {documentation => doc}/UI/index.md | 0 {documentation => doc}/UI/render-dom-elements.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {documentation => doc}/UI/index.md (100%) rename {documentation => doc}/UI/render-dom-elements.md (100%) diff --git a/documentation/UI/index.md b/doc/UI/index.md similarity index 100% rename from documentation/UI/index.md rename to doc/UI/index.md diff --git a/documentation/UI/render-dom-elements.md b/doc/UI/render-dom-elements.md similarity index 100% rename from documentation/UI/render-dom-elements.md rename to doc/UI/render-dom-elements.md From 675ee59e5093ce80bc5628ad1456b3993b33a204 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 13:26:14 +0200 Subject: [PATCH 6/8] Add instructions and example code for basic SDK usage --- doc/SDK.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 doc/SDK.md diff --git a/doc/SDK.md b/doc/SDK.md new file mode 100644 index 00000000..7d34a49b --- /dev/null +++ b/doc/SDK.md @@ -0,0 +1,77 @@ +# How to use Hydrogen as an SDK + +If you want to use end-to-end encryption, it is recommended to use a [supported build system](../src/sdk/paths/) (currently only vite) to be able to locate the olm library files. + +You can create a project using the following commands + +```sh +# you can pick "vanilla-ts" here for project type if you're not using react or vue +yarn create vite +cd +yarn +yarn add https://github.com/vector-im/hydrogen-web.git +``` + +If you go into the `src` directory, you should see a `main.ts` file. If you put this code in there, you should see a basic timeline after login and initial sync have finished. + +```ts +import { + Platform, + SessionContainer, + LoadStatus, + createNavigation, + createRouter, + RoomViewModel, + TimelineView +} from "hydrogen-web"; +import {olmPaths, downloadSandboxPath} from "hydrogen-web/src/sdk/paths/vite"; + +const app = document.querySelector('#app')! + +// bootstrap a session container +const platform = new Platform(app, { + downloadSandbox: downloadSandboxPath, + olm: olmPaths, +}, null, { development: true }); +const navigation = createNavigation(); +platform.setNavigation(navigation); +const urlRouter = createRouter({ + navigation: navigation, + history: platform.history +}); +urlRouter.attach(); +const sessionContainer = new SessionContainer({ + platform, + olmPromise: platform.loadOlm(), + workerPromise: platform.loadOlmWorker() +}); + +// wait for login and first sync to finish +const loginOptions = await sessionContainer.queryLogin("matrix.org").result; +sessionContainer.startWithLogin(loginOptions.password("bruno4", "testtest")); +await sessionContainer.loadStatus.waitFor((status: string) => { + return status === LoadStatus.Ready || + status === LoadStatus.Error || + status === LoadStatus.LoginFailed; +}).promise; +// check the result +if (sessionContainer.loginFailure) { + alert("login failed: " + sessionContainer.loginFailure); +} else if (sessionContainer.loadError) { + alert("load failed: " + sessionContainer.loadError.message); +} else { + // we're logged in, we can access the room now + const {session} = sessionContainer; + const room = session.rooms.get("!bEWtlqtDwCLFIAKAcv:matrix.org"); + const vm = new RoomViewModel({ + room, + ownUserId: session.userId, + platform, + urlCreator: urlRouter, + navigation, + }); + await vm.load(); + const view = new TimelineView(vm.timelineViewModel); + app.appendChild(view.mount()); +} +``` From 23da4ae2dd7a557062c2f5e49c02df00e35bff8d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 13:27:58 +0200 Subject: [PATCH 7/8] point to SDK docs from FAQ --- doc/FAQ.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/FAQ.md b/doc/FAQ.md index c6445c72..4784062d 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -32,10 +32,4 @@ There are no published builds at this point. You need to checkout the version yo ## I want to embed Hydrogen in my website, how should I do that? -There are no npm modules yet published for Hydrogen. The easiest is probably to setup your website project, do yarn/npm init if you haven't yet, then add the hydrogen repo as a git http dependency, and import the files/classes you want to use from Hydrogen. - -For example, for a single room chat, you could create an instance of `Platform`, you create a new `SessionContainer` with it, call `startWithLogin` on it, observe `sessionContainer.loadStatus` to know when initial sync is done, then do `sessionContainer.session.rooms.get('roomid')` and you create a `RoomViewModel` with it and pass that to a `RoomView`. Then you call `document.appendChild(roomView.mount())` and you should see a syncing room. - -Feel free to ask for pointers in #hydrogen:matrix.org as the documentation is still lacking considerably. Note that at this early, pre 1.0 stage of the project, there is no promise of API stability yet. - -Also, to make end-to-end encryption work, you'll likely need some tweaks to your build system, see [this issue](https://github.com/vector-im/hydrogen-web/issues/467). +Hydrogen aims to be usable as an SDK, and while it is still early days, you can find some documentation how to do that in [SDK.md](SDK.md). From fbfda031381d4a34796bd5f89d94f696d783155f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 1 Oct 2021 13:32:09 +0200 Subject: [PATCH 8/8] don't let tsc check build system specific files --- tsconfig.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tsconfig.json b/tsconfig.json index 0179e267..e09e7cc5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,5 +4,8 @@ "noEmit": true, "target": "ES2020" }, + "exclude": [ + "src/sdk/paths/*" + ], "include": ["src/**/*"], }