create-feathersdev 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -0
- package/README.md +3 -0
- package/bin/feathersdev +9 -0
- package/esm/actions/app.js +51 -0
- package/esm/actions/integrate.js +80 -0
- package/esm/actions/login.js +8 -0
- package/esm/actions/logout.js +12 -0
- package/esm/actions/server.js +52 -0
- package/esm/base.js +40 -0
- package/esm/flows/check-login.js +70 -0
- package/esm/flows/with-application.js +81 -0
- package/esm/flows/with-organization.js +74 -0
- package/esm/index.js +55 -0
- package/esm/package.json +1 -0
- package/examples/frontend/auth.ts +39 -0
- package/examples/frontend/react/.eslintrc.cjs +18 -0
- package/examples/frontend/react/README.md +30 -0
- package/examples/frontend/react/index.html +13 -0
- package/examples/frontend/react/package.json +29 -0
- package/examples/frontend/react/public/vite.svg +1 -0
- package/examples/frontend/react/src/App.css +42 -0
- package/examples/frontend/react/src/App.tsx +37 -0
- package/examples/frontend/react/src/assets/react.svg +1 -0
- package/examples/frontend/react/src/auth.ts +39 -0
- package/examples/frontend/react/src/automerge.ts +16 -0
- package/examples/frontend/react/src/index.css +68 -0
- package/examples/frontend/react/src/main.tsx +10 -0
- package/examples/frontend/react/src/vite-env.d.ts +1 -0
- package/examples/frontend/react/tsconfig.app.json +27 -0
- package/examples/frontend/react/tsconfig.json +11 -0
- package/examples/frontend/react/tsconfig.node.json +13 -0
- package/examples/frontend/react/vite.config.ts +7 -0
- package/examples/frontend/svelte/.vscode/extensions.json +3 -0
- package/examples/frontend/svelte/README.md +47 -0
- package/examples/frontend/svelte/index.html +13 -0
- package/examples/frontend/svelte/package.json +24 -0
- package/examples/frontend/svelte/public/vite.svg +1 -0
- package/examples/frontend/svelte/src/App.svelte +30 -0
- package/examples/frontend/svelte/src/app.css +79 -0
- package/examples/frontend/svelte/src/assets/svelte.svg +1 -0
- package/examples/frontend/svelte/src/auth.ts +33 -0
- package/examples/frontend/svelte/src/main.ts +9 -0
- package/examples/frontend/svelte/src/vite-env.d.ts +2 -0
- package/examples/frontend/svelte/svelte.config.js +7 -0
- package/examples/frontend/svelte/tsconfig.json +21 -0
- package/examples/frontend/svelte/tsconfig.node.json +12 -0
- package/examples/frontend/svelte/vite.config.ts +8 -0
- package/examples/frontend/vanilla/index.html +13 -0
- package/examples/frontend/vanilla/package.json +16 -0
- package/examples/frontend/vanilla/public/vite.svg +1 -0
- package/examples/frontend/vanilla/src/auth.ts +39 -0
- package/examples/frontend/vanilla/src/automerge.ts +16 -0
- package/examples/frontend/vanilla/src/main.ts +23 -0
- package/examples/frontend/vanilla/src/style.css +96 -0
- package/examples/frontend/vanilla/src/vite-env.d.ts +1 -0
- package/examples/frontend/vanilla/tsconfig.json +23 -0
- package/examples/frontend/vanilla/vite.config.ts +8 -0
- package/examples/frontend/vue/.vscode/extensions.json +3 -0
- package/examples/frontend/vue/README.md +33 -0
- package/examples/frontend/vue/env.d.ts +1 -0
- package/examples/frontend/vue/index.html +13 -0
- package/examples/frontend/vue/package.json +29 -0
- package/examples/frontend/vue/public/favicon.ico +0 -0
- package/examples/frontend/vue/src/App.vue +30 -0
- package/examples/frontend/vue/src/assets/base.css +86 -0
- package/examples/frontend/vue/src/assets/logo.svg +1 -0
- package/examples/frontend/vue/src/assets/main.css +35 -0
- package/examples/frontend/vue/src/auth.ts +39 -0
- package/examples/frontend/vue/src/automerge.ts +16 -0
- package/examples/frontend/vue/src/main.ts +6 -0
- package/examples/frontend/vue/tsconfig.app.json +14 -0
- package/examples/frontend/vue/tsconfig.json +11 -0
- package/examples/frontend/vue/tsconfig.node.json +19 -0
- package/examples/frontend/vue/vite.config.ts +18 -0
- package/examples/server/bun/README.md +15 -0
- package/examples/server/bun/bun.lockb +0 -0
- package/examples/server/bun/package.json +17 -0
- package/examples/server/bun/src/authenticate.ts +17 -0
- package/examples/server/bun/src/index.ts +54 -0
- package/examples/server/bun/tsconfig.json +27 -0
- package/examples/server/cloudflare/.editorconfig +12 -0
- package/examples/server/cloudflare/.prettierrc +6 -0
- package/examples/server/cloudflare/package.json +22 -0
- package/examples/server/cloudflare/src/authenticate.ts +17 -0
- package/examples/server/cloudflare/src/index.ts +50 -0
- package/examples/server/cloudflare/test/index.spec.ts +25 -0
- package/examples/server/cloudflare/test/tsconfig.json +8 -0
- package/examples/server/cloudflare/tsconfig.json +105 -0
- package/examples/server/cloudflare/vitest.config.mts +11 -0
- package/examples/server/cloudflare/worker-configuration.d.ts +4 -0
- package/examples/server/cloudflare/wrangler.toml +108 -0
- package/examples/server/deno/deno.lock +79 -0
- package/examples/server/deno/package.json +13 -0
- package/examples/server/deno/src/authenticate.ts +17 -0
- package/examples/server/deno/src/server.ts +51 -0
- package/examples/server/express/package.json +24 -0
- package/examples/server/express/src/app.ts +26 -0
- package/examples/server/express/src/authenticate.ts +51 -0
- package/examples/server/express/tsconfig.json +108 -0
- package/examples/server/nodejs/package.json +20 -0
- package/examples/server/nodejs/src/authenticate.ts +28 -0
- package/examples/server/nodejs/src/server.ts +38 -0
- package/examples/server/nodejs/tsconfig.json +108 -0
- package/package.json +67 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createClient } from '@feathersdev/auth'
|
|
2
|
+
import { createAutomerge } from '@feathersdev/automerge'
|
|
3
|
+
|
|
4
|
+
export const appId = '<your-app-id>'
|
|
5
|
+
|
|
6
|
+
export const auth = createClient({
|
|
7
|
+
appId,
|
|
8
|
+
onLoginRequired: async (error) => {
|
|
9
|
+
window.location.href = await auth.getLoginUrl(error)
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
export const automerge = createAutomerge(auth)
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Make an authenticated request using the fetch API or
|
|
17
|
+
* redirect to the login page if the user needs to log in.
|
|
18
|
+
*
|
|
19
|
+
* @param url The URL for the request
|
|
20
|
+
* @param options Additional request options.
|
|
21
|
+
* @returns The fetch response
|
|
22
|
+
*/
|
|
23
|
+
export async function authFetch(url: string, options?: RequestInit) {
|
|
24
|
+
const headers = new Headers(options?.headers)
|
|
25
|
+
|
|
26
|
+
// Set the authorization header with the Feathers Auth token
|
|
27
|
+
headers.set('Authorization', await auth.getHeader())
|
|
28
|
+
|
|
29
|
+
return fetch(url, {
|
|
30
|
+
...options,
|
|
31
|
+
headers,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"moduleDetection": "force",
|
|
6
|
+
"useDefineForClassFields": true,
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
/**
|
|
10
|
+
* Typecheck JS in `.svelte` and `.js` files by default.
|
|
11
|
+
* Disable checkJs if you'd like to use dynamic types in JS.
|
|
12
|
+
* Note that setting allowJs false does not prevent the use
|
|
13
|
+
* of JS in `.svelte` files.
|
|
14
|
+
*/
|
|
15
|
+
"allowJs": true,
|
|
16
|
+
"checkJs": true,
|
|
17
|
+
"isolatedModules": true
|
|
18
|
+
},
|
|
19
|
+
"references": [{ "path": "./tsconfig.node.json" }],
|
|
20
|
+
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"composite": true,
|
|
4
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"skipLibCheck": true
|
|
10
|
+
},
|
|
11
|
+
"include": ["vite.config.ts"]
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Vite + TS</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.ts"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vanilla-frontend",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite --port 3000",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"typescript": "^5.6.3",
|
|
13
|
+
"vite-plugin-wasm": "^3.4.1",
|
|
14
|
+
"vite": "^5.4.11"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createClient } from '@feathersdev/auth'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is your public application id
|
|
5
|
+
*/
|
|
6
|
+
export const appId = '<your-app-id>'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The Feathers auth client instance. You can use it to get a token,
|
|
10
|
+
* retrieve the current user and to log in and out.
|
|
11
|
+
*/
|
|
12
|
+
export const auth = createClient({
|
|
13
|
+
appId,
|
|
14
|
+
onLoginRequired: async (error) => {
|
|
15
|
+
// Redirect to login page if a login is required
|
|
16
|
+
// You can also do other things here like show a modal before redirecting
|
|
17
|
+
window.location.href = await auth.getLoginUrl(error)
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Make an authenticated request to a server using the standard fetch API.
|
|
23
|
+
* Will redirect to the login page instead if the user needs to log in.
|
|
24
|
+
*
|
|
25
|
+
* @param url The URL for the request
|
|
26
|
+
* @param options Additional request options.
|
|
27
|
+
* @returns The fetch response
|
|
28
|
+
*/
|
|
29
|
+
export async function authFetch(url: string, options?: RequestInit) {
|
|
30
|
+
const headers = new Headers(options?.headers)
|
|
31
|
+
|
|
32
|
+
// Set the authorization header with the Feathers Auth token
|
|
33
|
+
headers.set('Authorization', await auth.getHeader())
|
|
34
|
+
|
|
35
|
+
return fetch(url, {
|
|
36
|
+
...options,
|
|
37
|
+
headers,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createAutomerge } from '@feathersdev/automerge'
|
|
2
|
+
import { auth } from './auth.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The Feathers Automerge client. Use it to retrieve the document
|
|
6
|
+
* for your application with `automerge.find()`.
|
|
7
|
+
*/
|
|
8
|
+
export const automerge = createAutomerge(auth)
|
|
9
|
+
|
|
10
|
+
interface AppData {
|
|
11
|
+
counter: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function getHandle() {
|
|
15
|
+
return automerge.find<AppData>()
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { authFetch } from './auth.js'
|
|
2
|
+
import { getHandle } from './automerge.js'
|
|
3
|
+
import './style.css'
|
|
4
|
+
|
|
5
|
+
getHandle().then((handle) => {
|
|
6
|
+
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
|
|
7
|
+
<div>
|
|
8
|
+
<div class="wrapper">
|
|
9
|
+
<h1>Feathers Auth + TypeScript demo</h1>
|
|
10
|
+
<p>Our community counter is</p>
|
|
11
|
+
<h2 id="counter">...</h2>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
handle.on('change', ({ doc }) => {
|
|
17
|
+
document.getElementById('message')!.innerHTML = doc.counter.toString()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
handle.change((doc) => {
|
|
21
|
+
doc.counter = (doc.counter || 0) + 1
|
|
22
|
+
})
|
|
23
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
a {
|
|
17
|
+
font-weight: 500;
|
|
18
|
+
color: #646cff;
|
|
19
|
+
text-decoration: inherit;
|
|
20
|
+
}
|
|
21
|
+
a:hover {
|
|
22
|
+
color: #535bf2;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
body {
|
|
26
|
+
margin: 0;
|
|
27
|
+
display: flex;
|
|
28
|
+
place-items: center;
|
|
29
|
+
min-width: 320px;
|
|
30
|
+
min-height: 100vh;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h1 {
|
|
34
|
+
font-size: 3.2em;
|
|
35
|
+
line-height: 1.1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#app {
|
|
39
|
+
max-width: 1280px;
|
|
40
|
+
margin: 0 auto;
|
|
41
|
+
padding: 2rem;
|
|
42
|
+
text-align: center;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.logo {
|
|
46
|
+
height: 6em;
|
|
47
|
+
padding: 1.5em;
|
|
48
|
+
will-change: filter;
|
|
49
|
+
transition: filter 300ms;
|
|
50
|
+
}
|
|
51
|
+
.logo:hover {
|
|
52
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
53
|
+
}
|
|
54
|
+
.logo.vanilla:hover {
|
|
55
|
+
filter: drop-shadow(0 0 2em #3178c6aa);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.card {
|
|
59
|
+
padding: 2em;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.read-the-docs {
|
|
63
|
+
color: #888;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
button {
|
|
67
|
+
border-radius: 8px;
|
|
68
|
+
border: 1px solid transparent;
|
|
69
|
+
padding: 0.6em 1.2em;
|
|
70
|
+
font-size: 1em;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
font-family: inherit;
|
|
73
|
+
background-color: #1a1a1a;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
transition: border-color 0.25s;
|
|
76
|
+
}
|
|
77
|
+
button:hover {
|
|
78
|
+
border-color: #646cff;
|
|
79
|
+
}
|
|
80
|
+
button:focus,
|
|
81
|
+
button:focus-visible {
|
|
82
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (prefers-color-scheme: light) {
|
|
86
|
+
:root {
|
|
87
|
+
color: #213547;
|
|
88
|
+
background-color: #ffffff;
|
|
89
|
+
}
|
|
90
|
+
a:hover {
|
|
91
|
+
color: #747bff;
|
|
92
|
+
}
|
|
93
|
+
button {
|
|
94
|
+
background-color: #f9f9f9;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
|
|
16
|
+
/* Linting */
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true
|
|
21
|
+
},
|
|
22
|
+
"include": ["src"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# vue-app
|
|
2
|
+
|
|
3
|
+
This template should help get you started developing with Vue 3 in Vite.
|
|
4
|
+
|
|
5
|
+
## Recommended IDE Setup
|
|
6
|
+
|
|
7
|
+
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
8
|
+
|
|
9
|
+
## Type Support for `.vue` Imports in TS
|
|
10
|
+
|
|
11
|
+
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
12
|
+
|
|
13
|
+
## Customize configuration
|
|
14
|
+
|
|
15
|
+
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
16
|
+
|
|
17
|
+
## Project Setup
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Compile and Hot-Reload for Development
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm run dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Type-Check, Compile and Minify for Production
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm run build
|
|
33
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<link rel="icon" href="/favicon.ico">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Vite App</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.ts"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-Frontend",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite --port 3000",
|
|
8
|
+
"build": "run-p type-check \"build-only {@}\" --",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"build-only": "vite build",
|
|
11
|
+
"type-check": "vue-tsc --build --force"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@feathersdev/auth": "^0.10.0",
|
|
15
|
+
"@feathersdev/automerge": "^0.10.0",
|
|
16
|
+
"vue": "^3.5.12"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@tsconfig/node20": "^20.1.4",
|
|
20
|
+
"@types/node": "^22.9.0",
|
|
21
|
+
"@vitejs/plugin-vue": "^5.2.0",
|
|
22
|
+
"@vue/tsconfig": "^0.6.0",
|
|
23
|
+
"npm-run-all2": "^7.0.1",
|
|
24
|
+
"typescript": "~5.6.3",
|
|
25
|
+
"vite": "^5.4.11",
|
|
26
|
+
"vite-plugin-wasm": "^3.4.1",
|
|
27
|
+
"vue-tsc": "^2.1.10"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { automerge } from './auth'
|
|
4
|
+
|
|
5
|
+
const handle = await automerge.find<{ counter: number }>()
|
|
6
|
+
const counter = ref<number>(0)
|
|
7
|
+
|
|
8
|
+
handle.on('change', ({ doc }) => {
|
|
9
|
+
counter.value = doc.counter
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
async function incrementCounter() {
|
|
13
|
+
handle.change((doc) => {
|
|
14
|
+
doc.counter = (doc.counter || 0) + 1
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<header>
|
|
21
|
+
<div class="wrapper">
|
|
22
|
+
<h1>feathers.dev Vue demo</h1>
|
|
23
|
+
<p>Our community counter is:</p>
|
|
24
|
+
<h2><strong>{{ counter }}</strong></h2>
|
|
25
|
+
<button @click="incrementCounter">
|
|
26
|
+
Increment
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
</header>
|
|
30
|
+
</template>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* color palette from <https://github.com/vuejs/theme> */
|
|
2
|
+
:root {
|
|
3
|
+
--vt-c-white: #ffffff;
|
|
4
|
+
--vt-c-white-soft: #f8f8f8;
|
|
5
|
+
--vt-c-white-mute: #f2f2f2;
|
|
6
|
+
|
|
7
|
+
--vt-c-black: #181818;
|
|
8
|
+
--vt-c-black-soft: #222222;
|
|
9
|
+
--vt-c-black-mute: #282828;
|
|
10
|
+
|
|
11
|
+
--vt-c-indigo: #2c3e50;
|
|
12
|
+
|
|
13
|
+
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
|
14
|
+
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
|
15
|
+
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
|
16
|
+
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
|
17
|
+
|
|
18
|
+
--vt-c-text-light-1: var(--vt-c-indigo);
|
|
19
|
+
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
|
20
|
+
--vt-c-text-dark-1: var(--vt-c-white);
|
|
21
|
+
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* semantic color variables for this project */
|
|
25
|
+
:root {
|
|
26
|
+
--color-background: var(--vt-c-white);
|
|
27
|
+
--color-background-soft: var(--vt-c-white-soft);
|
|
28
|
+
--color-background-mute: var(--vt-c-white-mute);
|
|
29
|
+
|
|
30
|
+
--color-border: var(--vt-c-divider-light-2);
|
|
31
|
+
--color-border-hover: var(--vt-c-divider-light-1);
|
|
32
|
+
|
|
33
|
+
--color-heading: var(--vt-c-text-light-1);
|
|
34
|
+
--color-text: var(--vt-c-text-light-1);
|
|
35
|
+
|
|
36
|
+
--section-gap: 160px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media (prefers-color-scheme: dark) {
|
|
40
|
+
:root {
|
|
41
|
+
--color-background: var(--vt-c-black);
|
|
42
|
+
--color-background-soft: var(--vt-c-black-soft);
|
|
43
|
+
--color-background-mute: var(--vt-c-black-mute);
|
|
44
|
+
|
|
45
|
+
--color-border: var(--vt-c-divider-dark-2);
|
|
46
|
+
--color-border-hover: var(--vt-c-divider-dark-1);
|
|
47
|
+
|
|
48
|
+
--color-heading: var(--vt-c-text-dark-1);
|
|
49
|
+
--color-text: var(--vt-c-text-dark-2);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
*,
|
|
54
|
+
*::before,
|
|
55
|
+
*::after {
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
margin: 0;
|
|
58
|
+
font-weight: normal;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
body {
|
|
62
|
+
min-height: 100vh;
|
|
63
|
+
color: var(--color-text);
|
|
64
|
+
background: var(--color-background);
|
|
65
|
+
transition:
|
|
66
|
+
color 0.5s,
|
|
67
|
+
background-color 0.5s;
|
|
68
|
+
line-height: 1.6;
|
|
69
|
+
font-family:
|
|
70
|
+
Inter,
|
|
71
|
+
-apple-system,
|
|
72
|
+
BlinkMacSystemFont,
|
|
73
|
+
'Segoe UI',
|
|
74
|
+
Roboto,
|
|
75
|
+
Oxygen,
|
|
76
|
+
Ubuntu,
|
|
77
|
+
Cantarell,
|
|
78
|
+
'Fira Sans',
|
|
79
|
+
'Droid Sans',
|
|
80
|
+
'Helvetica Neue',
|
|
81
|
+
sans-serif;
|
|
82
|
+
font-size: 15px;
|
|
83
|
+
text-rendering: optimizeLegibility;
|
|
84
|
+
-webkit-font-smoothing: antialiased;
|
|
85
|
+
-moz-osx-font-smoothing: grayscale;
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@import './base.css';
|
|
2
|
+
|
|
3
|
+
#app {
|
|
4
|
+
max-width: 1280px;
|
|
5
|
+
margin: 0 auto;
|
|
6
|
+
padding: 2rem;
|
|
7
|
+
font-weight: normal;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
a,
|
|
11
|
+
.green {
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
color: hsla(160, 100%, 37%, 1);
|
|
14
|
+
transition: 0.4s;
|
|
15
|
+
padding: 3px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (hover: hover) {
|
|
19
|
+
a:hover {
|
|
20
|
+
background-color: hsla(160, 100%, 37%, 0.2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (min-width: 1024px) {
|
|
25
|
+
body {
|
|
26
|
+
display: flex;
|
|
27
|
+
place-items: center;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#app {
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-template-columns: 1fr 1fr;
|
|
33
|
+
padding: 0 2rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createClient } from '@feathersdev/auth'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is your public application id
|
|
5
|
+
*/
|
|
6
|
+
export const appId = '<your-app-id>'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The Feathers auth client instance. You can use it to get a token,
|
|
10
|
+
* retrieve the current user and to log in and out.
|
|
11
|
+
*/
|
|
12
|
+
export const auth = createClient({
|
|
13
|
+
appId,
|
|
14
|
+
onLoginRequired: async (error) => {
|
|
15
|
+
// Redirect to login page whenever a login is required
|
|
16
|
+
// You can also do other things here like show a modal before redirecting
|
|
17
|
+
window.location.href = await auth.getLoginUrl(error)
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Make an authenticated request to a server using the standard fetch API.
|
|
23
|
+
* Will redirect to the login page instead if the user needs to log in.
|
|
24
|
+
*
|
|
25
|
+
* @param url The URL for the request
|
|
26
|
+
* @param options Additional request options.
|
|
27
|
+
* @returns The fetch response
|
|
28
|
+
*/
|
|
29
|
+
export async function authFetch(url: string, options?: RequestInit) {
|
|
30
|
+
const headers = new Headers(options?.headers)
|
|
31
|
+
|
|
32
|
+
// Set the authorization header with the Feathers Auth token
|
|
33
|
+
headers.set('Authorization', await auth.getHeader())
|
|
34
|
+
|
|
35
|
+
return fetch(url, {
|
|
36
|
+
...options,
|
|
37
|
+
headers,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createAutomerge } from '@feathersdev/automerge'
|
|
2
|
+
import { auth } from './auth.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The Feathers Automerge client. Use it to retrieve the document
|
|
6
|
+
* for your application with `automerge.find()`.
|
|
7
|
+
*/
|
|
8
|
+
export const automerge = createAutomerge(auth)
|
|
9
|
+
|
|
10
|
+
interface AppData {
|
|
11
|
+
counter: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function getHandle() {
|
|
15
|
+
return automerge.find<AppData>()
|
|
16
|
+
}
|