@bardioc/create-bardioc-app 0.4.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/LICENSE +5 -0
- package/README.md +105 -0
- package/bin/create.mjs +76 -0
- package/package.json +45 -0
- package/src/scaffold.d.ts +50 -0
- package/src/scaffold.js +379 -0
- package/templates/_base/.changeset/README.md +17 -0
- package/templates/_base/.changeset/config.json +12 -0
- package/templates/_base/.claude/commands/changeset-app.md +104 -0
- package/templates/_base/.claude/commands/refresh-bundle.md +101 -0
- package/templates/_base/README.md +89 -0
- package/templates/_base/public/app-manifest.json +10 -0
- package/templates/_base/scripts/stamp-manifest.mjs +17 -0
- package/templates/_opt-link/_npmrc +2 -0
- package/templates/_opt-link/pnpm-workspace.yaml +3 -0
- package/templates/_opt-link/scripts/link-source.mjs +188 -0
- package/templates/_opt-pipeline/bitbucket-pipelines.yml +100 -0
- package/templates/angular/.env.example +5 -0
- package/templates/angular/_gitignore +7 -0
- package/templates/angular/angular.json +64 -0
- package/templates/angular/package.json +49 -0
- package/templates/angular/postcss.config.mjs +5 -0
- package/templates/angular/public/icon.svg +1 -0
- package/templates/angular/public/runtime-env.js +1 -0
- package/templates/angular/scripts/dev-auth-proxy.mjs +92 -0
- package/templates/angular/scripts/sync-runtime-env.mjs +89 -0
- package/templates/angular/src/app/app.component.ts +181 -0
- package/templates/angular/src/app/bardioc-bridge.ts +5 -0
- package/templates/angular/src/app/bardioc.token.ts +4 -0
- package/templates/angular/src/index.html +15 -0
- package/templates/angular/src/main.ts +82 -0
- package/templates/angular/src/runtime-env.ts +17 -0
- package/templates/angular/src/styles.css +258 -0
- package/templates/angular/src/vite-env.d.ts +10 -0
- package/templates/angular/tsconfig.json +27 -0
- package/templates/manifest.json +13 -0
- package/templates/nextjs/.env.example +8 -0
- package/templates/nextjs/_gitignore +7 -0
- package/templates/nextjs/app/globals.css +75 -0
- package/templates/nextjs/app/layout.tsx +17 -0
- package/templates/nextjs/app/page.tsx +222 -0
- package/templates/nextjs/app/proxy/route.ts +85 -0
- package/templates/nextjs/global.d.ts +1 -0
- package/templates/nextjs/next-env.d.ts +5 -0
- package/templates/nextjs/next.config.ts +21 -0
- package/templates/nextjs/package.json +32 -0
- package/templates/nextjs/postcss.config.mjs +5 -0
- package/templates/nextjs/public/icon.svg +1 -0
- package/templates/nextjs/tailwind.config.ts +10 -0
- package/templates/nextjs/tsconfig.json +27 -0
- package/templates/preact/.env.example +13 -0
- package/templates/preact/_gitignore +9 -0
- package/templates/preact/index.html +13 -0
- package/templates/preact/package.json +32 -0
- package/templates/preact/public/icon.svg +1 -0
- package/templates/preact/src/App.tsx +139 -0
- package/templates/preact/src/index.css +76 -0
- package/templates/preact/src/main.tsx +46 -0
- package/templates/preact/src/vite-env.d.ts +11 -0
- package/templates/preact/tsconfig.json +19 -0
- package/templates/preact/vite.config.ts +17 -0
- package/templates/solid/.env.example +13 -0
- package/templates/solid/_gitignore +9 -0
- package/templates/solid/index.html +13 -0
- package/templates/solid/package.json +32 -0
- package/templates/solid/public/icon.svg +1 -0
- package/templates/solid/src/App.tsx +150 -0
- package/templates/solid/src/bardioc-sdk.tsx +33 -0
- package/templates/solid/src/index.css +76 -0
- package/templates/solid/src/main.tsx +50 -0
- package/templates/solid/src/vite-env.d.ts +11 -0
- package/templates/solid/tsconfig.json +20 -0
- package/templates/solid/vite.config.ts +17 -0
- package/templates/svelte/.env.example +5 -0
- package/templates/svelte/_gitignore +6 -0
- package/templates/svelte/index.html +13 -0
- package/templates/svelte/package.json +32 -0
- package/templates/svelte/public/icon.svg +1 -0
- package/templates/svelte/src/App.svelte +135 -0
- package/templates/svelte/src/index.css +76 -0
- package/templates/svelte/src/main.ts +42 -0
- package/templates/svelte/src/vite-env.d.ts +11 -0
- package/templates/svelte/tsconfig.json +13 -0
- package/templates/svelte/vite.config.ts +17 -0
- package/templates/vite/.env.example +14 -0
- package/templates/vite/CLAUDE.md +114 -0
- package/templates/vite/_gitignore +9 -0
- package/templates/vite/index.html +13 -0
- package/templates/vite/package.json +34 -0
- package/templates/vite/public/icon.svg +1 -0
- package/templates/vite/src/App.tsx +141 -0
- package/templates/vite/src/index.css +76 -0
- package/templates/vite/src/main.tsx +44 -0
- package/templates/vite/src/vite-env.d.ts +11 -0
- package/templates/vite/tsconfig.json +18 -0
- package/templates/vite/vite.config.ts +17 -0
- package/templates/vue/.env.example +5 -0
- package/templates/vue/_gitignore +6 -0
- package/templates/vue/index.html +13 -0
- package/templates/vue/package.json +32 -0
- package/templates/vue/public/icon.svg +1 -0
- package/templates/vue/src/App.vue +127 -0
- package/templates/vue/src/bardioc-sdk.ts +23 -0
- package/templates/vue/src/index.css +76 -0
- package/templates/vue/src/main.ts +43 -0
- package/templates/vue/src/vite-env.d.ts +17 -0
- package/templates/vue/tsconfig.json +26 -0
- package/templates/vue/vite.config.ts +17 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
html,
|
|
8
|
+
body,
|
|
9
|
+
#app {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
height: 100%;
|
|
13
|
+
width: 100%;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:root {
|
|
18
|
+
--background: oklch(17.88% 0.0075 229.38);
|
|
19
|
+
--foreground: oklch(98.69% 0.0093 99.98);
|
|
20
|
+
--muted-foreground: oklch(86.03% 0.0056 95.11);
|
|
21
|
+
--border: oklch(1 0 0 / 10%);
|
|
22
|
+
--primary: oklch(97.02% 0 0);
|
|
23
|
+
--primary-foreground: oklch(36.94% 0.0053 236.64);
|
|
24
|
+
--destructive: oklch(68.04% 0.1386 21.38);
|
|
25
|
+
--ring: oklch(79.43% 0.0084 98.91);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
body {
|
|
29
|
+
background: var(--background);
|
|
30
|
+
color: var(--foreground);
|
|
31
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
code {
|
|
35
|
+
font-family: inherit;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.bg-background {
|
|
39
|
+
background-color: var(--background);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.text-foreground {
|
|
43
|
+
color: var(--foreground);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.text-muted-foreground {
|
|
47
|
+
color: var(--muted-foreground);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.border-border {
|
|
51
|
+
border-color: var(--border);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bg-primary {
|
|
55
|
+
background-color: var(--primary);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.text-primary-foreground {
|
|
59
|
+
color: var(--primary-foreground);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.text-destructive {
|
|
63
|
+
color: var(--destructive);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.focus\:ring-ring:focus {
|
|
67
|
+
--tw-ring-color: var(--ring);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.hover\:bg-primary\/90:hover {
|
|
71
|
+
background-color: oklch(from var(--primary) calc(l * 0.9) c h);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.hover\:text-foreground:hover {
|
|
75
|
+
color: var(--foreground);
|
|
76
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureDevAuthSession,
|
|
3
|
+
installDevBridge,
|
|
4
|
+
isDevStandalone,
|
|
5
|
+
isInsideIframe,
|
|
6
|
+
} from '@bardioc/app-sdk/dev';
|
|
7
|
+
import { createHostBridge } from '@bardioc/app-sdk';
|
|
8
|
+
import { mount } from 'svelte';
|
|
9
|
+
import App from './App.svelte';
|
|
10
|
+
import './index.css';
|
|
11
|
+
|
|
12
|
+
const APP_NAME = import.meta.env.VITE_APP_NAME?.trim();
|
|
13
|
+
const APP_ID = import.meta.env.VITE_APP_ID?.trim();
|
|
14
|
+
const standaloneDevAuthEnabled = import.meta.env.DEV && import.meta.env.VITE_ENABLE_DEV_AUTH === 'true';
|
|
15
|
+
|
|
16
|
+
if (!APP_NAME) {
|
|
17
|
+
throw new Error('Missing VITE_APP_NAME for runtime');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const insideIframe = isInsideIframe();
|
|
21
|
+
const devStandalone = standaloneDevAuthEnabled && isDevStandalone();
|
|
22
|
+
const useSdkProvider = insideIframe || devStandalone;
|
|
23
|
+
|
|
24
|
+
if (useSdkProvider && !APP_ID) {
|
|
25
|
+
throw new Error('Missing VITE_APP_ID for SDK runtime');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function bootstrap() {
|
|
29
|
+
if (devStandalone) {
|
|
30
|
+
await ensureDevAuthSession({ appId: APP_ID, appName: APP_NAME });
|
|
31
|
+
installDevBridge({ appId: APP_ID, appName: APP_NAME, debug: false });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const bridge = useSdkProvider ? createHostBridge({ appId: APP_ID! }) : null;
|
|
35
|
+
|
|
36
|
+
mount(App, {
|
|
37
|
+
target: document.getElementById('app')!,
|
|
38
|
+
props: { bridge },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
bootstrap();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noEmit": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"verbatimModuleSyntax": true,
|
|
10
|
+
"isolatedModules": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts", "src/**/*.svelte"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { bardiocApp, bardiocDevAuth } from '@bardioc/app-sdk/vite';
|
|
2
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4
|
+
import { defineConfig, loadEnv } from 'vite';
|
|
5
|
+
|
|
6
|
+
export default defineConfig(({ mode }) => {
|
|
7
|
+
const env = loadEnv(mode, __dirname, '');
|
|
8
|
+
const appName = env.VITE_APP_NAME?.trim();
|
|
9
|
+
|
|
10
|
+
if (!appName) {
|
|
11
|
+
throw new Error('Missing VITE_APP_NAME for Vite config');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
plugins: [bardiocDevAuth({ appName }), svelte(), bardiocApp({ appName, port: {{PORT}} }), tailwindcss()],
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Hosted app slug used by local runtime/dev-auth wiring.
|
|
2
|
+
VITE_APP_NAME={{APP_NAME}}
|
|
3
|
+
|
|
4
|
+
# Get this from the BardiocOS AppStore after registering your app.
|
|
5
|
+
# Required for token exchange
|
|
6
|
+
VITE_APP_ID=your-app-client-id-here
|
|
7
|
+
|
|
8
|
+
# Opt into the host-backed standalone dev session when running outside the host iframe.
|
|
9
|
+
VITE_ENABLE_DEV_AUTH=false
|
|
10
|
+
|
|
11
|
+
# Required host URL for standalone dev auth. Run `bardioc login` once, then
|
|
12
|
+
# `pnpm dev` will refresh DEV_SESSION_KEY automatically before Vite starts.
|
|
13
|
+
DEV_AUTH_HOST_URL=
|
|
14
|
+
DEV_SESSION_KEY=
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# {{DISPLAY_NAME}}
|
|
2
|
+
|
|
3
|
+
Bardioc app. Vite + React 19 + TypeScript 6 + @bardioc/app-sdk.
|
|
4
|
+
|
|
5
|
+
**Global rules apply.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Code style
|
|
10
|
+
|
|
11
|
+
### Comments
|
|
12
|
+
|
|
13
|
+
- Single-line: `// WHY, not WHAT`
|
|
14
|
+
- No `/* */` blocks
|
|
15
|
+
- No task refs
|
|
16
|
+
|
|
17
|
+
### Constraints
|
|
18
|
+
|
|
19
|
+
- 600 LOC max per file
|
|
20
|
+
- Constants: `SCREAMING_SNAKE_CASE`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Development
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm dev # http://localhost:{{PORT}}
|
|
28
|
+
pnpm dev:live # public tunnel
|
|
29
|
+
pnpm build # → dist/
|
|
30
|
+
pnpm bundle # → {{APP_NAME}}.zip
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`.env`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
VITE_APP_NAME={{APP_NAME}}
|
|
37
|
+
VITE_APP_ID=your-app-id
|
|
38
|
+
VITE_ENABLE_DEV_AUTH=true
|
|
39
|
+
DEV_AUTH_HOST_URL=https://your-host
|
|
40
|
+
DEV_SESSION_KEY=
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Standalone host-backed dev sessions are opt-in. Without `VITE_ENABLE_DEV_AUTH=true`, local `pnpm dev` runs outside the host iframe as a preview shell only and will not call the dev-session flow. Run `bardioc login` once, then `pnpm dev` will mint and refresh `DEV_SESSION_KEY` automatically.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## SDK API
|
|
48
|
+
|
|
49
|
+
**Graph API**
|
|
50
|
+
Access the graph database via `bridge.transport.graph.*`:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const bridge = useSdk();
|
|
54
|
+
await bridge.transport.graph.get('node-id');
|
|
55
|
+
await bridge.transport.graph.gremlin('node-id', 'g.V().limit(10)');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**OS API**
|
|
59
|
+
Access OS resources via `bridge.transport.os.*`:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
await bridge.transport.os.profile.get();
|
|
63
|
+
await bridge.transport.os.organization.getStructure();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Notifications**
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const notify = useNotify();
|
|
70
|
+
notify('Done', 'success');
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Provider** (only in iframe)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const isInsideIframe = window.parent !== window;
|
|
77
|
+
{isInsideIframe && (
|
|
78
|
+
<AppSdkProvider appId={APP_ID}><App /></AppSdkProvider>
|
|
79
|
+
)}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Anti-patterns
|
|
85
|
+
|
|
86
|
+
**❌ bridge.notify in components**
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
function MyComponent() {
|
|
90
|
+
const bridge = useSdk();
|
|
91
|
+
bridge.notify('Done', 'success');
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**✅ useNotify hook**
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
function MyComponent() {
|
|
99
|
+
const notify = useNotify();
|
|
100
|
+
notify('Done', 'success');
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**❌ provider outside iframe**
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
<AppSdkProvider appId={APP_ID}><App /></AppSdkProvider>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**✅ conditional rendering**
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
{isInsideIframe && <AppSdkProvider appId={APP_ID}><App /></AppSdkProvider>}
|
|
114
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="dark" style="height: 100%; margin: 0">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>{{DISPLAY_NAME}}</title>
|
|
7
|
+
<link rel="stylesheet" href="/fonts/bardioc-fonts.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body style="height: 100%; margin: 0">
|
|
10
|
+
<div id="root" style="height: 100%"></div>
|
|
11
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{APP_NAME}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "bardioc-dev-session -- vite",
|
|
8
|
+
"dev:live": "BARDIOC_TUNNEL=1 bardioc-dev-session -- vite",
|
|
9
|
+
"build": "tsc && vite build && node scripts/stamp-manifest.mjs dist",
|
|
10
|
+
"bundle": "tsc && vite build && node scripts/stamp-manifest.mjs dist && cd dist && zip -r ../{{APP_NAME}}.zip .",
|
|
11
|
+
"preview": "vite preview",
|
|
12
|
+
"check-types": "tsc --noEmit",
|
|
13
|
+
"changeset": "changeset",
|
|
14
|
+
"release:status": "changeset status --verbose",
|
|
15
|
+
"release:version": "changeset version && pnpm install --lockfile-only",
|
|
16
|
+
"release:publish": "changeset publish"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@bardioc/app-sdk": "latest",
|
|
20
|
+
"react": "19.2.6",
|
|
21
|
+
"react-dom": "19.2.6"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@changesets/cli": "^2.31.0",
|
|
25
|
+
"@tailwindcss/vite": "^4.3.0",
|
|
26
|
+
"@types/node": "^22.19.19",
|
|
27
|
+
"@types/react": "^19.2.14",
|
|
28
|
+
"@types/react-dom": "^19.2.3",
|
|
29
|
+
"@vitejs/plugin-react": "5.2.0",
|
|
30
|
+
"tailwindcss": "4.3.0",
|
|
31
|
+
"typescript": "6.0.3",
|
|
32
|
+
"vite": "8.0.13"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="15.3012" x2="-2.25993" y1="1.77049" y2="12.9254"><stop offset=".4898" stop-color="#c084fc"/><stop offset="1" stop-color="#9333ea"/></linearGradient><path d="m14.3984 3.35791c1.9618.00013 3.5514 1.59021 3.5518 3.55176v8.08593c0 1.9602-1.5896 3.5507-3.5518 3.5508h-8.84567c-1.96194-.0002-3.55273-1.5909-3.55273-3.5527v-8.08403c.00042-1.96151 1.59105-3.55156 3.55273-3.55176zm4.5186 12.18069c.0121-.1019.0221-.2048.0273-.3086.004-.0776.0059-.1559.0059-.2344v-8.08593c0-.18616-.0124-.36951-.0342-.54981.0218.18056.0352.36435.0352.55078v8.08496c0 .1837-.013.3649-.0342.543zm-17.8672.1318c-.03282-.2205-.0498-.4471-.0498-.6767 0 .2298.01694.456.0498.6767zm.00098-9.44042c-.03187.21266-.0494.43015-.05078.65137.00138-.22122.01891-.43871.05078-.65137zm3.60254-3.7832c.0723-.01449.14526-.02707.21875-.03809-.07349.01102-.14645.0236-.21875.03809zm.66504-.08301c-.14548.00737-.2891.02225-.43066.04297.14156-.02072.28518-.0356.43066-.04297zm9.31444 0c.1368.00693.272.02032.4053.03906-.1332-.01872-.2686-.03213-.4053-.03906zm-9.76171 17.13183c-.06758-.0101-.1346-.0221-.20117-.0352.06658.0131.13359.0251.20117.0352zm-2.92578-1.7256c-.0288-.0374-.0573-.075-.08496-.1133.02766.0383.05616.0759.08496.1133zm16.82719-12.11912c.0144.05023.0292.10044.042.15137-.0128-.05093-.0276-.10114-.042-.15137zm.0449.16504c.0166.06713.0313.13485.0449.20312-.0135-.06826-.0284-.13599-.0449-.20312zm.0644.31152c.006.03443.0124.06883.0176.10352-.0052-.03469-.0116-.06909-.0176-.10352zm-17.81246 9.65526c-.00653-.0373-.01393-.0746-.01954-.1123.00561.0377.01301.075.01954.1123zm17.57126-10.5244c.0165.04237.0326.08495.0479.12793-.0153-.04298-.0314-.08556-.0479-.12793zm-14.12888-2.78027c.04696-.01099.09409-.02174.1416-.03125-.04751.00952-.09464.02026-.1416.03125z" fill="url(#a)"/><g opacity=".31"><path d="m3.24438 5.75049v7.11941c0 1.4408.99919 2.6095 2.23108 2.6095h9.00044c1.2319 0 2.231-1.1687 2.231-2.6095v-7.11941z" fill="#fff" fill-opacity=".6"/></g><rect x="6" y="7" width="8" height="1.5" rx="0.75" fill="#eddcff"/><rect x="6" y="10" width="8" height="1.5" rx="0.75" fill="#eddcff"/><rect x="6" y="13" width="5" height="1.5" rx="0.75" fill="#eddcff"/></svg>
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
2
|
+
import { useSdk, useNotify } from '@bardioc/app-sdk/react';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
type ResultState =
|
|
6
|
+
| { status: 'idle' }
|
|
7
|
+
| { status: 'loading'; request: string }
|
|
8
|
+
| { status: 'success'; request: string; data: unknown }
|
|
9
|
+
| { status: 'error'; request: string; message: string };
|
|
10
|
+
|
|
11
|
+
function SdkDemo() {
|
|
12
|
+
const bridge = useSdk();
|
|
13
|
+
const notify = useNotify();
|
|
14
|
+
const [result, setResult] = useState<ResultState>({ status: 'idle' });
|
|
15
|
+
const [running, setRunning] = useState(false);
|
|
16
|
+
|
|
17
|
+
async function runGetProfile() {
|
|
18
|
+
if (running) return;
|
|
19
|
+
setRunning(true);
|
|
20
|
+
|
|
21
|
+
const request = 'transport.os.profile.get()';
|
|
22
|
+
setResult({ status: 'loading', request });
|
|
23
|
+
|
|
24
|
+
const startTime = Date.now();
|
|
25
|
+
notify('Getting user profile', 'info');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const data = await bridge.transport.os.profile.get();
|
|
29
|
+
|
|
30
|
+
const duration = Date.now() - startTime;
|
|
31
|
+
notify(`Profile loaded (${duration}ms)`, 'success');
|
|
32
|
+
setResult({ status: 'success', request, data });
|
|
33
|
+
} catch (err) {
|
|
34
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
35
|
+
notify(`Failed: ${message}`, 'error');
|
|
36
|
+
setResult({ status: 'error', request, message });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setRunning(false);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function handleNotify() {
|
|
43
|
+
notify('Hello from {{DISPLAY_NAME}}', 'info');
|
|
44
|
+
setResult({
|
|
45
|
+
status: 'success',
|
|
46
|
+
request: 'SDK_NOTIFY',
|
|
47
|
+
data: { ok: true, message: 'Notification sent to OS' },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-3 p-4">
|
|
53
|
+
<div className="flex flex-col gap-1">
|
|
54
|
+
<h1 className="m-0 text-2xl font-semibold">Hello Bardioc App</h1>
|
|
55
|
+
<p className="text-muted-foreground m-0 text-xs leading-5">
|
|
56
|
+
Minimal hosted-app demo for API transport and SDK APIs.
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div className="flex flex-wrap gap-2">
|
|
61
|
+
<button
|
|
62
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 rounded px-3 py-1 text-xs font-medium disabled:cursor-not-allowed"
|
|
63
|
+
onClick={() => void runGetProfile()}
|
|
64
|
+
disabled={running}
|
|
65
|
+
>
|
|
66
|
+
Get Profile
|
|
67
|
+
</button>
|
|
68
|
+
<button
|
|
69
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 rounded px-3 py-1 text-xs font-medium disabled:cursor-not-allowed"
|
|
70
|
+
onClick={handleNotify}
|
|
71
|
+
disabled={running}
|
|
72
|
+
>
|
|
73
|
+
Send Notification OS
|
|
74
|
+
</button>
|
|
75
|
+
<button
|
|
76
|
+
className="border-border text-muted-foreground hover:text-foreground rounded border px-3 py-1 text-xs"
|
|
77
|
+
onClick={() => setResult({ status: 'idle' })}
|
|
78
|
+
disabled={running}
|
|
79
|
+
>
|
|
80
|
+
Clear
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div className="border-border bg-background flex min-h-0 flex-1 flex-col overflow-hidden rounded border">
|
|
85
|
+
{result.status === 'idle' && (
|
|
86
|
+
<div className="text-muted-foreground flex h-full items-center justify-center p-3 text-center text-xs leading-5">
|
|
87
|
+
Run a query to see results. If the host session is missing, the transport route will return 401.
|
|
88
|
+
</div>
|
|
89
|
+
)}
|
|
90
|
+
{result.status === 'loading' && (
|
|
91
|
+
<div className="flex h-full flex-col items-center justify-center gap-2 p-3">
|
|
92
|
+
<div className="text-muted-foreground font-mono text-xs">{result.request}</div>
|
|
93
|
+
<div className="text-muted-foreground text-xs">Loading…</div>
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
{result.status === 'error' && (
|
|
97
|
+
<div className="flex h-full flex-col gap-2 p-3 text-xs">
|
|
98
|
+
{result.request && (
|
|
99
|
+
<div className="text-muted-foreground border-border border-b pb-2 font-mono text-xs">
|
|
100
|
+
{result.request}
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
<div className="text-destructive whitespace-pre-wrap break-all">{result.message}</div>
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
{result.status === 'success' && (
|
|
107
|
+
<div className="flex h-full flex-col gap-0 overflow-hidden">
|
|
108
|
+
<div className="border-border text-muted-foreground shrink-0 border-b px-3 py-1 font-mono text-xs">
|
|
109
|
+
{result.request}
|
|
110
|
+
</div>
|
|
111
|
+
<pre className="text-foreground flex-1 overflow-auto p-3 text-[11px] leading-5">
|
|
112
|
+
{JSON.stringify(result.data, null, 2)}
|
|
113
|
+
</pre>
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function App() {
|
|
122
|
+
const showSdkDemo = isInsideIframe() || (import.meta.env.VITE_ENABLE_DEV_AUTH === 'true' && isDevStandalone());
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div className="bg-background text-foreground min-h-screen">
|
|
126
|
+
{showSdkDemo ? (
|
|
127
|
+
<SdkDemo />
|
|
128
|
+
) : (
|
|
129
|
+
<div className="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-4 p-4">
|
|
130
|
+
<h1 className="m-0 text-2xl font-semibold">Hello Bardioc App</h1>
|
|
131
|
+
<p className="text-muted-foreground m-0 max-w-2xl text-xs leading-5">
|
|
132
|
+
Open this app inside Bardioc OS to use transport requests and send host notifications.
|
|
133
|
+
</p>
|
|
134
|
+
<div className="border-border bg-muted/20 rounded-xl border p-3 text-xs leading-5">
|
|
135
|
+
Outside the host iframe this page is only a local preview shell.
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
html,
|
|
8
|
+
body,
|
|
9
|
+
#root {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
height: 100%;
|
|
13
|
+
width: 100%;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:root {
|
|
18
|
+
--background: oklch(17.88% 0.0075 229.38);
|
|
19
|
+
--foreground: oklch(98.69% 0.0093 99.98);
|
|
20
|
+
--muted-foreground: oklch(86.03% 0.0056 95.11);
|
|
21
|
+
--border: oklch(1 0 0 / 10%);
|
|
22
|
+
--primary: oklch(97.02% 0 0);
|
|
23
|
+
--primary-foreground: oklch(36.94% 0.0053 236.64);
|
|
24
|
+
--destructive: oklch(68.04% 0.1386 21.38);
|
|
25
|
+
--ring: oklch(79.43% 0.0084 98.91);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
body {
|
|
29
|
+
background: var(--background);
|
|
30
|
+
color: var(--foreground);
|
|
31
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
code {
|
|
35
|
+
font-family: inherit;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.bg-background {
|
|
39
|
+
background-color: var(--background);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.text-foreground {
|
|
43
|
+
color: var(--foreground);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.text-muted-foreground {
|
|
47
|
+
color: var(--muted-foreground);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.border-border {
|
|
51
|
+
border-color: var(--border);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bg-primary {
|
|
55
|
+
background-color: var(--primary);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.text-primary-foreground {
|
|
59
|
+
color: var(--primary-foreground);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.text-destructive {
|
|
63
|
+
color: var(--destructive);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.focus\:ring-ring:focus {
|
|
67
|
+
--tw-ring-color: var(--ring);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.hover\:bg-primary\/90:hover {
|
|
71
|
+
background-color: oklch(from var(--primary) calc(l * 0.9) c h);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.hover\:text-foreground:hover {
|
|
75
|
+
color: var(--foreground);
|
|
76
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureDevAuthSession,
|
|
3
|
+
installDevBridge,
|
|
4
|
+
isDevStandalone,
|
|
5
|
+
isInsideIframe,
|
|
6
|
+
} from '@bardioc/app-sdk/dev';
|
|
7
|
+
import { AppSdkProvider } from '@bardioc/app-sdk/react';
|
|
8
|
+
import { StrictMode } from 'react';
|
|
9
|
+
import { createRoot } from 'react-dom/client';
|
|
10
|
+
import { App } from './App';
|
|
11
|
+
import './index.css';
|
|
12
|
+
|
|
13
|
+
const APP_NAME = import.meta.env.VITE_APP_NAME?.trim();
|
|
14
|
+
const APP_ID = import.meta.env.VITE_APP_ID?.trim();
|
|
15
|
+
const standaloneDevAuthEnabled = import.meta.env.DEV && import.meta.env.VITE_ENABLE_DEV_AUTH === 'true';
|
|
16
|
+
|
|
17
|
+
if (!APP_NAME) {
|
|
18
|
+
throw new Error('Missing VITE_APP_NAME for runtime');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const insideIframe = isInsideIframe();
|
|
22
|
+
const devStandalone = standaloneDevAuthEnabled && isDevStandalone();
|
|
23
|
+
const useSdkProvider = insideIframe || devStandalone;
|
|
24
|
+
|
|
25
|
+
if (useSdkProvider && !APP_ID) {
|
|
26
|
+
throw new Error('Missing VITE_APP_ID for SDK runtime');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (devStandalone) {
|
|
30
|
+
await ensureDevAuthSession({ appId: APP_ID, appName: APP_NAME });
|
|
31
|
+
installDevBridge({ appId: APP_ID, appName: APP_NAME, debug: false });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
createRoot(document.getElementById('root')!).render(
|
|
35
|
+
<StrictMode>
|
|
36
|
+
{useSdkProvider ? (
|
|
37
|
+
<AppSdkProvider appId={APP_ID}>
|
|
38
|
+
<App />
|
|
39
|
+
</AppSdkProvider>
|
|
40
|
+
) : (
|
|
41
|
+
<App />
|
|
42
|
+
)}
|
|
43
|
+
</StrictMode>
|
|
44
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { bardiocApp, bardiocDevAuth } from '@bardioc/app-sdk/vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4
|
+
import { defineConfig, loadEnv } from 'vite';
|
|
5
|
+
|
|
6
|
+
export default defineConfig(({ mode }) => {
|
|
7
|
+
const env = loadEnv(mode, __dirname, '');
|
|
8
|
+
const appName = env.VITE_APP_NAME?.trim();
|
|
9
|
+
|
|
10
|
+
if (!appName) {
|
|
11
|
+
throw new Error('Missing VITE_APP_NAME for Vite config');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
plugins: [bardiocDevAuth({ appName }), react(), bardiocApp({ appName, port: {{PORT}} }), tailwindcss()],
|
|
16
|
+
};
|
|
17
|
+
});
|