mirror of
https://github.com/OutlineFoundation/outline-server.git
synced 2026-08-04 06:35:06 +00:00
almost done
This commit is contained in:
parent
12631d3727
commit
1bc144f44e
15 changed files with 1921 additions and 46 deletions
1788
package-lock.json
generated
1788
package-lock.json
generated
File diff suppressed because it is too large
Load diff
50
src/sdk/README.md
Normal file
50
src/sdk/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Manager SDK Prototype
|
||||
|
||||
This is a prototype of a Manager SDK for the Outline Server.
|
||||
|
||||
It uses `ngrok` to allow the user to access the Management API from the browser.
|
||||
|
||||
It uses the `lit` library to create a web component that displays the server details.
|
||||
|
||||
It also uses `@hey-api/openapi-ts` to generate a TypeScript library from the Outline Server API definition.
|
||||
|
||||
## Setup
|
||||
|
||||
Get a`NGROK_TOKEN` from https://dashboard.ngrok.com/get-started/your-authtoken and a `NGROK_DOMAIN` from https://dashboard.ngrok.com/domains.
|
||||
|
||||
```sh
|
||||
export NGROK_TOKEN=...
|
||||
export NGROK_DOMAIN=...
|
||||
|
||||
# Start the local outline server
|
||||
task shadowbox:start &
|
||||
|
||||
# Start the web app demo
|
||||
npm run example --workspace sdk
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
<img src="screenshots/results.png" alt="results" width="320"/>
|
||||
|
||||
## Library Generation
|
||||
|
||||
Generated library from `src/shadowbox/server/api.yml` with `@hey-api/openapi-ts`:
|
||||
|
||||
```bash
|
||||
# run in project root
|
||||
npx @hey-api/openapi-ts \
|
||||
-i src/shadowbox/server/api.yml \
|
||||
-o src/sdk/library/generated \
|
||||
-c @hey-api/client-fetch
|
||||
```
|
||||
|
||||
Intellisense example:
|
||||
|
||||
<img src="screenshots/intellisense.png" alt="intellisense" width="320"/>
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] Why does Prometheus continuously crash (had to comment it out)
|
||||
- [ ] Generate Library on API change
|
||||
- [ ] ...
|
||||
12
src/sdk/example/index.html
Normal file
12
src/sdk/example/index.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Manager SDK Demo</title>
|
||||
<script type="module" src="/src/server-details.ts"></script>
|
||||
</head>
|
||||
<body>
|
||||
<server-details url="%VITE_SERVER_DETAIL_URL%"></server-details>
|
||||
</body>
|
||||
</html>
|
||||
53
src/sdk/example/src/server-details.ts
Normal file
53
src/sdk/example/src/server-details.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { LitElement, html, css } from 'lit'
|
||||
import { customElement, state, property } from 'lit/decorators.js';
|
||||
|
||||
import makeLibrary, { type Server } from '../../library';
|
||||
|
||||
@customElement('server-details')
|
||||
export class MainPage extends LitElement {
|
||||
@property({ type: String }) url: string;
|
||||
|
||||
@state() server?: Server;
|
||||
|
||||
constructor(url: string) {
|
||||
super();
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
get client() {
|
||||
return makeLibrary(this.url);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
font-family: system-ui;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
`;
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
const { data } = await this.client.getServer();
|
||||
|
||||
this.server = data;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.server) {
|
||||
return html`Loading...`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<dl>
|
||||
${Object.entries(this.server).map(([key, value]) => html`
|
||||
<dt>${key}</dt>
|
||||
<dd>${value}</dd>
|
||||
`)}
|
||||
</dl>
|
||||
`;
|
||||
}
|
||||
}
|
||||
1
src/sdk/example/src/vite-env.d.ts
vendored
Normal file
1
src/sdk/example/src/vite-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
||||
25
src/sdk/example/tsconfig.json
Normal file
25
src/sdk/example/tsconfig.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": false,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
11
src/sdk/library/index.ts
Normal file
11
src/sdk/library/index.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { client } from './generated/client.gen';
|
||||
|
||||
import * as generated from './generated';
|
||||
|
||||
export type * from './generated';
|
||||
|
||||
export default (baseUrl: string) => {
|
||||
client.setConfig({ baseUrl, headers: { "ngrok-skip-browser-warning": "69420" } });
|
||||
|
||||
return generated;
|
||||
}
|
||||
16
src/sdk/package.json
Normal file
16
src/sdk/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "sdk",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"example": "VITE_SERVER_DETAIL_URL=https://${NGROK_DOMAIN}/TestApiPrefix vite example"
|
||||
},
|
||||
"dependencies": {
|
||||
"lit": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "~5.7.2",
|
||||
"vite": "^6.2.0"
|
||||
}
|
||||
}
|
||||
BIN
src/sdk/screenshots/intellisense.png
Normal file
BIN
src/sdk/screenshots/intellisense.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
src/sdk/screenshots/results.png
Normal file
BIN
src/sdk/screenshots/results.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
|
|
@ -283,17 +283,26 @@ process.on('unhandledRejection', (error: Error) => {
|
|||
|
||||
main()
|
||||
.then(async () => {
|
||||
if (!process.env.NGROK_TOKEN || !process.env.NGROK_DOMAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
process.env.SSL_CERT_FILE = process.env.SB_CERTIFICATE_FILE;
|
||||
process.env.SSL_KEY_FILE = process.env.SB_PRIVATE_KEY_FILE;
|
||||
|
||||
const listener = await ngrok.forward({
|
||||
domain: process.env.NGROK_DOMAIN,
|
||||
// ipv6 loopback address doesn't work
|
||||
addr: `https://127.0.0.1:${process.env.SB_API_PORT || 8081}`,
|
||||
authtoken_from_env: true,
|
||||
verify_upstream_tls: false,
|
||||
response_header_add: [
|
||||
'Allow-Access-Control-Origin: *',
|
||||
'Access-Control-Allow-Headers: *'
|
||||
],
|
||||
});
|
||||
|
||||
console.log(`Listening to the Manager API on ${listener.url()}`);
|
||||
console.log(`Listening to the Manager API on '${listener.url()}'`);
|
||||
})
|
||||
.catch((error) => {
|
||||
logging.error(error.stack);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue