@geenius/adapters 0.1.0 → 0.3.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/README.md +79 -42
- package/package.json +23 -4
- package/packages/convex/README.md +1 -1
- package/packages/convex/dist/index.cjs +300 -0
- package/packages/convex/dist/index.cjs.map +1 -0
- package/packages/convex/dist/index.d.cts +231 -0
- package/packages/convex/dist/index.d.ts +231 -0
- package/packages/convex/dist/index.js +263 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/README.md +1 -1
- package/packages/react/dist/index.d.mts +106 -0
- package/packages/react/dist/index.d.ts +106 -0
- package/packages/react/dist/index.js +611 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react/dist/index.mjs +570 -0
- package/packages/react/dist/index.mjs.map +1 -0
- package/packages/react-css/README.md +1 -1
- package/packages/react-css/dist/index.cjs +515 -0
- package/packages/react-css/dist/index.cjs.map +1 -0
- package/packages/react-css/dist/index.d.cts +105 -0
- package/packages/react-css/dist/index.d.ts +105 -0
- package/packages/react-css/dist/index.js +467 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/README.md +1 -1
- package/packages/shared/dist/index.d.mts +625 -0
- package/packages/shared/dist/index.d.ts +625 -0
- package/packages/shared/dist/index.js +1567 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/shared/dist/index.mjs +1489 -0
- package/packages/shared/dist/index.mjs.map +1 -0
- package/packages/solidjs/README.md +1 -1
- package/packages/solidjs/dist/index.d.mts +97 -0
- package/packages/solidjs/dist/index.d.ts +97 -0
- package/packages/solidjs/dist/index.js +250 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs/dist/index.mjs +202 -0
- package/packages/solidjs/dist/index.mjs.map +1 -0
- package/packages/solidjs-css/README.md +1 -1
- package/packages/solidjs-css/dist/index.cjs +343 -0
- package/packages/solidjs-css/dist/index.cjs.map +1 -0
- package/packages/solidjs-css/dist/index.d.cts +67 -0
- package/packages/solidjs-css/dist/index.d.ts +67 -0
- package/packages/solidjs-css/dist/index.js +326 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/package.json +0 -42
- package/packages/convex/src/adapter.ts +0 -39
- package/packages/convex/src/index.ts +0 -19
- package/packages/convex/src/mutations.ts +0 -142
- package/packages/convex/src/queries.ts +0 -106
- package/packages/convex/src/schema.ts +0 -54
- package/packages/convex/src/types.ts +0 -20
- package/packages/convex/tsconfig.json +0 -11
- package/packages/convex/tsup.config.ts +0 -10
- package/packages/react/package.json +0 -45
- package/packages/react/src/components/AdapterCard.tsx +0 -49
- package/packages/react/src/components/AdapterConfigForm.tsx +0 -118
- package/packages/react/src/components/AdapterList.tsx +0 -84
- package/packages/react/src/components/AdapterStatusBadge.tsx +0 -30
- package/packages/react/src/components/index.ts +0 -4
- package/packages/react/src/hooks/index.ts +0 -75
- package/packages/react/src/index.tsx +0 -44
- package/packages/react/src/pages/AdapterDetailPage.tsx +0 -133
- package/packages/react/src/pages/AdaptersPage.tsx +0 -111
- package/packages/react/src/pages/index.ts +0 -2
- package/packages/react/src/provider/AdapterProvider.tsx +0 -115
- package/packages/react/src/provider/index.ts +0 -2
- package/packages/react/tsconfig.json +0 -18
- package/packages/react/tsup.config.ts +0 -10
- package/packages/react-css/package.json +0 -44
- package/packages/react-css/src/adapters.css +0 -1576
- package/packages/react-css/src/components/AdapterCard.tsx +0 -34
- package/packages/react-css/src/components/AdapterConfigForm.tsx +0 -63
- package/packages/react-css/src/components/AdapterList.tsx +0 -40
- package/packages/react-css/src/components/AdapterStatusBadge.tsx +0 -21
- package/packages/react-css/src/components/index.ts +0 -4
- package/packages/react-css/src/hooks/index.ts +0 -75
- package/packages/react-css/src/index.tsx +0 -25
- package/packages/react-css/src/pages/AdapterDetailPage.tsx +0 -133
- package/packages/react-css/src/pages/AdaptersPage.tsx +0 -111
- package/packages/react-css/src/pages/index.ts +0 -2
- package/packages/react-css/src/provider/AdapterProvider.tsx +0 -115
- package/packages/react-css/src/provider/index.ts +0 -2
- package/packages/react-css/src/styles.css +0 -494
- package/packages/react-css/tsconfig.json +0 -19
- package/packages/react-css/tsup.config.ts +0 -2
- package/packages/shared/package.json +0 -39
- package/packages/shared/src/__tests__/adapters.test.ts +0 -545
- package/packages/shared/src/admin/index.ts +0 -2
- package/packages/shared/src/admin/interface.ts +0 -34
- package/packages/shared/src/admin/localStorage.ts +0 -109
- package/packages/shared/src/ai/anthropic.ts +0 -123
- package/packages/shared/src/ai/cloudflare-gateway.ts +0 -130
- package/packages/shared/src/ai/gemini.ts +0 -181
- package/packages/shared/src/ai/index.ts +0 -14
- package/packages/shared/src/ai/interface.ts +0 -11
- package/packages/shared/src/ai/localStorage.ts +0 -78
- package/packages/shared/src/ai/ollama.ts +0 -143
- package/packages/shared/src/ai/openai.ts +0 -120
- package/packages/shared/src/ai/vercel-ai.ts +0 -101
- package/packages/shared/src/auth/better-auth.ts +0 -118
- package/packages/shared/src/auth/clerk.ts +0 -151
- package/packages/shared/src/auth/convex-auth.ts +0 -125
- package/packages/shared/src/auth/index.ts +0 -10
- package/packages/shared/src/auth/interface.ts +0 -17
- package/packages/shared/src/auth/localStorage.ts +0 -125
- package/packages/shared/src/auth/supabase-auth.ts +0 -136
- package/packages/shared/src/config.ts +0 -57
- package/packages/shared/src/constants.ts +0 -122
- package/packages/shared/src/db/convex.ts +0 -146
- package/packages/shared/src/db/index.ts +0 -10
- package/packages/shared/src/db/interface.ts +0 -13
- package/packages/shared/src/db/localStorage.ts +0 -91
- package/packages/shared/src/db/mongodb.ts +0 -125
- package/packages/shared/src/db/neon.ts +0 -171
- package/packages/shared/src/db/supabase.ts +0 -158
- package/packages/shared/src/index.ts +0 -117
- package/packages/shared/src/payments/index.ts +0 -4
- package/packages/shared/src/payments/interface.ts +0 -11
- package/packages/shared/src/payments/localStorage.ts +0 -81
- package/packages/shared/src/payments/stripe.ts +0 -177
- package/packages/shared/src/storage/convex.ts +0 -113
- package/packages/shared/src/storage/index.ts +0 -14
- package/packages/shared/src/storage/interface.ts +0 -11
- package/packages/shared/src/storage/localStorage.ts +0 -95
- package/packages/shared/src/storage/minio.ts +0 -47
- package/packages/shared/src/storage/r2.ts +0 -123
- package/packages/shared/src/storage/s3.ts +0 -128
- package/packages/shared/src/storage/supabase-storage.ts +0 -116
- package/packages/shared/src/storage/uploadthing.ts +0 -126
- package/packages/shared/src/styles/adapters.css +0 -494
- package/packages/shared/src/tier-gate.ts +0 -119
- package/packages/shared/src/types.ts +0 -162
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -9
- package/packages/shared/vitest.config.ts +0 -14
- package/packages/solidjs/package.json +0 -44
- package/packages/solidjs/src/components/AdapterCard.tsx +0 -24
- package/packages/solidjs/src/components/AdapterConfigForm.tsx +0 -54
- package/packages/solidjs/src/components/AdapterList.tsx +0 -28
- package/packages/solidjs/src/components/AdapterStatusBadge.tsx +0 -20
- package/packages/solidjs/src/components/index.ts +0 -4
- package/packages/solidjs/src/index.tsx +0 -17
- package/packages/solidjs/src/pages/AdapterDetailPage.tsx +0 -38
- package/packages/solidjs/src/pages/AdaptersPage.tsx +0 -39
- package/packages/solidjs/src/pages/index.ts +0 -2
- package/packages/solidjs/src/primitives/index.ts +0 -78
- package/packages/solidjs/src/provider/AdapterProvider.tsx +0 -62
- package/packages/solidjs/src/provider/index.ts +0 -2
- package/packages/solidjs/tsconfig.json +0 -20
- package/packages/solidjs/tsup.config.ts +0 -10
- package/packages/solidjs-css/package.json +0 -43
- package/packages/solidjs-css/src/adapters.css +0 -1576
- package/packages/solidjs-css/src/components/AdapterCard.tsx +0 -43
- package/packages/solidjs-css/src/components/AdapterConfigForm.tsx +0 -119
- package/packages/solidjs-css/src/components/AdapterList.tsx +0 -68
- package/packages/solidjs-css/src/components/AdapterStatusBadge.tsx +0 -24
- package/packages/solidjs-css/src/components/index.ts +0 -8
- package/packages/solidjs-css/src/index.tsx +0 -30
- package/packages/solidjs-css/src/pages/AdapterDetailPage.tsx +0 -107
- package/packages/solidjs-css/src/pages/AdaptersPage.tsx +0 -94
- package/packages/solidjs-css/src/pages/index.ts +0 -4
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/src/provider/AdapterProvider.tsx +0 -61
- package/packages/solidjs-css/src/provider/index.ts +0 -2
- package/packages/solidjs-css/tsconfig.json +0 -20
- package/packages/solidjs-css/tsup.config.ts +0 -2
- package/pnpm-workspace.yaml +0 -2
- package/tsconfig.json +0 -17
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
// @geenius/adapters — shared types
|
|
2
|
-
// These align with @geenius-auth/shared types where applicable.
|
|
3
|
-
|
|
4
|
-
// ============================================================================
|
|
5
|
-
// Auth types
|
|
6
|
-
// ============================================================================
|
|
7
|
-
|
|
8
|
-
export interface AuthUser {
|
|
9
|
-
id: string
|
|
10
|
-
email?: string
|
|
11
|
-
name?: string
|
|
12
|
-
image?: string
|
|
13
|
-
role?: string
|
|
14
|
-
createdAt?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface AuthSession {
|
|
18
|
-
userId: string
|
|
19
|
-
token?: string
|
|
20
|
-
expiresAt?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// ============================================================================
|
|
24
|
-
// DB types
|
|
25
|
-
// ============================================================================
|
|
26
|
-
|
|
27
|
-
export interface ListOptions {
|
|
28
|
-
limit?: number
|
|
29
|
-
offset?: number
|
|
30
|
-
orderBy?: string
|
|
31
|
-
order?: 'asc' | 'desc'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type QueryOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'contains'
|
|
35
|
-
|
|
36
|
-
export interface QueryCondition {
|
|
37
|
-
field: string
|
|
38
|
-
operator: QueryOperator
|
|
39
|
-
value: unknown
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export type QueryFilter = QueryCondition[]
|
|
43
|
-
|
|
44
|
-
// ============================================================================
|
|
45
|
-
// Payments types
|
|
46
|
-
// ============================================================================
|
|
47
|
-
|
|
48
|
-
export interface Plan {
|
|
49
|
-
id: string
|
|
50
|
-
name: string
|
|
51
|
-
price: number
|
|
52
|
-
currency: string
|
|
53
|
-
interval: 'month' | 'year' | 'one-time'
|
|
54
|
-
features: string[]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface Subscription {
|
|
58
|
-
id: string
|
|
59
|
-
userId: string
|
|
60
|
-
planId: string
|
|
61
|
-
status: 'active' | 'cancelled' | 'past_due' | 'trialing'
|
|
62
|
-
currentPeriodEnd: string
|
|
63
|
-
cancelAtPeriodEnd: boolean
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface CheckoutParams {
|
|
67
|
-
planId: string
|
|
68
|
-
userId: string
|
|
69
|
-
successUrl?: string
|
|
70
|
-
cancelUrl?: string
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface CheckoutResult {
|
|
74
|
-
url: string
|
|
75
|
-
sessionId: string
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ============================================================================
|
|
79
|
-
// AI types
|
|
80
|
-
// ============================================================================
|
|
81
|
-
|
|
82
|
-
export type ChatRole = 'system' | 'user' | 'assistant'
|
|
83
|
-
|
|
84
|
-
export interface ChatMessage {
|
|
85
|
-
role: ChatRole
|
|
86
|
-
content: string
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface AiOptions {
|
|
90
|
-
model?: string
|
|
91
|
-
temperature?: number
|
|
92
|
-
maxTokens?: number
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface ChatResponse {
|
|
96
|
-
content: string
|
|
97
|
-
finishReason: 'stop' | 'length' | 'error'
|
|
98
|
-
usage?: {
|
|
99
|
-
promptTokens: number
|
|
100
|
-
completionTokens: number
|
|
101
|
-
totalTokens: number
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ============================================================================
|
|
106
|
-
// File Storage types
|
|
107
|
-
// ============================================================================
|
|
108
|
-
|
|
109
|
-
export interface StoredFile {
|
|
110
|
-
id: string
|
|
111
|
-
name: string
|
|
112
|
-
path: string
|
|
113
|
-
size: number
|
|
114
|
-
mimeType: string
|
|
115
|
-
url: string
|
|
116
|
-
createdAt: string
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ============================================================================
|
|
120
|
-
// Adapter configuration types
|
|
121
|
-
// ============================================================================
|
|
122
|
-
|
|
123
|
-
export type AdapterDomain = 'db' | 'auth' | 'payments' | 'ai' | 'storage' | 'admin'
|
|
124
|
-
|
|
125
|
-
export interface DomainAdapterConfig {
|
|
126
|
-
provider: string
|
|
127
|
-
apiKey?: string
|
|
128
|
-
baseUrl?: string
|
|
129
|
-
options?: Record<string, unknown>
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export interface AdapterConfig {
|
|
133
|
-
db?: DomainAdapterConfig
|
|
134
|
-
auth?: DomainAdapterConfig
|
|
135
|
-
payments?: DomainAdapterConfig
|
|
136
|
-
ai?: DomainAdapterConfig
|
|
137
|
-
storage?: DomainAdapterConfig
|
|
138
|
-
admin?: DomainAdapterConfig
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ============================================================================
|
|
142
|
-
// Adapter registry types (for UI components)
|
|
143
|
-
// ============================================================================
|
|
144
|
-
|
|
145
|
-
export type AdapterStatusType = 'connected' | 'disconnected' | 'error' | 'initializing'
|
|
146
|
-
|
|
147
|
-
export interface AdapterStatusInfo {
|
|
148
|
-
domain: AdapterDomain
|
|
149
|
-
provider: string
|
|
150
|
-
status: AdapterStatusType
|
|
151
|
-
latency?: number
|
|
152
|
-
lastCheckedAt?: number
|
|
153
|
-
error?: string
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface AdapterRegistryEntry {
|
|
157
|
-
domain: AdapterDomain
|
|
158
|
-
provider: string
|
|
159
|
-
status: AdapterStatusType
|
|
160
|
-
config: DomainAdapterConfig
|
|
161
|
-
connectedAt?: number
|
|
162
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "./dist",
|
|
5
|
-
"rootDir": "./src",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"forceConsistentCasingInFileNames": true,
|
|
9
|
-
"resolveJsonModule": true,
|
|
10
|
-
"isolatedModules": true,
|
|
11
|
-
"target": "ES2022",
|
|
12
|
-
"module": "ESNext",
|
|
13
|
-
"moduleResolution": "bundler"
|
|
14
|
-
},
|
|
15
|
-
"include": [
|
|
16
|
-
"src"
|
|
17
|
-
]
|
|
18
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
coverage: {
|
|
8
|
-
provider: 'v8',
|
|
9
|
-
reporter: ['text', 'json', 'html'],
|
|
10
|
-
include: ['src/**/*.ts'],
|
|
11
|
-
exclude: ['src/**/__tests__/**', 'src/**/*.test.ts'],
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@geenius-adapters/solidjs",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "Geenius Adapters — SolidJS primitives and providers",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": "./dist/index.mjs",
|
|
11
|
-
"require": "./dist/index.js",
|
|
12
|
-
"types": "./dist/index.d.ts"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsup",
|
|
17
|
-
"lint": "tsc --noEmit",
|
|
18
|
-
"test": "vitest run",
|
|
19
|
-
"clean": "rm -rf dist"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist"
|
|
23
|
-
],
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
26
|
-
},
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"solid-js": ">=1.8.0"
|
|
29
|
-
},
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"@geenius-adapters/shared": "workspace:*"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"solid-js": "^1.9.0",
|
|
35
|
-
"tsup": "^8.5.1",
|
|
36
|
-
"typescript": "~6.0.2",
|
|
37
|
-
"vitest": "^4.1.0"
|
|
38
|
-
},
|
|
39
|
-
"author": "Antigravity HQ",
|
|
40
|
-
"license": "MIT",
|
|
41
|
-
"engines": {
|
|
42
|
-
"node": ">=20.0.0"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterCard
|
|
2
|
-
import { Show } from 'solid-js'
|
|
3
|
-
import type { AdapterDomain, AdapterStatusInfo } from '@geenius-adapters/shared'
|
|
4
|
-
import { DOMAIN_LABELS, DOMAIN_ICONS, DOMAIN_DESCRIPTIONS } from '@geenius-adapters/shared'
|
|
5
|
-
import { AdapterStatusBadge } from './AdapterStatusBadge'
|
|
6
|
-
|
|
7
|
-
export function AdapterCard(props: { domain: AdapterDomain; status: AdapterStatusInfo; onClick?: () => void; class?: string }) {
|
|
8
|
-
return (
|
|
9
|
-
<button type="button" onClick={props.onClick} class={`group flex w-full items-start gap-4 rounded-2xl border border-white/10 bg-white/[0.03] p-5 text-left backdrop-blur-sm transition-all hover:border-white/15 hover:bg-white/[0.05] ${props.class ?? ''}`}>
|
|
10
|
-
<div class="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-xl bg-white/5 text-2xl transition-transform group-hover:scale-105">{DOMAIN_ICONS[props.domain]}</div>
|
|
11
|
-
<div class="min-w-0 flex-1">
|
|
12
|
-
<div class="flex items-center justify-between gap-2"><h3 class="truncate text-sm font-bold text-white/90">{DOMAIN_LABELS[props.domain]}</h3><AdapterStatusBadge status={props.status.status} /></div>
|
|
13
|
-
<p class="mt-0.5 text-xs text-white/40 line-clamp-2">{DOMAIN_DESCRIPTIONS[props.domain]}</p>
|
|
14
|
-
<Show when={props.status.provider && props.status.provider !== 'none'}>
|
|
15
|
-
<div class="mt-2 flex items-center gap-2">
|
|
16
|
-
<span class="rounded-md bg-white/5 px-2 py-0.5 text-[0.625rem] font-semibold text-white/50">{props.status.provider}</span>
|
|
17
|
-
<Show when={props.status.latency}><span class="text-[0.625rem] text-white/30">{props.status.latency}ms</span></Show>
|
|
18
|
-
</div>
|
|
19
|
-
</Show>
|
|
20
|
-
<Show when={props.status.error}><p class="mt-1.5 truncate text-[0.625rem] text-red-400/80">{props.status.error}</p></Show>
|
|
21
|
-
</div>
|
|
22
|
-
</button>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterConfigForm
|
|
2
|
-
import { createSignal, For, Show } from 'solid-js'
|
|
3
|
-
import type { AdapterDomain, DomainAdapterConfig } from '@geenius-adapters/shared'
|
|
4
|
-
import { DOMAIN_LABELS, getProvidersForDomain } from '@geenius-adapters/shared'
|
|
5
|
-
|
|
6
|
-
export function AdapterConfigForm(props: { domain: AdapterDomain; initialConfig?: DomainAdapterConfig; onSave: (c: DomainAdapterConfig) => Promise<void> | void; onCancel?: () => void; class?: string }) {
|
|
7
|
-
const providers = getProvidersForDomain(props.domain)
|
|
8
|
-
const [provider, setProvider] = createSignal(props.initialConfig?.provider ?? providers[0]?.id ?? '')
|
|
9
|
-
const [apiKey, setApiKey] = createSignal(props.initialConfig?.apiKey ?? '')
|
|
10
|
-
const [baseUrl, setBaseUrl] = createSignal(props.initialConfig?.baseUrl ?? '')
|
|
11
|
-
const [isSaving, setIsSaving] = createSignal(false)
|
|
12
|
-
const [error, setError] = createSignal<string | null>(null)
|
|
13
|
-
|
|
14
|
-
const needsApiKey = () => !['localStorage', 'noop'].includes(provider())
|
|
15
|
-
const needsBaseUrl = () => ['ollama', 'minio', 'neon', 'supabase'].includes(provider())
|
|
16
|
-
|
|
17
|
-
const handleSubmit = async (e: Event) => {
|
|
18
|
-
e.preventDefault(); setError(null)
|
|
19
|
-
if (!provider()) { setError('Select a provider'); return }
|
|
20
|
-
setIsSaving(true)
|
|
21
|
-
try { await props.onSave({ provider: provider(), apiKey: apiKey() || undefined, baseUrl: baseUrl() || undefined }) }
|
|
22
|
-
catch (e) { setError(e instanceof Error ? e.message : 'Failed') }
|
|
23
|
-
finally { setIsSaving(false) }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<form onSubmit={handleSubmit} class={`space-y-5 rounded-2xl border border-white/10 bg-white/[0.03] p-6 backdrop-blur-sm ${props.class ?? ''}`}>
|
|
28
|
-
<div><h3 class="text-lg font-bold text-white/90">Configure {DOMAIN_LABELS[props.domain]}</h3></div>
|
|
29
|
-
<Show when={error()}><div class="rounded-lg border border-red-500/20 bg-red-500/10 px-4 py-3 text-sm text-red-400">{error()}</div></Show>
|
|
30
|
-
<div>
|
|
31
|
-
<span class="mb-1.5 block text-xs font-semibold uppercase tracking-wider text-white/40">Provider</span>
|
|
32
|
-
<div class="grid gap-2 sm:grid-cols-2">
|
|
33
|
-
<For each={providers}>{p => (
|
|
34
|
-
<button type="button" onClick={() => setProvider(p.id)} class={`flex flex-col rounded-xl border p-3 text-left transition-all ${provider() === p.id ? 'border-indigo-500/30 bg-indigo-500/10' : 'border-white/10 bg-white/[0.02] hover:bg-white/[0.04]'}`}>
|
|
35
|
-
<span class="text-xs font-semibold text-white/80">{p.name}</span>
|
|
36
|
-
<span class="mt-0.5 text-[0.625rem] text-white/40">{p.description}</span>
|
|
37
|
-
<span class={`mt-1 self-start rounded px-1.5 py-0.5 text-[0.5625rem] font-bold uppercase ${p.tier === 'pronto' ? 'bg-emerald-500/10 text-emerald-400' : p.tier === 'mvp' ? 'bg-blue-500/10 text-blue-400' : 'bg-purple-500/10 text-purple-400'}`}>{p.tier}</span>
|
|
38
|
-
</button>
|
|
39
|
-
)}</For>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
<Show when={needsApiKey()}>
|
|
43
|
-
<div><label class="mb-1.5 block text-xs font-semibold uppercase tracking-wider text-white/40">API Key</label><input type="password" value={apiKey()} onInput={e => setApiKey(e.currentTarget.value)} class="w-full rounded-xl border border-white/10 bg-white/[0.02] px-4 py-3 text-sm text-white/90 placeholder:text-white/20 focus:border-indigo-500/50 focus:outline-none" placeholder="API key" /></div>
|
|
44
|
-
</Show>
|
|
45
|
-
<Show when={needsBaseUrl()}>
|
|
46
|
-
<div><label class="mb-1.5 block text-xs font-semibold uppercase tracking-wider text-white/40">Base URL</label><input type="url" value={baseUrl()} onInput={e => setBaseUrl(e.currentTarget.value)} class="w-full rounded-xl border border-white/10 bg-white/[0.02] px-4 py-3 text-sm text-white/90 placeholder:text-white/20 focus:border-indigo-500/50 focus:outline-none" placeholder="https://..." /></div>
|
|
47
|
-
</Show>
|
|
48
|
-
<div class="flex justify-end gap-3 pt-2">
|
|
49
|
-
<Show when={props.onCancel}><button type="button" onClick={props.onCancel} class="rounded-xl px-5 py-2.5 text-sm font-semibold text-white/50 hover:text-white/70">Cancel</button></Show>
|
|
50
|
-
<button type="submit" disabled={isSaving() || !provider()} class="rounded-xl bg-indigo-500 px-6 py-2.5 text-sm font-semibold text-white hover:bg-indigo-400 disabled:opacity-50">{isSaving() ? 'Saving…' : 'Save'}</button>
|
|
51
|
-
</div>
|
|
52
|
-
</form>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterList
|
|
2
|
-
import { createSignal, createMemo, Show, For } from 'solid-js'
|
|
3
|
-
import { createAdapters } from '../primitives'
|
|
4
|
-
import { AdapterCard } from './AdapterCard'
|
|
5
|
-
import { ADAPTER_DOMAINS, DOMAIN_LABELS } from '@geenius-adapters/shared'
|
|
6
|
-
import type { AdapterDomain, AdapterStatusType } from '@geenius-adapters/shared'
|
|
7
|
-
|
|
8
|
-
export function AdapterList(props: { onSelect?: (d: AdapterDomain) => void; filterStatus?: AdapterStatusType; class?: string }) {
|
|
9
|
-
const ctx = createAdapters()
|
|
10
|
-
const [search, setSearch] = createSignal('')
|
|
11
|
-
|
|
12
|
-
const filtered = createMemo(() => {
|
|
13
|
-
let domains = [...ADAPTER_DOMAINS]
|
|
14
|
-
const q = search().toLowerCase()
|
|
15
|
-
if (q) domains = domains.filter(d => DOMAIN_LABELS[d].toLowerCase().includes(q) || d.includes(q))
|
|
16
|
-
if (props.filterStatus) domains = domains.filter(d => ctx.statuses[d]?.status === props.filterStatus)
|
|
17
|
-
return domains
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<div class={props.class ?? ''}>
|
|
22
|
-
<input type="text" value={search()} onInput={e => setSearch(e.currentTarget.value)} placeholder="Search adapters..." class="w-full rounded-xl border border-white/10 bg-white/[0.02] px-4 py-2.5 text-sm text-white/90 placeholder:text-white/20 focus:border-indigo-500/50 focus:outline-none mb-4" />
|
|
23
|
-
<Show when={filtered().length > 0} fallback={<div class="rounded-xl border border-white/5 bg-white/[0.01] p-8 text-center"><p class="text-sm text-white/40">No adapters match</p></div>}>
|
|
24
|
-
<div class="grid gap-3 sm:grid-cols-2"><For each={filtered()}>{d => <AdapterCard domain={d} status={ctx.statuses[d]} onClick={() => props.onSelect?.(d)} />}</For></div>
|
|
25
|
-
</Show>
|
|
26
|
-
</div>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterStatusBadge
|
|
2
|
-
import type { AdapterStatusType } from '@geenius-adapters/shared'
|
|
3
|
-
|
|
4
|
-
const LABELS: Record<AdapterStatusType, string> = { connected: 'Connected', disconnected: 'Disconnected', error: 'Error', initializing: 'Initializing' }
|
|
5
|
-
const STYLES: Record<AdapterStatusType, { bg: string; text: string; dot: string }> = {
|
|
6
|
-
connected: { bg: 'bg-emerald-500/10', text: 'text-emerald-400', dot: 'bg-emerald-400' },
|
|
7
|
-
disconnected: { bg: 'bg-white/5', text: 'text-white/40', dot: 'bg-white/30' },
|
|
8
|
-
error: { bg: 'bg-red-500/10', text: 'text-red-400', dot: 'bg-red-400' },
|
|
9
|
-
initializing: { bg: 'bg-amber-500/10', text: 'text-amber-400', dot: 'bg-amber-400' },
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function AdapterStatusBadge(props: { status: AdapterStatusType; showLabel?: boolean; class?: string }) {
|
|
13
|
-
const s = () => STYLES[props.status]
|
|
14
|
-
return (
|
|
15
|
-
<span class={`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 ${s().bg} ${props.class ?? ''}`}>
|
|
16
|
-
<span class={`h-1.5 w-1.5 rounded-full ${s().dot} ${props.status === 'initializing' ? 'animate-pulse' : ''}`} />
|
|
17
|
-
{props.showLabel !== false && <span class={`text-[0.625rem] font-semibold uppercase tracking-wider ${s().text}`}>{LABELS[props.status]}</span>}
|
|
18
|
-
</span>
|
|
19
|
-
)
|
|
20
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — Barrel export
|
|
2
|
-
|
|
3
|
-
export type {
|
|
4
|
-
AuthAdapter, OAuthProvider, DbAdapter, PaymentsAdapter, AiAdapter, FileStorageAdapter,
|
|
5
|
-
AdminAdapter, AdapterDomain, AdapterConfig, AdapterStatusType, AdapterStatusInfo,
|
|
6
|
-
} from '@geenius-adapters/shared'
|
|
7
|
-
|
|
8
|
-
export { ADAPTER_DOMAINS, DOMAIN_LABELS, DOMAIN_ICONS, DOMAIN_DESCRIPTIONS, configureAdapters, getAdapterConfig } from '@geenius-adapters/shared'
|
|
9
|
-
|
|
10
|
-
export { AdapterProvider, useAdapterContext } from './provider'
|
|
11
|
-
export type { AdapterProviderProps, AdapterSet, AdapterContextValue } from './provider'
|
|
12
|
-
|
|
13
|
-
export { createDb, createAuth, createPayments, createAi, createStorage, createAdmin, createAdapters, createAdapterStatuses, createAdapterStatus, createIsAdapterReady } from './primitives'
|
|
14
|
-
|
|
15
|
-
export { AdapterStatusBadge, AdapterCard, AdapterList, AdapterConfigForm } from './components'
|
|
16
|
-
|
|
17
|
-
export { AdaptersPage, AdapterDetailPage } from './pages'
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterDetailPage
|
|
2
|
-
import { createSignal, Show, For } from 'solid-js'
|
|
3
|
-
import { createAdapters, createAdapterStatus } from '../primitives'
|
|
4
|
-
import { AdapterStatusBadge } from '../components/AdapterStatusBadge'
|
|
5
|
-
import { AdapterConfigForm } from '../components/AdapterConfigForm'
|
|
6
|
-
import type { AdapterDomain } from '@geenius-adapters/shared'
|
|
7
|
-
import { DOMAIN_LABELS, DOMAIN_ICONS, DOMAIN_DESCRIPTIONS, getProvidersForDomain } from '@geenius-adapters/shared'
|
|
8
|
-
|
|
9
|
-
export function AdapterDetailPage(props: { domain: AdapterDomain; onBack?: () => void; class?: string }) {
|
|
10
|
-
const status = createAdapterStatus(props.domain)
|
|
11
|
-
const providers = getProvidersForDomain(props.domain)
|
|
12
|
-
const [isEditing, setIsEditing] = createSignal(false)
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<div class={`max-w-3xl mx-auto space-y-8 ${props.class ?? ''}`}>
|
|
16
|
-
<Show when={props.onBack}><button onClick={props.onBack} class="text-sm text-white/30 hover:text-white/60">← Back</button></Show>
|
|
17
|
-
<div class="flex items-start gap-5">
|
|
18
|
-
<div class="flex h-16 w-16 items-center justify-center rounded-2xl bg-white/5 text-3xl">{DOMAIN_ICONS[props.domain]}</div>
|
|
19
|
-
<div class="flex-1"><div class="flex items-center gap-3"><h1 class="text-2xl font-extrabold text-white/95">{DOMAIN_LABELS[props.domain]}</h1><AdapterStatusBadge status={status().status} /></div><p class="mt-1 text-sm text-white/40">{DOMAIN_DESCRIPTIONS[props.domain]}</p></div>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="rounded-2xl border border-white/10 bg-white/[0.03] p-6">
|
|
22
|
-
<h2 class="text-xs font-semibold uppercase text-white/30 mb-4">Status</h2>
|
|
23
|
-
<div class="grid gap-4 sm:grid-cols-3">
|
|
24
|
-
<div><p class="text-[0.625rem] text-white/30 uppercase">Provider</p><p class="mt-0.5 text-sm font-semibold text-white/80">{status().provider !== 'none' ? status().provider : '—'}</p></div>
|
|
25
|
-
<div><p class="text-[0.625rem] text-white/30 uppercase">Status</p><AdapterStatusBadge status={status().status} /></div>
|
|
26
|
-
<div><p class="text-[0.625rem] text-white/30 uppercase">Last Checked</p><p class="mt-0.5 text-sm text-white/60">{status().lastCheckedAt ? new Date(status().lastCheckedAt!).toLocaleTimeString() : '—'}</p></div>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
<div class="rounded-2xl border border-white/10 bg-white/[0.03] p-6">
|
|
30
|
-
<h2 class="text-xs font-semibold uppercase text-white/30 mb-4">Available Providers ({providers.length})</h2>
|
|
31
|
-
<div class="divide-y divide-white/5"><For each={providers}>{p => <div class="flex items-center justify-between py-3"><div><p class="text-sm font-semibold text-white/80">{p.name}</p><p class="text-xs text-white/30">{p.description}</p></div><span class={`rounded px-2 py-0.5 text-[0.625rem] font-bold uppercase ${p.tier === 'pronto' ? 'bg-emerald-500/10 text-emerald-400' : 'bg-blue-500/10 text-blue-400'}`}>{p.tier}</span></div>}</For></div>
|
|
32
|
-
</div>
|
|
33
|
-
<Show when={isEditing()} fallback={<button onClick={() => setIsEditing(true)} class="w-full rounded-2xl border border-dashed border-white/10 bg-white/[0.01] p-6 text-center text-sm text-white/30 hover:border-white/20">⚙️ Configure</button>}>
|
|
34
|
-
<AdapterConfigForm domain={props.domain} onSave={async () => setIsEditing(false)} onCancel={() => setIsEditing(false)} />
|
|
35
|
-
</Show>
|
|
36
|
-
</div>
|
|
37
|
-
)
|
|
38
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdaptersPage
|
|
2
|
-
import { createSignal, For } from 'solid-js'
|
|
3
|
-
import { createAdapters } from '../primitives'
|
|
4
|
-
import { AdapterList } from '../components/AdapterList'
|
|
5
|
-
import { AdapterConfigForm } from '../components/AdapterConfigForm'
|
|
6
|
-
import { AdapterStatusBadge } from '../components/AdapterStatusBadge'
|
|
7
|
-
import { ADAPTER_DOMAINS, ADAPTER_STATUSES } from '@geenius-adapters/shared'
|
|
8
|
-
import type { AdapterDomain, AdapterStatusType } from '@geenius-adapters/shared'
|
|
9
|
-
|
|
10
|
-
export function AdaptersPage(props: { onNavigateDetail?: (d: AdapterDomain) => void; class?: string }) {
|
|
11
|
-
const ctx = createAdapters()
|
|
12
|
-
const [selectedDomain, setSelectedDomain] = createSignal<AdapterDomain | null>(null)
|
|
13
|
-
const [filterStatus, setFilterStatus] = createSignal<AdapterStatusType | undefined>()
|
|
14
|
-
const connected = () => ADAPTER_DOMAINS.filter(d => ctx.statuses[d]?.status === 'connected').length
|
|
15
|
-
const errors = () => ADAPTER_DOMAINS.filter(d => ctx.statuses[d]?.status === 'error').length
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div class={`max-w-4xl mx-auto space-y-8 ${props.class ?? ''}`}>
|
|
19
|
-
<div><h1 class="text-2xl font-extrabold text-white/95 tracking-tight">Adapters</h1><p class="mt-1 text-sm text-white/40">Manage infrastructure adapters.</p></div>
|
|
20
|
-
<div class="grid gap-3 sm:grid-cols-3">
|
|
21
|
-
<div class="rounded-2xl border border-white/10 bg-white/[0.03] p-4"><p class="text-xs font-semibold uppercase text-white/30">Total</p><p class="mt-1 text-2xl font-extrabold text-white/90">{ADAPTER_DOMAINS.length}</p></div>
|
|
22
|
-
<div class="rounded-2xl border border-emerald-500/10 bg-emerald-500/[0.03] p-4"><p class="text-xs font-semibold uppercase text-emerald-400/60">Connected</p><p class="mt-1 text-2xl font-extrabold text-emerald-400">{connected()}</p></div>
|
|
23
|
-
{errors() > 0 && <div class="rounded-2xl border border-red-500/10 bg-red-500/[0.03] p-4"><p class="text-xs font-semibold uppercase text-red-400/60">Errors</p><p class="mt-1 text-2xl font-extrabold text-red-400">{errors()}</p></div>}
|
|
24
|
-
</div>
|
|
25
|
-
<div class="flex items-center gap-2">
|
|
26
|
-
<button onClick={() => setFilterStatus(undefined)} class={`rounded-lg px-3 py-1.5 text-xs font-semibold ${!filterStatus() ? 'bg-white/10 text-white/80' : 'text-white/30'}`}>All</button>
|
|
27
|
-
<For each={[...ADAPTER_STATUSES]}>{s => <button onClick={() => setFilterStatus(s)} class={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-semibold ${filterStatus() === s ? 'bg-white/10 text-white/80' : 'text-white/30'}`}><AdapterStatusBadge status={s} showLabel={false} />{s}</button>}</For>
|
|
28
|
-
</div>
|
|
29
|
-
<AdapterList onSelect={d => props.onNavigateDetail ? props.onNavigateDetail(d) : setSelectedDomain(d)} filterStatus={filterStatus()} />
|
|
30
|
-
{selectedDomain() && (
|
|
31
|
-
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm" onClick={() => setSelectedDomain(null)}>
|
|
32
|
-
<div class="max-w-lg w-full mx-4" onClick={e => e.stopPropagation()}>
|
|
33
|
-
<AdapterConfigForm domain={selectedDomain()!} onSave={async () => setSelectedDomain(null)} onCancel={() => setSelectedDomain(null)} />
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
)}
|
|
37
|
-
</div>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — Primitives
|
|
2
|
-
|
|
3
|
-
import { createMemo } from 'solid-js'
|
|
4
|
-
import { useAdapterContext } from '../provider/AdapterProvider'
|
|
5
|
-
import type {
|
|
6
|
-
AuthAdapter, DbAdapter, PaymentsAdapter, AiAdapter, FileStorageAdapter, AdminAdapter,
|
|
7
|
-
AdapterDomain, AdapterStatusInfo,
|
|
8
|
-
} from '@geenius-adapters/shared'
|
|
9
|
-
|
|
10
|
-
/** Access the database adapter */
|
|
11
|
-
export function createDb() {
|
|
12
|
-
const ctx = useAdapterContext()
|
|
13
|
-
return ctx.getAdapter('db')
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** Access the auth adapter */
|
|
17
|
-
export function createAuth() {
|
|
18
|
-
const ctx = useAdapterContext()
|
|
19
|
-
return ctx.getAdapter('auth')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** Access the payments adapter */
|
|
23
|
-
export function createPayments() {
|
|
24
|
-
const ctx = useAdapterContext()
|
|
25
|
-
return ctx.getAdapter('payments')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Access the AI adapter */
|
|
29
|
-
export function createAi() {
|
|
30
|
-
const ctx = useAdapterContext()
|
|
31
|
-
return ctx.getAdapter('ai')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Access the file storage adapter */
|
|
35
|
-
export function createStorage() {
|
|
36
|
-
const ctx = useAdapterContext()
|
|
37
|
-
return ctx.getAdapter('storage')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Access the admin adapter */
|
|
41
|
-
export function createAdmin() {
|
|
42
|
-
const ctx = useAdapterContext()
|
|
43
|
-
return ctx.getAdapter('admin')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Access all adapter statuses */
|
|
47
|
-
export function createAdapterStatuses() {
|
|
48
|
-
const ctx = useAdapterContext()
|
|
49
|
-
return ctx.statuses
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Access status for a specific domain */
|
|
53
|
-
export function createAdapterStatus(domain: AdapterDomain) {
|
|
54
|
-
const ctx = useAdapterContext()
|
|
55
|
-
return createMemo(() => ctx.statuses[domain])
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Check if adapter is ready */
|
|
59
|
-
export function createIsAdapterReady(domain: AdapterDomain) {
|
|
60
|
-
const ctx = useAdapterContext()
|
|
61
|
-
return createMemo(() => ctx.isReady(domain))
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Access full adapters object */
|
|
65
|
-
export function createAdapters() {
|
|
66
|
-
const ctx = useAdapterContext()
|
|
67
|
-
return {
|
|
68
|
-
db: ctx.adapters.db,
|
|
69
|
-
auth: ctx.adapters.auth,
|
|
70
|
-
payments: ctx.adapters.payments,
|
|
71
|
-
ai: ctx.adapters.ai,
|
|
72
|
-
storage: ctx.adapters.storage,
|
|
73
|
-
admin: ctx.adapters.admin,
|
|
74
|
-
statuses: ctx.statuses,
|
|
75
|
-
isLoading: ctx.isLoading,
|
|
76
|
-
isReady: ctx.isReady,
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// @geenius-adapters/solidjs — AdapterProvider
|
|
2
|
-
|
|
3
|
-
import { createContext, useContext } from 'solid-js'
|
|
4
|
-
import { createStore } from 'solid-js/store'
|
|
5
|
-
import type { JSX } from 'solid-js'
|
|
6
|
-
import type {
|
|
7
|
-
AuthAdapter, DbAdapter, PaymentsAdapter, AiAdapter, FileStorageAdapter, AdminAdapter,
|
|
8
|
-
AdapterDomain, AdapterStatusInfo,
|
|
9
|
-
} from '@geenius-adapters/shared'
|
|
10
|
-
import { ADAPTER_DOMAINS, DOMAIN_LABELS } from '@geenius-adapters/shared'
|
|
11
|
-
|
|
12
|
-
export interface AdapterSet {
|
|
13
|
-
db?: DbAdapter
|
|
14
|
-
auth?: AuthAdapter
|
|
15
|
-
payments?: PaymentsAdapter
|
|
16
|
-
ai?: AiAdapter
|
|
17
|
-
storage?: FileStorageAdapter
|
|
18
|
-
admin?: AdminAdapter
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface AdapterContextValue {
|
|
22
|
-
adapters: AdapterSet
|
|
23
|
-
statuses: Record<AdapterDomain, AdapterStatusInfo>
|
|
24
|
-
getAdapter: <K extends keyof AdapterSet>(domain: K) => NonNullable<AdapterSet[K]>
|
|
25
|
-
isReady: (domain: AdapterDomain) => boolean
|
|
26
|
-
isLoading: boolean
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const AdapterContext = createContext<AdapterContextValue>()
|
|
30
|
-
|
|
31
|
-
export interface AdapterProviderProps {
|
|
32
|
-
adapters: AdapterSet
|
|
33
|
-
children: JSX.Element
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function AdapterProvider(props: AdapterProviderProps) {
|
|
37
|
-
const initStatuses = {} as Record<AdapterDomain, AdapterStatusInfo>
|
|
38
|
-
for (const d of ADAPTER_DOMAINS) {
|
|
39
|
-
const adapter = props.adapters[d as keyof AdapterSet]
|
|
40
|
-
initStatuses[d] = { domain: d, provider: adapter ? 'configured' : 'none', status: adapter ? 'connected' : 'disconnected', lastCheckedAt: Date.now() }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const [statuses] = createStore(initStatuses)
|
|
44
|
-
|
|
45
|
-
const getAdapter = <K extends keyof AdapterSet>(domain: K): NonNullable<AdapterSet[K]> => {
|
|
46
|
-
const adapter = props.adapters[domain]
|
|
47
|
-
if (!adapter) throw new Error(`${DOMAIN_LABELS[domain as AdapterDomain] ?? domain} adapter not configured`)
|
|
48
|
-
return adapter as NonNullable<AdapterSet[K]>
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const isReady = (domain: AdapterDomain) => !!props.adapters[domain as keyof AdapterSet] && statuses[domain]?.status === 'connected'
|
|
52
|
-
|
|
53
|
-
const value: AdapterContextValue = { adapters: props.adapters, statuses, getAdapter, isReady, isLoading: false }
|
|
54
|
-
|
|
55
|
-
return <AdapterContext.Provider value={value}>{props.children}</AdapterContext.Provider>
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function useAdapterContext(): AdapterContextValue {
|
|
59
|
-
const ctx = useContext(AdapterContext)
|
|
60
|
-
if (!ctx) throw new Error('useAdapterContext must be used within <AdapterProvider>')
|
|
61
|
-
return ctx
|
|
62
|
-
}
|