@inflector/aura 0.1.20 → 0.2.2

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/dist/auth.d.ts CHANGED
@@ -1,23 +1,13 @@
1
- export declare const authTokenVersion: import("nanostores").PreinitializedWritableAtom<number> & object;
2
- declare const getTokenKey: (workspace: string) => string;
3
- declare const getToken: (workspace: string) => string;
4
- declare const setToken: (workspace: string, token: string | null) => void;
5
- export { getToken, setToken, getTokenKey };
6
1
  export declare const AuraAuth: (url: string, workspace: string) => {
7
- Logout: () => Promise<{
8
- data: {
9
- success: boolean;
10
- };
11
- error: null;
12
- } | {
13
- data: null;
14
- error: {
15
- code?: string | undefined | undefined;
16
- message?: string | undefined | undefined;
17
- status: number;
18
- statusText: string;
19
- };
20
- }>;
2
+ Logout: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
3
+ query?: Record<string, any> | undefined;
4
+ fetchOptions?: FetchOptions | undefined;
5
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
6
+ success: boolean;
7
+ }, {
8
+ code?: string | undefined;
9
+ message?: string | undefined;
10
+ }, FetchOptions["throw"] extends true ? true : false>>;
21
11
  Email: {
22
12
  SignUp: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<{
23
13
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,kEAAW,CAAC;AAKzC,QAAA,MAAM,WAAW,GAAI,WAAW,MAAM,WAAqC,CAAC;AAG5E,QAAA,MAAM,QAAQ,GAAI,WAAW,MAAM,KAAG,MAGrC,CAAC;AAEF,QAAA,MAAM,QAAQ,GAAI,WAAW,MAAM,EAAE,OAAO,MAAM,GAAG,IAAI,SAWxD,CAAC;AAGF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AAU3C,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBA2E3B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;yBAQxB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA7EvC,CAAC;iBAAe,CAAC;;;;;;;;;;;;;;;;qBAZI,CAAC;;;;;;;;;;;;;;;;CAoKtC,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAoD3B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;yBAQxB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAdJ,CAAC;iBAC1C,CAAC;;;;;;;;;;;;;;;;qBAbF,CAAC;;;;;;;;;;;;;;;;CAiGV,CAAC"}
package/dist/auth.js CHANGED
@@ -1,70 +1,20 @@
1
1
  import { createAuthClient } from "better-auth/client";
2
2
  import { anonymousClient } from "better-auth/client/plugins";
3
- import { computed, atom } from "nanostores";
4
- // Atom to track session/token version for reactivity
5
- export const authTokenVersion = atom(-1);
6
- // Token storage key - unique per workspace to avoid conflicts
7
- const getTokenKey = (workspace) => `aura_bearer_token_${workspace}`;
8
- // Helper to get/set token from localStorage (with SSR safety)
9
- const getToken = (workspace) => {
10
- if (typeof window === 'undefined')
11
- return '';
12
- return localStorage.getItem(getTokenKey(workspace)) || '';
13
- };
14
- const setToken = (workspace, token) => {
15
- if (typeof window === 'undefined')
16
- return;
17
- const key = getTokenKey(workspace);
18
- if (token) {
19
- localStorage.setItem(key, token);
20
- }
21
- else {
22
- localStorage.removeItem(key);
23
- }
24
- // Update version to trigger reactivity in hooks
25
- authTokenVersion.set(authTokenVersion.get() + 1);
26
- };
27
- // Export for use in other modules
28
- export { getToken, setToken, getTokenKey };
29
- // Listen for storage events (cross-tab sync) to update token version
30
- if (typeof window !== 'undefined') {
31
- window.addEventListener('storage', (e) => {
32
- if (e.key && e.key.startsWith('aura_bearer_token_')) {
33
- authTokenVersion.set(authTokenVersion.get() + 1);
34
- }
35
- });
36
- }
3
+ import { computed } from "nanostores";
4
+ // export const AuraAuth = (workspace: string) => {
37
5
  export const AuraAuth = (url, workspace) => {
38
6
  const _onUserLoadedCallbacks = [];
39
7
  const _onUserNotFoundCallbacks = [];
40
8
  let _initialized = false;
41
9
  let User = null;
42
10
  const authClient = createAuthClient({
43
- baseURL: url + "/api/auth/" + workspace,
11
+ // baseURL: `${window.location.origin}/api/auth/${workspace}`,
12
+ baseURL: `${url}/api/auth/${workspace}`,
44
13
  plugins: [anonymousClient()],
45
14
  fetchOptions: {
46
- // Use Bearer token authentication instead of cookies
47
- auth: {
48
- type: "Bearer",
49
- token: () => getToken(workspace)
50
- },
51
- // Store the token from response headers on every successful request
52
- onSuccess: (ctx) => {
53
- const authToken = ctx.response.headers.get("set-auth-token");
54
- if (authToken) {
55
- setToken(workspace, authToken);
56
- }
57
- }
15
+ credentials: "include"
58
16
  },
59
17
  });
60
- // Refresh session when token changes (e.g. from another tab)
61
- if (typeof window !== 'undefined') {
62
- const unsub = authTokenVersion.subscribe((v) => {
63
- if (v > 0) {
64
- authClient.getSession().catch(() => { });
65
- }
66
- });
67
- }
68
18
  const Session = computed(authClient.useSession, (session) => {
69
19
  if (!session?.data?.user)
70
20
  return session;
@@ -74,7 +24,7 @@ export const AuraAuth = (url, workspace) => {
74
24
  ...session.data,
75
25
  user: {
76
26
  ...session.data.user,
77
- image: session.data.user.image ? url + session.data.user.image : null,
27
+ image: session.data.user.image ? session.data.user.image : null,
78
28
  },
79
29
  },
80
30
  };
@@ -99,9 +49,6 @@ export const AuraAuth = (url, workspace) => {
99
49
  await triggerCallbacks(_onUserNotFoundCallbacks);
100
50
  }
101
51
  finally {
102
- if (authTokenVersion.get() < 0) {
103
- authTokenVersion.set(0);
104
- }
105
52
  _initialized = true;
106
53
  }
107
54
  };
@@ -124,11 +71,7 @@ export const AuraAuth = (url, workspace) => {
124
71
  // Initialize auth on creation
125
72
  initialize();
126
73
  return {
127
- Logout: async () => {
128
- const result = await authClient.signOut();
129
- setToken(workspace, null); // Clear token on logout
130
- return result;
131
- },
74
+ Logout: authClient.signOut,
132
75
  Email: {
133
76
  SignUp: authClient.signUp.email,
134
77
  Login: authClient.signIn.email,
package/dist/bin.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env bun
2
2
  export declare function build(silent?: boolean): void;
3
+ export declare function dev(): Promise<void>;
3
4
  //# sourceMappingURL=bin.d.ts.map
package/dist/bin.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AA2JA,wBAAgB,KAAK,CAAC,MAAM,UAAQ,QAqBnC"}
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AA+KA,wBAAgB,KAAK,CAAC,MAAM,UAAQ,QAyBnC;AAwaD,wBAAsB,GAAG,kBAsExB"}
package/dist/bin.js CHANGED
@@ -27,7 +27,7 @@ class Spinner {
27
27
  return;
28
28
  process.stdout.write("\x1B[?25l");
29
29
  this.timer = setInterval(() => {
30
- const frame = this.frames[this.i = (this.i + 1) % this.frames.length];
30
+ const frame = this.frames[(this.i = (this.i + 1) % this.frames.length)];
31
31
  process.stdout.write(`\r${chalk.cyan(frame)} ${this.text}`);
32
32
  }, 80);
33
33
  }
@@ -54,15 +54,21 @@ function printBanner() {
54
54
  console.log("");
55
55
  }
56
56
  function printBox(title, content) {
57
- const lines = content.split('\n');
58
- const width = Math.max(title.length, ...lines.map(l => l.length)) + 4;
57
+ const lines = content.split("\n");
58
+ const width = Math.max(title.length, ...lines.map((l) => l.length)) + 4;
59
59
  const top = BORDER_COLOR("┌" + "─".repeat(width) + "┐");
60
60
  const bottom = BORDER_COLOR("└" + "─".repeat(width) + "┘");
61
61
  console.log(top);
62
- console.log(BORDER_COLOR("│") + " " + chalk.bold.white(title.padEnd(width - 2)) + BORDER_COLOR("│"));
62
+ console.log(BORDER_COLOR("│") +
63
+ " " +
64
+ chalk.bold.white(title.padEnd(width - 2)) +
65
+ BORDER_COLOR("│"));
63
66
  console.log(BORDER_COLOR("├" + "─".repeat(width) + "┤"));
64
- lines.forEach(line => {
65
- console.log(BORDER_COLOR("│") + " " + ACCENT_COLOR(line.padEnd(width - 2)) + BORDER_COLOR("│"));
67
+ lines.forEach((line) => {
68
+ console.log(BORDER_COLOR("│") +
69
+ " " +
70
+ ACCENT_COLOR(line.padEnd(width - 2)) +
71
+ BORDER_COLOR("│"));
66
72
  });
67
73
  console.log(bottom);
68
74
  }
@@ -106,7 +112,7 @@ function scanFolderWithTypes(folder) {
106
112
  if (isAuraFunctionHandlerExport(content)) {
107
113
  result[name] = {
108
114
  type: "AuraFunctionHandler",
109
- returnType: inferAuraFunctionReturnType(content)
115
+ returnType: inferAuraFunctionReturnType(content),
110
116
  };
111
117
  }
112
118
  else {
@@ -118,7 +124,9 @@ function scanFolderWithTypes(folder) {
118
124
  }
119
125
  function objectToTypeWithReturn(name, obj, auraType = "AuraFunctionHandler") {
120
126
  const lines = [];
121
- function toFnType(returnType) { return `(...args: any[]) => Promise<${returnType}>`; }
127
+ function toFnType(returnType) {
128
+ return `(...args: any[]) => Promise<${returnType}>`;
129
+ }
122
130
  function recurse(o, indent = " ") {
123
131
  const inner = [];
124
132
  for (const key in o) {
@@ -143,13 +151,16 @@ function objectToTypeWithReturn(name, obj, auraType = "AuraFunctionHandler") {
143
151
  return lines.join("\n");
144
152
  }
145
153
  export function build(silent = false) {
146
- const spin = silent ? null : new Spinner("Scanning functions & generating types...");
154
+ const spin = silent
155
+ ? null
156
+ : new Spinner("Scanning functions & generating types...");
147
157
  if (spin)
148
158
  spin.start();
149
159
  try {
150
160
  const folder = join(process.cwd(), "Aura", "Functions");
151
161
  const structure = scanFolderWithTypes(folder);
152
- const tsType = 'import type { SSEHandler } from "@inflector/aura";\n' + objectToTypeWithReturn("AuraFunctions", structure);
162
+ const tsType = 'import type { SSEHandler } from "@inflector/aura";\n' +
163
+ objectToTypeWithReturn("AuraFunctions", structure);
153
164
  const generatedDir = join(process.cwd(), "Aura", ".generated");
154
165
  if (!fs.existsSync(generatedDir)) {
155
166
  fs.mkdirSync(generatedDir, { recursive: true });
@@ -182,7 +193,7 @@ async function askUser(question) {
182
193
  process.stdout.write(chalk.yellow("? ") + chalk.bold(question) + chalk.dim(" [Y/n] "));
183
194
  for await (const line of console) {
184
195
  const answer = line.trim().toLowerCase();
185
- if (answer === 'y' || answer === 'yes' || answer === '')
196
+ if (answer === "y" || answer === "yes" || answer === "")
186
197
  return true;
187
198
  return false;
188
199
  }
@@ -214,8 +225,8 @@ async function fetchWithAuth(url, options = {}, spinner) {
214
225
  ...options,
215
226
  headers: {
216
227
  ...options.headers,
217
- "aura-deploy-key": token ?? ""
218
- }
228
+ "aura-deploy-key": token ?? "",
229
+ },
219
230
  });
220
231
  if (res.status === 401 || res.status === 403 || res.status === 400) {
221
232
  if (spinner)
@@ -231,14 +242,14 @@ async function fetchWithAuth(url, options = {}, spinner) {
231
242
  if (spinner)
232
243
  spinner.start(); // Restart spinner
233
244
  const newToken = await getToken();
234
- // We don't log "Retrying" if we have a spinner running,
245
+ // We don't log "Retrying" if we have a spinner running,
235
246
  // just update the spinner text if you want, or let it spin.
236
247
  res = await fetch(url, {
237
248
  ...options,
238
249
  headers: {
239
250
  ...options.headers,
240
- "aura-deploy-key": newToken ?? ""
241
- }
251
+ "aura-deploy-key": newToken ?? "",
252
+ },
242
253
  });
243
254
  }
244
255
  else {
@@ -254,12 +265,12 @@ async function fetchWithAuth(url, options = {}, spinner) {
254
265
  // --- Commands ---
255
266
  async function pull() {
256
267
  // 1. Check Auth first
257
- if (!await checkAndLogin())
268
+ if (!(await checkAndLogin()))
258
269
  return;
259
270
  const spin = new Spinner("Pulling workspace configuration...");
260
271
  spin.start();
261
272
  try {
262
- const Config = JSON.parse(fs.readFileSync('./Aura/config.json', 'utf-8'));
273
+ const Config = JSON.parse(fs.readFileSync("./Aura/config.json", "utf-8"));
263
274
  const res = await fetchWithAuth(Config.Url + "/api/client/pull/" + Config.WorkSpace, {}, spin);
264
275
  if (!res.ok) {
265
276
  const text = await res.text();
@@ -286,18 +297,18 @@ async function pull() {
286
297
  log.error(err.message);
287
298
  }
288
299
  }
289
- function init() {
300
+ function init(c = "vite") {
290
301
  log.info("Initializing Aura project...");
291
302
  const filesContent = {
292
303
  config: {
293
- path: './Aura/config.json',
304
+ path: "./Aura/config.json",
294
305
  content: JSON.stringify({
295
306
  Url: "http://localhost:3000",
296
- Project: "your-project-id"
297
- }, null, 2) + "\n"
307
+ WorkSpace: "your-project-id",
308
+ }, null, 2) + "\n",
298
309
  },
299
310
  indexTs: {
300
- path: './Aura/index.ts',
311
+ path: "./Aura/index.ts",
301
312
  content: `import { CreateAura } from "@inflector/aura"
302
313
  import * as AuraConfig from "./config.json"
303
314
  import * as Tables from "./schema.ts"
@@ -306,19 +317,19 @@ export const Aura = CreateAura<AuraFunctions, typeof Tables>({
306
317
  config: AuraConfig,
307
318
  Tables
308
319
  })
309
- `
320
+ `,
310
321
  },
311
322
  schemaTs: {
312
- path: './Aura/schema.ts',
313
- content: `// Define your schema here\n`
314
- }
323
+ path: "./Aura/schema.ts",
324
+ content: `// Define your schema here\n`,
325
+ },
315
326
  };
316
- if (!fs.existsSync('./Aura')) {
317
- fs.mkdirSync('./Aura', { recursive: true });
327
+ if (!fs.existsSync("./Aura")) {
328
+ fs.mkdirSync("./Aura", { recursive: true });
318
329
  }
319
- Object.values(filesContent).forEach(file => {
330
+ Object.values(filesContent).forEach((file) => {
320
331
  if (!fs.existsSync(file.path)) {
321
- fs.writeFileSync(file.path, file.content, 'utf-8');
332
+ fs.writeFileSync(file.path, file.content, "utf-8");
322
333
  console.log(chalk.green(" + ") + chalk.dim(file.path));
323
334
  }
324
335
  else {
@@ -330,15 +341,17 @@ export const Aura = CreateAura<AuraFunctions, typeof Tables>({
330
341
  }
331
342
  async function push() {
332
343
  // 1. Check Auth first
333
- if (!await checkAndLogin())
344
+ if (!(await checkAndLogin()))
334
345
  return;
335
346
  const spin = new Spinner("Preparing deployment...");
336
347
  spin.start();
337
348
  try {
338
- const Config = JSON.parse(fs.readFileSync('./Aura/config.json', 'utf-8'));
349
+ const Config = JSON.parse(fs.readFileSync("./Aura/config.json", "utf-8"));
339
350
  let schemaContent = "";
340
351
  try {
341
- schemaContent = fs.readFileSync('./Aura/schema.ts', 'utf-8').replace("@inflector/aura", "@inflector/optima");
352
+ schemaContent = fs
353
+ .readFileSync("./Aura/schema.ts", "utf-8")
354
+ .replace("@inflector/aura", "@inflector/optima");
342
355
  }
343
356
  catch {
344
357
  spin.stop("Schema missing", false);
@@ -346,7 +359,7 @@ async function push() {
346
359
  }
347
360
  // Utility to convert all paths to POSIX (forward slash) format
348
361
  function toPosixPath(p) {
349
- return p.split('\\').join('/');
362
+ return p.split("\\").join("/");
350
363
  }
351
364
  function collectFunctions(baseDir, baseRel = "") {
352
365
  let results = {};
@@ -367,7 +380,7 @@ async function push() {
367
380
  }
368
381
  return results;
369
382
  }
370
- const functionsDir = './Aura/Functions';
383
+ const functionsDir = "./Aura/Functions";
371
384
  const functions = collectFunctions(functionsDir);
372
385
  const fnCount = Object.keys(functions).length;
373
386
  spin.setText(`Pushing schema & ${fnCount} functions...`);
@@ -378,8 +391,8 @@ async function push() {
378
391
  },
379
392
  body: JSON.stringify({
380
393
  "schema.ts": schemaContent,
381
- functions
382
- })
394
+ functions,
395
+ }),
383
396
  }, spin); // Pass spinner
384
397
  if (!res.ok) {
385
398
  const text = await res.text();
@@ -404,13 +417,13 @@ async function ping() {
404
417
  const spin = new Spinner("Pinging server...");
405
418
  spin.start();
406
419
  try {
407
- const Config = JSON.parse(fs.readFileSync('./Aura/config.json', 'utf-8'));
420
+ const Config = JSON.parse(fs.readFileSync("./Aura/config.json", "utf-8"));
408
421
  const token = await getToken();
409
422
  // Start Timer
410
423
  const start = performance.now();
411
424
  // Use standard fetch here to avoid forcing login for simple ping
412
425
  const res = await fetch(Config.Url + "/api/ping", {
413
- headers: token ? { "aura-deploy-key": token } : {}
426
+ headers: token ? { "aura-deploy-key": token } : {},
414
427
  });
415
428
  // End Timer
416
429
  const end = performance.now();
@@ -493,7 +506,7 @@ function login() {
493
506
  await Bun.secrets.set({
494
507
  name: `aura-deploy-key/${Config.Url}-${Config.WorkSpace}`,
495
508
  service: "aura@inflector",
496
- value: loginToken
509
+ value: loginToken,
497
510
  });
498
511
  if (spin)
499
512
  spin.stop("Login successful", true);
@@ -511,6 +524,142 @@ function login() {
511
524
  };
512
525
  });
513
526
  }
527
+ import { createServer as createViteServer, mergeConfig, loadConfigFromFile, } from "vite";
528
+ import path from "node:path";
529
+ export async function dev() {
530
+ let Config;
531
+ try {
532
+ Config = JSON.parse(fs.readFileSync("./Aura/config.json", "utf-8"));
533
+ }
534
+ catch {
535
+ log.error("Config file not found. Run `aura init` first.");
536
+ return;
537
+ }
538
+ // Load user Vite config
539
+ const configFile = path.resolve(process.cwd(), "vite.config.ts");
540
+ const configResult = await loadConfigFromFile({ command: "serve", mode: "development" }, configFile);
541
+ const userConfig = configResult?.config;
542
+ if (!userConfig) {
543
+ log.error("Could not load vite.config.ts");
544
+ return;
545
+ }
546
+ const AURA_KEY = process.env.AURA_KEY;
547
+ // Merge proxy into their server config
548
+ const finalConfig = mergeConfig(userConfig, {
549
+ // FIX: Tell Vite NOT to try loading the config file again,
550
+ // because we already loaded it manually above.
551
+ configFile: false,
552
+ server: {
553
+ proxy: {
554
+ "/api": {
555
+ target: Config.Url,
556
+ changeOrigin: true,
557
+ secure: false,
558
+ configure(proxy, _options) {
559
+ proxy.on("proxyReq", (proxyReq, req, res) => {
560
+ if (AURA_KEY) {
561
+ proxyReq.setHeader("Authorization", `Bearer ${AURA_KEY}`);
562
+ }
563
+ });
564
+ },
565
+ },
566
+ },
567
+ },
568
+ });
569
+ const vite = await createViteServer(finalConfig);
570
+ // Note: bindCLIShortcuts exists in Vite 5+.
571
+ // If you are on an older version, remove this line.
572
+ if (vite.bindCLIShortcuts) {
573
+ vite.bindCLIShortcuts({ print: true });
574
+ }
575
+ await vite.listen();
576
+ vite.printUrls();
577
+ }
578
+ async function start() {
579
+ let Config;
580
+ try {
581
+ Config = JSON.parse(fs.readFileSync("./Aura/config.json", "utf-8"));
582
+ }
583
+ catch (err) {
584
+ console.log(chalk.red("✖") + " Config file not found. Run `aura init` first.");
585
+ process.exit(1);
586
+ }
587
+ const configFile = path.resolve(process.cwd(), "vite.config.ts");
588
+ const configResult = await loadConfigFromFile({ command: "serve", mode: "development" }, configFile);
589
+ const userConfig = configResult?.config;
590
+ const upstreamUrl = Config.Url.replace(/\/$/, "");
591
+ const AURA_KEY = process.env.AURA_KEY;
592
+ Bun.serve({
593
+ hostname: "0.0.0.0",
594
+ port: userConfig?.preview?.port || 80,
595
+ idleTimeout: 0,
596
+ async fetch(req) {
597
+ const url = new URL(req.url);
598
+ // --- API PROXY ---
599
+ if (url.pathname.startsWith("/api")) {
600
+ const targetUrl = `${upstreamUrl}${url.pathname}${url.search}`;
601
+ const headers = new Headers(req.headers);
602
+ headers.delete("host");
603
+ headers.set("x-forwarded-host", req.headers.get("x-forwarded-host") ?? req.headers.get("host"));
604
+ const forwardedProto = req.headers.get("x-forwarded-proto") ??
605
+ req.headers.get("x-forwarded-scheme") ??
606
+ "http";
607
+ headers.set("x-forwarded-proto", forwardedProto);
608
+ // Inject Authorization
609
+ if (AURA_KEY)
610
+ headers.set("Authorization", `Bearer ${AURA_KEY}`);
611
+ try {
612
+ return await fetch(targetUrl, {
613
+ method: req.method,
614
+ headers,
615
+ body: req.method === "GET" || req.method === "HEAD"
616
+ ? undefined
617
+ : req.body,
618
+ });
619
+ }
620
+ catch {
621
+ return new Response(JSON.stringify({ error: "Upstream Proxy Failed" }), { status: 502, headers: { "Content-Type": "application/json" } });
622
+ }
623
+ }
624
+ // --- STATIC FILES ---
625
+ const filePath = `./dist${url.pathname}`;
626
+ const file = Bun.file(filePath);
627
+ if (await file.exists()) {
628
+ return new Response(file, {
629
+ headers: { "Content-Type": getMimeType(filePath) },
630
+ });
631
+ }
632
+ // --- SPA FALLBACK ---
633
+ const indexFile = Bun.file("./dist/index.html");
634
+ if (await indexFile.exists()) {
635
+ return new Response(indexFile, {
636
+ headers: { "Content-Type": "text/html" },
637
+ });
638
+ }
639
+ return new Response("Not Found", { status: 404 });
640
+ },
641
+ });
642
+ console.log(`Server running on http://localhost:${userConfig?.preview?.port || 80}`);
643
+ console.log(chalk.dim(` • Proxying /api → ${upstreamUrl}`));
644
+ console.log(chalk.dim(` • Serving static → ./dist`));
645
+ function getMimeType(path) {
646
+ if (path.endsWith(".js"))
647
+ return "application/javascript";
648
+ if (path.endsWith(".css"))
649
+ return "text/css";
650
+ if (path.endsWith(".html"))
651
+ return "text/html";
652
+ if (path.endsWith(".json"))
653
+ return "application/json";
654
+ if (path.endsWith(".png"))
655
+ return "image/png";
656
+ if (path.endsWith(".jpg") || path.endsWith(".jpeg"))
657
+ return "image/jpeg";
658
+ if (path.endsWith(".svg"))
659
+ return "image/svg+xml";
660
+ return "application/octet-stream";
661
+ }
662
+ }
514
663
  async function main() {
515
664
  const args = process.argv.slice(2);
516
665
  const Command = args[0];
@@ -535,6 +684,10 @@ async function main() {
535
684
  case "login":
536
685
  await login();
537
686
  break;
687
+ case "dev":
688
+ return await dev();
689
+ case "start":
690
+ return await start();
538
691
  case undefined:
539
692
  log.info("Available commands: init, pull, push, build, login, ping");
540
693
  break;
@@ -547,6 +700,9 @@ async function main() {
547
700
  log.error("Unexpected Error: " + e.message);
548
701
  }
549
702
  log.br();
550
- process.exit(0);
703
+ // Only exit for short-lived commands
704
+ if (!["start", "dev"].includes(Command ?? "")) {
705
+ process.exit(0);
706
+ }
551
707
  }
552
708
  main();
@@ -1,10 +1,8 @@
1
1
  import { Infer, InferAdd, Where } from "@inflector/optima";
2
2
  declare class RemoteTable<TDef extends Record<string, any>> {
3
- private URL;
4
3
  private Name;
5
4
  private WorkSpace;
6
- private getAuthHeaders;
7
- constructor(url: string, name: string, workspace: string);
5
+ constructor(name: string, workspace: string);
8
6
  Get: () => {
9
7
  where: Where<{ [K_1 in keyof TDef as K_1 extends `__${string}` ? never : TDef[K_1] extends import("@inflector/optima").ColumnBuilder<any, infer C extends import("@inflector/optima").ColumnConfig, any> ? C["notnull"] extends true ? K_1 : never : never]: TDef[K_1] extends import("@inflector/optima").ColumnBuilder<infer U, any, any> ? U : never; } & { [K_2 in keyof TDef as K_2 extends `__${string}` ? never : TDef[K_2] extends import("@inflector/optima").ColumnBuilder<any, infer C extends import("@inflector/optima").ColumnConfig, any> ? C["notnull"] extends true ? never : K_2 : never]: TDef[K_2] extends import("@inflector/optima").ColumnBuilder<infer U, any, any> ? U | null : never; } extends infer T ? { [K in keyof T]: T[K]; } : never> extends boolean ? () => {
10
8
  limit: (arg: number) => {
@@ -254,6 +252,6 @@ declare class RemoteTable<TDef extends Record<string, any>> {
254
252
  }
255
253
  export declare const AuraDatabase: <T extends {
256
254
  [key: string]: Record<string, any>;
257
- }>(url: string, workspace: string, tables: T) => { [K in keyof T]: RemoteTable<T[K]>; };
255
+ }>(workspace: string, tables: T) => { [K in keyof T]: RemoteTable<T[K]>; };
258
256
  export {};
259
257
  //# sourceMappingURL=database.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAS,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAMjE,cAAM,WAAW,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,cAAc;gBAKV,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMxD,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wvBAYF;IACD,MAAM;;ovBAYL;IACD,MAAM;;wvBAYL;IACD,GAAG,GAAI,QAAQ,QAAQ,CAAC,IAAI,CAAC,gvBAe5B;IACD,OAAO,GAAI,QAAQ,QAAQ,CAAC,IAAI,CAAC,EAAE,gvBAelC;IACD,MAAM,GAAI,QAAQ,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;;wvBAarC;IACD,KAAK;;4BAYJ;IACD,KAAK;;6BAYJ;IACD,SAAS,GAAI,UAAU,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,CAAA;KAAE,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,EAAE,OAAO,OAAO,gBA+B7J;CACJ;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,EACzE,KAAK,MAAM,EACX,WAAW,MAAM,EACjB,QAAQ,CAAC,QAEe,CAAC,kCAY5B,CAAA"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAS,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAKlE,cAAM,WAAW,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAChD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAS;gBAEd,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAI3C,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wvBAsBD;IACF,MAAM;;ovBAgBJ;IACF,MAAM;;wvBAgBJ;IACF,GAAG,GAAI,QAAQ,QAAQ,CAAC,IAAI,CAAC,gvBAiB3B;IACF,OAAO,GAAI,QAAQ,QAAQ,CAAC,IAAI,CAAC,EAAE,gvBAiBjC;IACF,MAAM,GAAI,QAAQ,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;;wvBAiBpC;IACF,KAAK;;4BAgBH;IACF,KAAK;;6BAgBH;IACF,SAAS,GACP,UACI,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,CAAA;KAAE,KAAK,GAAG,CAAC,GACnD,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,EACxD,QAAQ,GAAG,EACX,OAAO,OAAO,gBAgCd;CACH;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,EAC3E,WAAW,MAAM,EACjB,QAAQ,CAAC,QAEe,CAAC,kCAW1B,CAAC"}
package/dist/database.js CHANGED
@@ -1,105 +1,82 @@
1
1
  import { createFluentBuilder } from "./fluent";
2
2
  import axios from "axios";
3
- import { getToken } from "./auth";
4
3
  import { SSE } from "sse.js";
5
4
  class RemoteTable {
6
- URL;
7
5
  Name;
8
6
  WorkSpace;
9
- getAuthHeaders() {
10
- const token = getToken(this.WorkSpace);
11
- return token ? { Authorization: `Bearer ${token}` } : {};
12
- }
13
- constructor(url, name, workspace) {
14
- this.URL = url;
7
+ constructor(name, workspace) {
15
8
  this.Name = name;
16
9
  this.WorkSpace = workspace;
17
10
  }
18
11
  Get = () => {
19
12
  return createFluentBuilder(async (data) => {
20
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
21
- operation: 'Get',
13
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
14
+ operation: "Get",
22
15
  settings: data,
23
- }, {
24
- headers: this.getAuthHeaders()
25
- })).data;
16
+ }, { withCredentials: true })).data;
26
17
  });
27
18
  };
28
19
  GetOne = () => {
29
20
  return createFluentBuilder(async (data) => {
30
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
31
- operation: 'GetOne',
21
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
22
+ operation: "GetOne",
32
23
  settings: data,
33
- }, {
34
- headers: this.getAuthHeaders()
35
- })).data;
24
+ }, { withCredentials: true })).data;
36
25
  });
37
26
  };
38
27
  Delete = () => {
39
28
  return createFluentBuilder(async (data) => {
40
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
41
- operation: 'Delete',
29
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
30
+ operation: "Delete",
42
31
  settings: { ...data, returning: true },
43
- }, {
44
- headers: this.getAuthHeaders()
45
- })).data;
32
+ }, { withCredentials: true })).data;
46
33
  });
47
34
  };
48
35
  Add = (record) => {
49
36
  return createFluentBuilder(async () => {
50
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
51
- operation: 'Add',
37
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
38
+ operation: "Add",
52
39
  settings: {
53
- returning: true
40
+ returning: true,
54
41
  },
55
- data: record
56
- }, {
57
- headers: this.getAuthHeaders()
58
- })).data;
42
+ data: record,
43
+ }, { withCredentials: true })).data;
59
44
  });
60
45
  };
61
46
  AddMany = (record) => {
62
47
  return createFluentBuilder(async () => {
63
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
64
- operation: 'AddMany',
48
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
49
+ operation: "AddMany",
65
50
  settings: {
66
- returning: true
51
+ returning: true,
67
52
  },
68
- data: record
69
- }, {
70
- headers: this.getAuthHeaders()
71
- })).data;
53
+ data: record,
54
+ }, { withCredentials: true })).data;
72
55
  });
73
56
  };
74
57
  Update = (record) => {
75
58
  return createFluentBuilder(async (data) => {
76
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
77
- operation: 'Update',
59
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
60
+ operation: "Update",
78
61
  settings: { ...data, returning: true },
79
- data: record
80
- }, {
81
- headers: this.getAuthHeaders()
82
- })).data;
62
+ data: record,
63
+ }, { withCredentials: true })).data;
83
64
  });
84
65
  };
85
66
  Count = () => {
86
67
  return createFluentBuilder(async (data) => {
87
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
88
- operation: 'Count',
68
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
69
+ operation: "Count",
89
70
  settings: data,
90
- }, {
91
- headers: this.getAuthHeaders()
92
- })).data;
71
+ }, { withCredentials: true })).data;
93
72
  });
94
73
  };
95
74
  Exist = () => {
96
75
  return createFluentBuilder(async (data) => {
97
- return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
98
- operation: 'Exist',
76
+ return (await axios.post(`/api/db/${this.WorkSpace}/${this.Name}`, {
77
+ operation: "Exist",
99
78
  settings: data,
100
- }, {
101
- headers: this.getAuthHeaders()
102
- })).data;
79
+ }, { withCredentials: true })).data;
103
80
  });
104
81
  };
105
82
  Subscribe = (callback, where, init) => {
@@ -110,9 +87,9 @@ class RemoteTable {
110
87
  params.push("init=true");
111
88
  const query = params.length ? "?" + params.join("&") : "";
112
89
  const tableName = this.Name;
113
- const url = `${this.URL}/api/db/${this.WorkSpace}/${this.Name}${query}`;
90
+ const url = `/api/db/${this.WorkSpace}/${this.Name}${query}`;
114
91
  const source = new SSE(url, {
115
- headers: this.getAuthHeaders(),
92
+ withCredentials: true,
116
93
  });
117
94
  source.addEventListener(tableName, (event) => {
118
95
  try {
@@ -123,8 +100,8 @@ class RemoteTable {
123
100
  // Ignore parse errors
124
101
  }
125
102
  });
126
- source.addEventListener('error', (error) => {
127
- console.error('SSE stream error:', error);
103
+ source.addEventListener("error", (error) => {
104
+ console.error("SSE stream error:", error);
128
105
  });
129
106
  source.stream();
130
107
  return () => {
@@ -132,12 +109,12 @@ class RemoteTable {
132
109
  };
133
110
  };
134
111
  }
135
- export const AuraDatabase = (url, workspace, tables) => {
112
+ export const AuraDatabase = (workspace, tables) => {
136
113
  const Tables = {};
137
114
  for (const key in tables) {
138
115
  if (Object.prototype.hasOwnProperty.call(tables, key)) {
139
116
  // @ts-ignore
140
- Tables[key] = new RemoteTable(url, key, workspace);
117
+ Tables[key] = new RemoteTable(key, workspace);
141
118
  }
142
119
  }
143
120
  return Tables;
@@ -1,2 +1,2 @@
1
- export declare function createFunctionHandler(baseUrl: string, workspace: string, functionsFolder?: string): any;
1
+ export declare function createFunctionHandler(workspace: string, functionsFolder?: string): any;
2
2
  //# sourceMappingURL=function.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../src/function.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,GAAG,CAyHvG"}
1
+ {"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../src/function.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAE,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,GAAG,CAmHvF"}
package/dist/function.js CHANGED
@@ -1,10 +1,4 @@
1
- export function createFunctionHandler(baseUrl, workspace, functionsFolder) {
2
- // Helper to get token for Bearer auth
3
- const getToken = () => {
4
- if (typeof window === 'undefined')
5
- return '';
6
- return localStorage.getItem(`aura_bearer_token_${workspace}`) || '';
7
- };
1
+ export function createFunctionHandler(workspace, functionsFolder) {
8
2
  const handler = new Proxy({}, {
9
3
  get(_, prop) {
10
4
  return createNestedProxy([prop]);
@@ -18,22 +12,20 @@ export function createFunctionHandler(baseUrl, workspace, functionsFolder) {
18
12
  },
19
13
  // 1. Remove 'async' here to prevent native Promise wrapping
20
14
  apply(_, __, args) {
21
- const url = [baseUrl, "api", "fn", workspace, ...path].join("/");
15
+ const url = ["api", "fn", workspace, ...path].join("/");
22
16
  const isFormData = args != null && args.length === 1 && args[0] instanceof FormData;
23
- const body = isFormData ? args[0] : JSON.stringify(args ?? {});
24
- const token = getToken();
17
+ const body = isFormData ? args[0] : JSON.stringify(args[0] ?? {});
25
18
  const headers = {
26
19
  "Accept": "text/event-stream,application/json",
27
20
  };
28
21
  if (!isFormData)
29
22
  headers["Content-Type"] = "application/json";
30
- if (token)
31
- headers["Authorization"] = `Bearer ${token}`;
32
23
  // 2. Start the fetch properly (without await)
33
24
  const requestPromise = fetch(url, {
34
25
  method: "POST",
35
26
  body,
36
27
  headers,
28
+ credentials: "include"
37
29
  });
38
30
  // 3. Return a custom "Thenable" object with full Promise interface
39
31
  const thenable = {
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/hooks/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAS,MAAM,IAAI,CAAA;AAK3C,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAkB5B,wBAAgB,QAAQ,CACtB,IAAI,SAAS,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAElF,KAAK,EAAE,IAAI,EACX,OAAO,CAAC,EAAE;IACR,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;CACnE,guBAwDF;AAED,wBAAgB,SAAS,CACvB,IAAI,SAAS,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAElF,KAAK,EAAE,IAAI,EACX,OAAO,EAAE;IACP,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;CACnE,0uBAqDF;AAED,eAAO,MAAM,OAAO,GAAI,UAAU,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;;;;;;;;;aAGjF,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,UAAU,GAAG,QAGvC,CAAA"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/hooks/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAS,MAAM,IAAI,CAAA;AAI3C,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAkB5B,wBAAgB,QAAQ,CACtB,IAAI,SAAS,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAElF,KAAK,EAAE,IAAI,EACX,OAAO,CAAC,EAAE;IACR,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;CACnE,guBAkDF;AAED,wBAAgB,SAAS,CACvB,IAAI,SAAS,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAElF,KAAK,EAAE,IAAI,EACX,OAAO,EAAE;IACP,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;CACnE,0uBAgDF;AAED,eAAO,MAAM,OAAO,GAAI,UAAU,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;;;;;;;;;aAGjF,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,UAAU,GAAG,QAGvC,CAAA"}
@@ -1,4 +1,3 @@
1
- import { authTokenVersion } from '../auth';
2
1
  import { useStore } from '@nanostores/react';
3
2
  import { useEffect, useState, useRef } from 'react';
4
3
  function deepEqual(a, b) {
@@ -20,8 +19,6 @@ function deepEqual(a, b) {
20
19
  }
21
20
  export function useTable(table, Options) {
22
21
  const [data, setData] = useState([]);
23
- // Subscribe to token version changes for reactivity
24
- const sessionVersion = useStore(authTokenVersion);
25
22
  // Use ref to track where clause changes with deep comparison
26
23
  const whereRef = useRef(Options?.where);
27
24
  const whereString = JSON.stringify(Options?.where);
@@ -30,9 +27,6 @@ export function useTable(table, Options) {
30
27
  }
31
28
  useEffect(() => {
32
29
  // Wait for auth to be initialized
33
- if (sessionVersion < 0)
34
- return;
35
- // Subscribe to table
36
30
  const unsubscribe = table.Subscribe((event) => {
37
31
  setData((prev) => {
38
32
  if (!prev)
@@ -58,13 +52,11 @@ export function useTable(table, Options) {
58
52
  return () => {
59
53
  unsubscribe();
60
54
  };
61
- }, [table, whereString, sessionVersion]); // <--- include sessionVersion here
55
+ }, [table, whereString]); // <--- include sessionVersion here
62
56
  return data;
63
57
  }
64
58
  export function useRecord(table, Options) {
65
59
  const [data, setData] = useState(undefined);
66
- // Subscribe to token version changes for reactivity
67
- const sessionVersion = useStore(authTokenVersion);
68
60
  // Use ref to track where clause changes with deep comparison
69
61
  const whereRef = useRef(Options.where);
70
62
  const whereString = JSON.stringify(Options.where);
@@ -72,9 +64,6 @@ export function useRecord(table, Options) {
72
64
  whereRef.current = Options.where;
73
65
  }
74
66
  useEffect(() => {
75
- // Wait for auth to be initialized
76
- if (sessionVersion < 0)
77
- return;
78
67
  const unsubscribe = table.Subscribe((event) => {
79
68
  setData((prev) => {
80
69
  if (!prev && event.action !== 'Get' && event.action !== 'Add')
@@ -100,7 +89,7 @@ export function useRecord(table, Options) {
100
89
  });
101
90
  }, Options.where, true);
102
91
  return () => unsubscribe();
103
- }, [table, whereString, sessionVersion]); // <--- include sessionVersion
92
+ }, [table, whereString]); // <--- include sessionVersion
104
93
  return data;
105
94
  }
106
95
  export const useUser = (provider) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,cAAc,yBAAyB,CAAC;AACxC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAE9B,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IACnD,MAAM,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACF,MAAM,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IAClD,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,QAAQ,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACxC,IAAI,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,UAAU,GACnB,CAAC,EACD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAE7B,QAAQ,gBAAgB,CAAC,CAAC,CAAC,KAC5B,YAAY,CAAC,CAAC,EAAE,CAAC,CAgBnB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,cAAc,yBAAyB,CAAC;AACxC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAE9B,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IACnD,MAAM,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACF,MAAM,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IAClD,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,QAAQ,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACxC,IAAI,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,UAAU,GACnB,CAAC,EACD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAE7B,QAAQ,gBAAgB,CAAC,CAAC,CAAC,KAC5B,YAAY,CAAC,CAAC,EAAE,CAAC,CAiBnB,CAAC"}
package/dist/index.js CHANGED
@@ -14,10 +14,11 @@ export const CreateAura = (Config) => {
14
14
  throw new Error("CreateAura: Config.WorkSpace is required and must be a string");
15
15
  }
16
16
  const auth = AuraAuth(Config.config.Url, Config.config.WorkSpace);
17
+ // const auth = AuraAuth(Config.config.WorkSpace);
17
18
  return {
18
- Database: AuraDatabase(Config.config.Url, Config.config.WorkSpace, Config.Tables),
19
- Function: createFunctionHandler(Config.config.Url, Config.config.WorkSpace),
19
+ Database: AuraDatabase(Config.config.WorkSpace, Config.Tables),
20
+ Function: createFunctionHandler(Config.config.WorkSpace),
20
21
  Auth: auth,
21
- Storage: AuraStorage(Config.config.Url, Config.config.WorkSpace, auth.Signal),
22
+ Storage: AuraStorage(Config.config.WorkSpace, auth.Signal),
22
23
  };
23
24
  };
package/dist/storage.d.ts CHANGED
@@ -7,7 +7,7 @@ type FileAura = {
7
7
  UploadedBy?: string;
8
8
  UploadedAt: Date;
9
9
  };
10
- export declare const AuraStorage: (url: string, workspace: string, userAtom: any) => {
10
+ export declare const AuraStorage: (workspace: string, userAtom: any) => {
11
11
  Upload: (file?: File, config?: {
12
12
  openSelector?: boolean;
13
13
  allowedTypes?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,WAAW,MAAM,EAAE,UAAU,GAAG;oBAQ1D,IAAI,WACH;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAC5D,OAAO,CAAC,QAAQ,CAAC;eA6DL,MAAM;iBAGE,MAAM;cAYT,MAAM,KAAG,OAAO,CAAC,QAAQ,CAAC;gBAY1B,OAAO,CAAC,QAAQ,EAAE,CAAC;6BAYvB,IAAI,EAAE,WACN;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;iBAmD5C,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;mBAYvB,MAAM,aAAY,OAAO,aAAoB,OAAO;;;;;CA6BhF,CAAA"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAIF,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,EAAE,UAAU,GAAG;oBAEjD,IAAI,WACH;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAC1D,OAAO,CAAC,QAAQ,CAAC;eAmEP,MAAM;iBAGE,MAAM;cAkBT,MAAM,KAAG,OAAO,CAAC,QAAQ,CAAC;gBAkB1B,OAAO,CAAC,QAAQ,EAAE,CAAC;6BAkBzB,IAAI,EAAE,WACN;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;iBAqD1C,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;mBAmBtC,MAAM,aACA,OAAO,aACN,OAAO;;;;;CAmCvB,CAAC"}
package/dist/storage.js CHANGED
@@ -1,11 +1,5 @@
1
1
  import axios from "axios";
2
- import { getToken } from "./auth";
3
- export const AuraStorage = (url, workspace, userAtom) => {
4
- // Helper to get auth headers for Bearer token
5
- const getAuthHeaders = () => {
6
- const token = getToken(workspace);
7
- return token ? { Authorization: `Bearer ${token}` } : {};
8
- };
2
+ export const AuraStorage = (workspace, userAtom) => {
9
3
  const UploadFn = async (file, config = {}) => {
10
4
  if (!userAtom.get().data)
11
5
  throw new Error("User not authenticated");
@@ -37,7 +31,9 @@ export const AuraStorage = (url, workspace, userAtom) => {
37
31
  fd.set("operation", "Upload");
38
32
  fd.set("owner", userAtom.get().data.user.id);
39
33
  fd.set("file", selectedFile);
40
- const result = (await axios.post(url + "/api/storage/" + workspace, fd, { headers: getAuthHeaders() })).data;
34
+ const result = (await axios.post("/api/storage/" + workspace, fd, {
35
+ withCredentials: true,
36
+ })).data;
41
37
  resolve(result);
42
38
  cleanup();
43
39
  }
@@ -47,7 +43,7 @@ export const AuraStorage = (url, workspace, userAtom) => {
47
43
  }
48
44
  };
49
45
  // Handle cancel - cleanup after a delay if no file selected
50
- input.addEventListener('cancel', () => {
46
+ input.addEventListener("cancel", () => {
51
47
  reject(new Error("File selection cancelled"));
52
48
  cleanup();
53
49
  });
@@ -59,52 +55,52 @@ export const AuraStorage = (url, workspace, userAtom) => {
59
55
  fd.set("operation", "Upload");
60
56
  fd.set("owner", userAtom.get().data.user.id);
61
57
  fd.set("file", file);
62
- return (await axios.post(url + "/api/storage/" + workspace, fd, {
63
- headers: getAuthHeaders()
58
+ return (await axios.post("/api/storage/" + workspace, fd, {
59
+ withCredentials: true
64
60
  })).data;
65
61
  }
66
62
  };
67
63
  return {
68
64
  Upload: UploadFn,
69
65
  File: (id) => {
70
- return `${url}/api/storage/${workspace}/${id}`;
66
+ return `/api/storage/${workspace}/${id}`;
71
67
  },
72
68
  Delete: async (id) => {
73
69
  if (!userAtom.get().data)
74
70
  throw new Error("User not authenticated");
75
- return (await axios.post(url + "/api/storage/" + workspace, {
71
+ return (await axios.post("/api/storage/" + workspace, {
76
72
  operation: "Delete",
77
73
  settings: {
78
74
  FileID: id,
79
- Owner: userAtom.get().data.user.id
80
- }
75
+ Owner: userAtom.get().data.user.id,
76
+ },
81
77
  }, {
82
- headers: getAuthHeaders()
78
+ withCredentials: true
83
79
  })).data;
84
80
  },
85
81
  Get: async (id) => {
86
82
  if (!userAtom.get().data)
87
83
  throw new Error("User not authenticated");
88
- return (await axios.post(url + "/api/storage/" + workspace, {
84
+ return (await axios.post("/api/storage/" + workspace, {
89
85
  operation: "Get",
90
86
  settings: {
91
87
  FileID: id,
92
- Owner: userAtom.get().data.user.id
93
- }
88
+ Owner: userAtom.get().data.user.id,
89
+ },
94
90
  }, {
95
- headers: getAuthHeaders()
91
+ withCredentials: true
96
92
  })).data;
97
93
  },
98
94
  List: async () => {
99
95
  if (!userAtom.get().data)
100
96
  throw new Error("User not authenticated");
101
- return (await axios.post(url + "/api/storage/" + workspace, {
97
+ return (await axios.post("/api/storage/" + workspace, {
102
98
  operation: "List",
103
99
  settings: {
104
- Owner: userAtom.get().data.user.id
105
- }
100
+ Owner: userAtom.get().data.user.id,
101
+ },
106
102
  }, {
107
- headers: getAuthHeaders()
103
+ withCredentials: true
108
104
  })).data;
109
105
  },
110
106
  UploadMultiple: async (files, config = {}) => {
@@ -133,7 +129,7 @@ export const AuraStorage = (url, workspace, userAtom) => {
133
129
  cleanup();
134
130
  return;
135
131
  }
136
- const uploadResults = await Promise.all(selectedFiles.map(f => UploadFn(f, config)));
132
+ const uploadResults = await Promise.all(selectedFiles.map((f) => UploadFn(f, config)));
137
133
  resolve(uploadResults);
138
134
  }
139
135
  catch (e) {
@@ -144,7 +140,7 @@ export const AuraStorage = (url, workspace, userAtom) => {
144
140
  }
145
141
  };
146
142
  // Handle cancel
147
- input.addEventListener('cancel', () => {
143
+ input.addEventListener("cancel", () => {
148
144
  reject(new Error("File selection cancelled"));
149
145
  cleanup();
150
146
  });
@@ -153,27 +149,27 @@ export const AuraStorage = (url, workspace, userAtom) => {
153
149
  }
154
150
  else {
155
151
  // Use given files directly
156
- return await Promise.all(files.map(f => UploadFn(f, config)));
152
+ return await Promise.all(files.map((f) => UploadFn(f, config)));
157
153
  }
158
154
  },
159
155
  Exists: async (id) => {
160
156
  if (!userAtom.get().data)
161
157
  throw new Error("User not authenticated");
162
- return (await axios.post(url + "/api/storage/" + workspace, {
158
+ return (await axios.post("/api/storage/" + workspace, {
163
159
  operation: "Exists",
164
160
  settings: {
165
161
  FileID: id,
166
- Owner: userAtom.get().data.user.id
167
- }
162
+ Owner: userAtom.get().data.user.id,
163
+ },
168
164
  }, {
169
- headers: getAuthHeaders()
165
+ withCredentials: true
170
166
  })).data;
171
167
  },
172
168
  Download: async (id, download = true, asBase64) => {
173
169
  try {
174
- const response = await axios.get(`${url}/api/storage/${workspace}/${id}?download=${download ? '1' : '0'}&base64=${asBase64 ? '1' : '0'}`, {
170
+ const response = await axios.get(`/api/storage/${workspace}/${id}?download=${download ? "1" : "0"}&base64=${asBase64 ? "1" : "0"}`, {
175
171
  responseType: "blob",
176
- headers: getAuthHeaders()
172
+ withCredentials: true
177
173
  });
178
174
  // Extract filename from content-disposition
179
175
  const contentDisposition = response.headers["content-disposition"];
@@ -186,11 +182,13 @@ export const AuraStorage = (url, workspace, userAtom) => {
186
182
  return {
187
183
  blob: response.data,
188
184
  fileName,
189
- mimeType: response.headers["content-type"] || "application/octet-stream"
185
+ mimeType: response.headers["content-type"] || "application/octet-stream",
190
186
  };
191
187
  }
192
188
  catch (error) {
193
- if (error.response && error.response.data && error.response.data.message) {
189
+ if (error.response &&
190
+ error.response.data &&
191
+ error.response.data.message) {
194
192
  throw new Error(error.response.data.message);
195
193
  }
196
194
  throw new Error("File not found");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inflector/aura",
3
- "version": "0.1.20",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -44,6 +44,7 @@
44
44
  "eventsource": "^4.1.0",
45
45
  "sse.js": "^2.7.2",
46
46
  "tsx": "^4.20.4",
47
+ "vite": "^7.3.1",
47
48
  "zod": "^3.25.67"
48
49
  }
49
50
  }