@feltdb/core 0.4.8 → 0.4.10

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.
@@ -2,3 +2,4 @@
2
2
  * create-feltdb - Main exports
3
3
  */
4
4
  export * from './create.js';
5
+ export * from './managed-account.js';
@@ -0,0 +1,61 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ async function responseJson(response, fallback) {
4
+ const body = await response.json().catch(() => ({}));
5
+ if (!response.ok)
6
+ throw new Error(String(body.error || body.message || fallback));
7
+ return body;
8
+ }
9
+ export async function configureManagedAccount(options) {
10
+ const accountUrl = (options.accountUrl || process.env.FELTDB_MANAGED_ACCOUNT_URL || 'https://feltdb.com').replace(/\/$/, '');
11
+ const apiUrl = (options.apiUrl || process.env.FELTDB_MANAGED_URL || 'https://api.feltdb.com').replace(/\/$/, '');
12
+ const request = options.fetchImpl || fetch;
13
+ const authenticated = await request(`${accountUrl}/api/auth`, {
14
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
15
+ body: JSON.stringify({ email: options.email, password: options.password }),
16
+ });
17
+ await responseJson(authenticated, 'Could not create or sign in to the managed account');
18
+ const cookie = authenticated.headers.get('set-cookie')?.split(';', 1)[0];
19
+ if (!cookie)
20
+ throw new Error('Managed account service did not return a secure session');
21
+ const headers = { Cookie: cookie, 'Content-Type': 'application/json' };
22
+ const tenants = await responseJson(await request(`${accountUrl}/api/tenants`, { headers }), 'Could not load managed workspaces');
23
+ let tenant = Array.isArray(tenants) ? tenants[0] : undefined;
24
+ if (!tenant) {
25
+ tenant = await responseJson(await request(`${accountUrl}/api/tenants`, {
26
+ method: 'POST', headers, body: JSON.stringify({ name: `${options.applicationName} Workspace` }),
27
+ }), 'Could not create the managed workspace');
28
+ }
29
+ const applicationsUrl = `${accountUrl}/api/tenants/${encodeURIComponent(tenant.id)}/applications`;
30
+ const applications = await responseJson(await request(applicationsUrl, { headers }), 'Could not load managed applications');
31
+ let application = Array.isArray(applications)
32
+ ? applications.find(value => value.name === options.applicationName)
33
+ : undefined;
34
+ if (!application) {
35
+ application = await responseJson(await request(applicationsUrl, {
36
+ method: 'POST', headers, body: JSON.stringify({ name: options.applicationName }),
37
+ }), 'Could not create the managed application');
38
+ }
39
+ const key = await responseJson(await request(`${apiUrl}/api/keys`, {
40
+ method: 'POST', headers,
41
+ body: JSON.stringify({
42
+ id: `${options.applicationName}-cli`,
43
+ namespace: options.namespace,
44
+ scopes: ['state:read', 'state:write', 'events:read'],
45
+ }),
46
+ }), 'Could not create the managed application key');
47
+ if (!key.secret)
48
+ throw new Error('Managed key service did not return an application secret');
49
+ const environment = [
50
+ '# Generated by create-feltdb managed setup. Do not commit this file.',
51
+ `VITE_FELTDB_MANAGED_URL=${apiUrl}`,
52
+ `VITE_FELTDB_MANAGED_API_KEY=${key.secret}`,
53
+ `VITE_FELTDB_MANAGED_TENANT_ID=${tenant.id}`,
54
+ `VITE_FELTDB_MANAGED_APPLICATION_ID=${application.id}`,
55
+ `VITE_FELTDB_MANAGED_NAMESPACE=${application.namespace || options.namespace}`,
56
+ 'VITE_FELTDB_MANAGED_ENVIRONMENT=production',
57
+ '',
58
+ ].join('\n');
59
+ fs.writeFileSync(path.join(options.projectDir, '.env.local'), environment, { mode: 0o600 });
60
+ return { tenant, application, apiUrl };
61
+ }
@@ -1,4 +1,4 @@
1
1
  // One release train keeps generated applications installable. The repository
2
2
  // validation script checks these values against every workspace manifest.
3
- export const FELTDB_PACKAGE_VERSION = '0.4.7';
3
+ export const FELTDB_PACKAGE_VERSION = '0.4.10';
4
4
  export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
@@ -28,12 +28,12 @@ var a = {
28
28
  keyActions: "_keyActions_1cbba_243",
29
29
  revokeBtn: "_revokeBtn_1cbba_250",
30
30
  info: "_info_1cbba_265"
31
- }, o = ({ apiUrl: o, token: s, namespace: c = "app-store-sherpa" }) => {
32
- let [l, u] = t([]), [d, f] = t(!0), [p, m] = t(null), [h, g] = t(!1), [_, v] = t(null), [y, b] = t(""), [x, S] = t([
31
+ }, o = ({ apiUrl: o, token: s, namespace: c = "app-store-sherpa", onConfigure: l }) => {
32
+ let [u, d] = t([]), [f, p] = t(!0), [m, h] = t(null), [g, _] = t(!1), [v, y] = t(null), [b, x] = t(""), [S, C] = t([
33
33
  "state:read",
34
34
  "state:write",
35
35
  "events:read"
36
- ]), C = [
36
+ ]), w = [
37
37
  "state:read",
38
38
  "state:write",
39
39
  "events:read",
@@ -41,7 +41,7 @@ var a = {
41
41
  "backup:restore",
42
42
  "admin:logs",
43
43
  "admin:restart"
44
- ], w = [
44
+ ], T = [
45
45
  "state:read",
46
46
  "state:write",
47
47
  "events:read",
@@ -51,79 +51,73 @@ var a = {
51
51
  "admin:restart"
52
52
  ];
53
53
  e(() => {
54
- T();
55
- }, []);
56
- let T = async () => {
54
+ E();
55
+ }, [o, s]);
56
+ let E = async () => {
57
57
  try {
58
- if (f(!0), m(null), !o || !s) {
59
- m("API URL or authentication token not configured. Please check your environment."), f(!1);
58
+ if (p(!0), h(null), !o) {
59
+ h("A server or managed API URL is not configured."), p(!1);
60
60
  return;
61
61
  }
62
62
  let e = await fetch(`${o}/api/keys`, {
63
- headers: { Authorization: `Bearer ${s}` },
63
+ headers: s ? { Authorization: `Bearer ${s}` } : {},
64
64
  signal: AbortSignal.timeout(1e4)
65
65
  });
66
66
  if (e.status === 401) throw Error("Unauthorized: Invalid or expired API token");
67
67
  if (e.status === 403) throw Error("Forbidden: Your account does not have permission to manage API keys");
68
68
  if (!e.ok) throw Error(`Failed to fetch keys: ${e.status} ${e.statusText}`);
69
69
  let t = await e.json();
70
- u(t.tokens || []);
70
+ d(t.tokens || []);
71
71
  } catch (e) {
72
72
  let t = e instanceof TypeError ? `Connection error: Unable to reach ${o}. Is the server running?` : e instanceof Error ? e.message : "Failed to fetch keys";
73
- m(t), console.error("Error fetching API keys:", e);
73
+ h(t), console.error("Error fetching API keys:", e);
74
74
  } finally {
75
- f(!1);
75
+ p(!1);
76
76
  }
77
- }, E = async (e) => {
77
+ }, D = async (e) => {
78
78
  e.preventDefault();
79
79
  try {
80
80
  let e = await fetch(`${o}/api/keys`, {
81
81
  method: "POST",
82
82
  headers: {
83
- Authorization: `Bearer ${s}`,
83
+ ...s ? { Authorization: `Bearer ${s}` } : {},
84
84
  "Content-Type": "application/json"
85
85
  },
86
86
  body: JSON.stringify({
87
- id: y || `key-${Date.now()}`,
87
+ id: b || `key-${Date.now()}`,
88
88
  namespace: c,
89
- scopes: x.length > 0 ? x : w,
90
- expiresIn: 90
89
+ scopes: S.length > 0 ? S : T
91
90
  }),
92
91
  signal: AbortSignal.timeout(1e4)
93
92
  });
94
93
  if (e.status === 401) throw Error("Unauthorized: Invalid or expired API token");
95
94
  if (e.status === 409) throw Error("A key with this name already exists");
96
95
  if (!e.ok) throw Error(`Failed to create key: ${e.status} ${e.statusText}`);
97
- b(""), S(w), g(!1), await T();
96
+ let t = await e.json();
97
+ j(t.secret), x(""), C(T), _(!1), await E();
98
98
  } catch (e) {
99
99
  let t = e instanceof TypeError ? "Connection error: Unable to reach the API server" : e instanceof Error ? e.message : "Failed to create key";
100
- m(t), console.error("Error creating API key:", e);
100
+ h(t), console.error("Error creating API key:", e);
101
101
  }
102
- }, D = async (e) => {
102
+ }, O = async (e) => {
103
103
  if (confirm(`Revoke key "${e}"? This cannot be undone.`)) try {
104
104
  let t = await fetch(`${o}/api/keys/${e}`, {
105
105
  method: "DELETE",
106
- headers: { Authorization: `Bearer ${s}` },
106
+ headers: s ? { Authorization: `Bearer ${s}` } : {},
107
107
  signal: AbortSignal.timeout(1e4)
108
108
  });
109
109
  if (t.status === 404) throw Error("Key not found");
110
110
  if (t.status === 401) throw Error("Unauthorized: Invalid or expired API token");
111
111
  if (!t.ok) throw Error(`Failed to revoke key: ${t.status} ${t.statusText}`);
112
- await T();
112
+ await E();
113
113
  } catch (e) {
114
114
  let t = e instanceof TypeError ? "Connection error: Unable to reach the API server" : e instanceof Error ? e.message : "Failed to revoke key";
115
- m(t), console.error("Error revoking API key:", e);
115
+ h(t), console.error("Error revoking API key:", e);
116
116
  }
117
- }, O = (e, t) => {
118
- navigator.clipboard.writeText(e), v(t), setTimeout(() => v(null), 2e3);
119
- }, k = (e) => new Date(e).toLocaleDateString("en-US", {
120
- year: "numeric",
121
- month: "short",
122
- day: "numeric",
123
- hour: "2-digit",
124
- minute: "2-digit"
125
- }), A = (e) => new Date(e) < /* @__PURE__ */ new Date(), j = (e) => Math.ceil((new Date(e).getTime() - (/* @__PURE__ */ new Date()).getTime()) / 864e5);
126
- return d ? /* @__PURE__ */ r("div", {
117
+ }, k = (e, t) => {
118
+ navigator.clipboard.writeText(e), y(t), setTimeout(() => y(null), 2e3);
119
+ }, [A, j] = t(null);
120
+ return f ? /* @__PURE__ */ r("div", {
127
121
  className: a.panel,
128
122
  children: "Loading keys..."
129
123
  }) : /* @__PURE__ */ i("div", {
@@ -133,20 +127,20 @@ var a = {
133
127
  className: a.header,
134
128
  children: [/* @__PURE__ */ r("h2", { children: "API Key Management" }), /* @__PURE__ */ r("button", {
135
129
  className: a.createButton,
136
- onClick: () => g(!h),
137
- disabled: !!p,
138
- children: h ? "✕ Cancel" : "+ New Key"
130
+ onClick: () => _(!g),
131
+ disabled: !o,
132
+ children: g ? "✕ Cancel" : "+ New Key"
139
133
  })]
140
134
  }),
141
- p && /* @__PURE__ */ i("div", {
135
+ m && /* @__PURE__ */ i("div", {
142
136
  className: a.error,
143
- children: [/* @__PURE__ */ i("strong", { children: ["⚠ ", p] }), /* @__PURE__ */ r("div", {
137
+ children: [/* @__PURE__ */ i("strong", { children: ["⚠ ", m] }), /* @__PURE__ */ r("div", {
144
138
  style: {
145
139
  fontSize: "12px",
146
140
  marginTop: "8px",
147
141
  lineHeight: "1.5"
148
142
  },
149
- children: p.includes("Connection error") && /* @__PURE__ */ i(n, { children: [
143
+ children: m.includes("Connection error") && /* @__PURE__ */ i(n, { children: [
150
144
  /* @__PURE__ */ r("p", { children: "To use API key management, ensure:" }),
151
145
  /* @__PURE__ */ i("ul", {
152
146
  style: {
@@ -160,7 +154,7 @@ var a = {
160
154
  ]
161
155
  }),
162
156
  /* @__PURE__ */ r("button", {
163
- onClick: () => T(),
157
+ onClick: () => E(),
164
158
  style: {
165
159
  marginTop: "8px",
166
160
  padding: "4px 12px",
@@ -176,16 +170,34 @@ var a = {
176
170
  ] })
177
171
  })]
178
172
  }),
179
- h && /* @__PURE__ */ i("form", {
180
- onSubmit: E,
173
+ !o && /* @__PURE__ */ i("div", {
174
+ className: a.error,
175
+ children: [/* @__PURE__ */ r("strong", { children: "Connect Studio to a server or managed runtime before managing keys." }), l && /* @__PURE__ */ r("button", {
176
+ onClick: l,
177
+ children: "Open connection settings"
178
+ })]
179
+ }),
180
+ A && /* @__PURE__ */ i("div", {
181
+ className: a.info,
182
+ children: [
183
+ /* @__PURE__ */ r("strong", { children: "New secret — copy it now; it will not be shown again." }),
184
+ /* @__PURE__ */ r("code", { children: A }),
185
+ /* @__PURE__ */ r("button", {
186
+ onClick: () => k(A, "created"),
187
+ children: v === "created" ? "✓ Copied" : "Copy secret"
188
+ })
189
+ ]
190
+ }),
191
+ g && /* @__PURE__ */ i("form", {
192
+ onSubmit: D,
181
193
  className: a.createForm,
182
194
  children: [
183
195
  /* @__PURE__ */ i("div", {
184
196
  className: a.formGroup,
185
197
  children: [/* @__PURE__ */ r("label", { children: "Key Name (optional)" }), /* @__PURE__ */ r("input", {
186
198
  type: "text",
187
- value: y,
188
- onChange: (e) => b(e.target.value),
199
+ value: b,
200
+ onChange: (e) => x(e.target.value),
189
201
  placeholder: "e.g., staging-key-001"
190
202
  })]
191
203
  }),
@@ -193,13 +205,13 @@ var a = {
193
205
  className: a.formGroup,
194
206
  children: [/* @__PURE__ */ r("label", { children: "Scopes" }), /* @__PURE__ */ r("div", {
195
207
  className: a.scopeList,
196
- children: C.map((e) => /* @__PURE__ */ i("label", {
208
+ children: w.map((e) => /* @__PURE__ */ i("label", {
197
209
  className: a.scopeCheckbox,
198
210
  children: [/* @__PURE__ */ r("input", {
199
211
  type: "checkbox",
200
- checked: x.includes(e),
212
+ checked: S.includes(e),
201
213
  onChange: (t) => {
202
- t.target.checked ? S([...x, e]) : S(x.filter((t) => t !== e));
214
+ t.target.checked ? C([...S, e]) : C(S.filter((t) => t !== e));
203
215
  }
204
216
  }), e]
205
217
  }, e))
@@ -212,75 +224,43 @@ var a = {
212
224
  })
213
225
  ]
214
226
  }),
215
- l.length === 0 ? /* @__PURE__ */ r("div", {
227
+ u.length === 0 ? /* @__PURE__ */ r("div", {
216
228
  className: a.empty,
217
229
  children: "No API keys configured. Create one to get started."
218
230
  }) : /* @__PURE__ */ r("div", {
219
231
  className: a.keysList,
220
- children: l.map((e) => /* @__PURE__ */ i("div", {
232
+ children: u.map((e) => /* @__PURE__ */ i("div", {
221
233
  className: a.keyCard,
222
234
  children: [
223
235
  /* @__PURE__ */ i("div", {
224
236
  className: a.keyHeader,
225
- children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h3", { children: e.id }), /* @__PURE__ */ i("p", {
237
+ children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h3", { children: e.name || e.id }), /* @__PURE__ */ i("p", {
226
238
  className: a.namespace,
227
- children: ["Namespace: ", e.namespace]
239
+ children: ["Namespaces: ", e.namespaces.join(", ")]
228
240
  })] }), /* @__PURE__ */ r("span", {
229
- className: `${a.status} ${A(e.expires_at) ? a.expired : a.active}`,
230
- children: A(e.expires_at) ? "Expired" : "Active"
241
+ className: `${a.status} ${e.revoked ? a.expired : a.active}`,
242
+ children: e.revoked ? "Revoked" : "Active"
231
243
  })]
232
244
  }),
233
- /* @__PURE__ */ i("div", {
245
+ /* @__PURE__ */ r("div", {
234
246
  className: a.keyDetails,
235
- children: [
236
- /* @__PURE__ */ i("div", {
237
- className: a.detail,
238
- children: [
239
- /* @__PURE__ */ r("strong", { children: "Secret:" }),
240
- /* @__PURE__ */ i("code", { children: [e.secret.substring(0, 20), "..."] }),
241
- /* @__PURE__ */ r("button", {
242
- className: a.copyBtn,
243
- onClick: () => O(e.secret, e.id),
244
- children: _ === e.id ? "✓ Copied" : "Copy"
245
- })
246
- ]
247
- }),
248
- /* @__PURE__ */ i("div", {
249
- className: a.detail,
250
- children: [/* @__PURE__ */ r("strong", { children: "Created:" }), /* @__PURE__ */ r("span", { children: k(e.created_at) })]
251
- }),
252
- /* @__PURE__ */ i("div", {
253
- className: a.detail,
254
- children: [/* @__PURE__ */ r("strong", { children: "Expires:" }), /* @__PURE__ */ i("span", { children: [k(e.expires_at), !A(e.expires_at) && /* @__PURE__ */ i("span", {
255
- className: a.daysLeft,
256
- children: [
257
- "(",
258
- j(e.expires_at),
259
- " days)"
260
- ]
261
- })] })]
262
- }),
263
- e.last_used && /* @__PURE__ */ i("div", {
264
- className: a.detail,
265
- children: [/* @__PURE__ */ r("strong", { children: "Last Used:" }), /* @__PURE__ */ r("span", { children: k(e.last_used) })]
266
- }),
267
- /* @__PURE__ */ i("div", {
268
- className: a.scopes,
269
- children: [/* @__PURE__ */ r("strong", { children: "Scopes:" }), /* @__PURE__ */ r("div", {
270
- className: a.scopeTags,
271
- children: e.scopes.map((e) => /* @__PURE__ */ r("span", {
272
- className: a.scopeTag,
273
- children: e
274
- }, e))
275
- })]
276
- })
277
- ]
247
+ children: /* @__PURE__ */ i("div", {
248
+ className: a.scopes,
249
+ children: [/* @__PURE__ */ r("strong", { children: "Scopes:" }), /* @__PURE__ */ r("div", {
250
+ className: a.scopeTags,
251
+ children: e.scopes.map((e) => /* @__PURE__ */ r("span", {
252
+ className: a.scopeTag,
253
+ children: e
254
+ }, e))
255
+ })]
256
+ })
278
257
  }),
279
258
  /* @__PURE__ */ r("div", {
280
259
  className: a.keyActions,
281
260
  children: /* @__PURE__ */ r("button", {
282
261
  className: a.revokeBtn,
283
- onClick: () => D(e.id),
262
+ onClick: () => O(e.id),
263
+ disabled: e.revoked,
284
264
  children: "Revoke"
285
265
  })
286
266
  })
@@ -289,7 +269,7 @@ var a = {
289
269
  }),
290
270
  /* @__PURE__ */ r("div", {
291
271
  className: a.info,
292
- children: /* @__PURE__ */ i("p", { children: [/* @__PURE__ */ r("strong", { children: "Security:" }), " Store tokens securely. Never commit to version control. Tokens expire after 90 days."] })
272
+ children: /* @__PURE__ */ i("p", { children: [/* @__PURE__ */ r("strong", { children: "Security:" }), " Store tokens securely. Never commit to version control. Secrets are shown once. Revoke and replace a key if its secret is lost."] })
293
273
  })
294
274
  ]
295
275
  });
@@ -3,8 +3,11 @@ import { StateFirstDB } from '@feltdb/core';
3
3
  export interface StudioAppProps {
4
4
  db?: StateFirstDB;
5
5
  remoteUrl?: string;
6
+ token?: string;
6
7
  namespace?: string;
8
+ deploymentRuntime?: string;
9
+ onConnect?: (url: string, token: string) => void;
7
10
  }
8
- export declare function StudioApp({ db, remoteUrl, namespace }: StudioAppProps): React.JSX.Element;
11
+ export declare function StudioApp({ db, remoteUrl, token, namespace, deploymentRuntime, onConnect }: StudioAppProps): React.JSX.Element;
9
12
  export default StudioApp;
10
13
  //# sourceMappingURL=app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAmBnD,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,WAAW,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAqB,EAAE,EAAE,cAAc,qBA2GjF;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAmBnD,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,WAAW,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,SAAc,EAAE,KAAU,EAAE,SAAqB,EAAE,iBAA6B,EAAE,SAAS,EAAE,EAAE,cAAc,qBAmG5I;AAED,eAAe,SAAS,CAAC"}
@@ -3,6 +3,7 @@ interface KeyManagementPanelProps {
3
3
  apiUrl: string;
4
4
  token: string;
5
5
  namespace?: string;
6
+ onConfigure?: () => void;
6
7
  }
7
8
  export declare const KeyManagementPanel: React.FC<KeyManagementPanelProps>;
8
9
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"KeyManagementPanel.d.ts","sourceRoot":"","sources":["../../src/components/KeyManagementPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,UAAU,uBAAuB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4WhE,CAAC"}
1
+ {"version":3,"file":"KeyManagementPanel.d.ts","sourceRoot":"","sources":["../../src/components/KeyManagementPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAWnD,UAAU,uBAAuB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA+ThE,CAAC"}
@@ -1,2 +1,2 @@
1
- import { t as e } from "../KeyManagementPanel-B0s0xAXz.js";
1
+ import { t as e } from "../KeyManagementPanel-DZuSeWBK.js";
2
2
  export { e as KeyManagementPanel };
@@ -1,7 +1,11 @@
1
1
  import { default as React } from 'react';
2
+ import { StateFirstDB } from '@feltdb/core';
2
3
  export interface SettingsPanelProps {
3
- db?: any;
4
+ db?: StateFirstDB;
5
+ remoteUrl?: string;
6
+ token?: string;
7
+ onConnect?: (url: string, token: string) => void;
4
8
  }
5
- export declare function SettingsPanel({ db }: SettingsPanelProps): React.JSX.Element;
9
+ export declare function SettingsPanel({ db, remoteUrl, token, onConnect }: SettingsPanelProps): React.JSX.Element;
6
10
  export default SettingsPanel;
7
11
  //# sourceMappingURL=SettingsPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsPanel.d.ts","sourceRoot":"","sources":["../../src/components/SettingsPanel.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE,GAAG,CAAC;CACV;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,kBAAkB,qBAwDvD;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"SettingsPanel.d.ts","sourceRoot":"","sources":["../../src/components/SettingsPanel.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,SAAc,EAAE,KAAU,EAAE,SAAS,EAAE,EAAE,kBAAkB,qBAmC9F;AAED,eAAe,aAAa,CAAC"}
@@ -1,4 +1,4 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p, x as m } from "../components-BAycgZhP.js";
2
- import { t as h } from "../KeyManagementPanel-B0s0xAXz.js";
1
+ import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p, x as m } from "../components-gmwCs-Pb.js";
2
+ import { t as h } from "../KeyManagementPanel-DZuSeWBK.js";
3
3
  import { ManagedInstancePanel as g } from "./ManagedInstancePanel.js";
4
4
  export { c as AgentExplorer, f as ApplicationDesigner, p as CapabilityExplorer, t as ConflictExplorer, a as ExecutionViewer, s as GlobalSearch, i as HealthCenter, h as KeyManagementPanel, g as ManagedInstancePanel, r as OperationsExplorer, m as OverviewDashboard, n as PeerMap, e as ProvenanceViewer, l as ReferenceExplorer, u as SettingsPanel, o as StateExplorer, d as WorkflowVisualizer };
@@ -1,4 +1,4 @@
1
- import "./KeyManagementPanel-B0s0xAXz.js";
1
+ import "./KeyManagementPanel-DZuSeWBK.js";
2
2
  import "./components/ManagedInstancePanel.js";
3
3
  import e, { useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
4
4
  import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
@@ -909,66 +909,65 @@ function I({ diagnostics: e, model: t }) {
909
909
  }
910
910
  //#endregion
911
911
  //#region src/components/SettingsPanel.tsx
912
- function L({ db: e }) {
913
- let [t, n] = a("api-keys");
914
- return /* @__PURE__ */ c("div", {
912
+ function L({ db: e, remoteUrl: t = "", token: r = "", onConnect: i }) {
913
+ let [o, l] = a(t), [u, d] = a(r), f = e?.runtime();
914
+ return n(() => {
915
+ l(t), d(r);
916
+ }, [t, r]), /* @__PURE__ */ c("div", {
915
917
  className: "settings-panel",
916
- children: [
917
- /* @__PURE__ */ s("h2", { children: "Settings" }),
918
- /* @__PURE__ */ c("div", {
919
- className: "settings-tabs",
920
- children: [/* @__PURE__ */ s("button", {
921
- className: `tab ${t === "api-keys" ? "active" : ""}`,
922
- onClick: () => n("api-keys"),
923
- children: "API Keys"
924
- }), /* @__PURE__ */ s("button", {
925
- className: `tab ${t === "connection" ? "active" : ""}`,
926
- onClick: () => n("connection"),
927
- children: "Connection"
928
- })]
929
- }),
930
- t === "api-keys" && /* @__PURE__ */ c("div", {
931
- className: "settings-content",
932
- children: [
933
- /* @__PURE__ */ s("h3", { children: "API Keys" }),
934
- /* @__PURE__ */ s("p", { children: "Manage authentication and access control" }),
935
- /* @__PURE__ */ s("div", {
936
- className: "keys-list",
937
- children: /* @__PURE__ */ s("div", {
938
- className: "empty-message",
939
- children: "No API keys configured"
940
- })
941
- }),
942
- /* @__PURE__ */ s("button", {
943
- className: "btn btn-primary",
944
- children: "Create API Key"
945
- })
946
- ]
947
- }),
948
- t === "connection" && /* @__PURE__ */ c("div", {
949
- className: "settings-content",
950
- children: [/* @__PURE__ */ s("h3", { children: "Connection" }), /* @__PURE__ */ c("div", {
918
+ children: [/* @__PURE__ */ s("h2", { children: "Settings" }), /* @__PURE__ */ c("div", {
919
+ className: "settings-content",
920
+ children: [
921
+ /* @__PURE__ */ s("h3", { children: "Connection" }),
922
+ /* @__PURE__ */ c("div", {
951
923
  className: "connection-info",
952
924
  children: [
953
925
  /* @__PURE__ */ c("div", {
954
926
  className: "info-row",
955
- children: [/* @__PURE__ */ s("label", { children: "Runtime Environment" }), /* @__PURE__ */ s("span", { children: "Browser" })]
927
+ children: [/* @__PURE__ */ s("label", { children: "Runtime Environment" }), /* @__PURE__ */ s("span", { children: f?.runtime || "unavailable" })]
956
928
  }),
957
929
  /* @__PURE__ */ c("div", {
958
930
  className: "info-row",
959
- children: [/* @__PURE__ */ s("label", { children: "Storage Backend" }), /* @__PURE__ */ s("span", { children: "OPFS / IndexedDB" })]
931
+ children: [/* @__PURE__ */ s("label", { children: "Storage Backend" }), /* @__PURE__ */ s("span", { children: f?.storage || "unavailable" })]
960
932
  }),
961
933
  /* @__PURE__ */ c("div", {
962
934
  className: "info-row",
963
935
  children: [/* @__PURE__ */ s("label", { children: "Instance ID" }), /* @__PURE__ */ s("span", {
964
936
  className: "monospace",
965
- children: "instance-xxxx"
937
+ children: e?.instanceId?.() || "unavailable"
966
938
  })]
967
939
  })
968
940
  ]
969
- })]
970
- })
971
- ]
941
+ }),
942
+ /* @__PURE__ */ c("form", {
943
+ className: "connection-form",
944
+ onSubmit: (e) => {
945
+ e.preventDefault(), i?.(o, u);
946
+ },
947
+ children: [
948
+ /* @__PURE__ */ c("label", { children: ["Server or managed endpoint", /* @__PURE__ */ s("input", {
949
+ type: "url",
950
+ value: o,
951
+ onChange: (e) => l(e.target.value),
952
+ placeholder: "https://your-runtime.example.com"
953
+ })] }),
954
+ /* @__PURE__ */ c("label", { children: ["API token", /* @__PURE__ */ s("input", {
955
+ type: "password",
956
+ value: u,
957
+ onChange: (e) => d(e.target.value),
958
+ placeholder: "fdb_live_…",
959
+ autoComplete: "off"
960
+ })] }),
961
+ /* @__PURE__ */ s("p", { children: "Tokens are kept in this browser session and are never written to the project." }),
962
+ /* @__PURE__ */ s("button", {
963
+ className: "btn btn-primary",
964
+ type: "submit",
965
+ children: "Connect Studio"
966
+ })
967
+ ]
968
+ })
969
+ ]
970
+ })]
972
971
  });
973
972
  }
974
973
  //#endregion