@inflector/aura 0.1.13 → 0.1.15
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 +19 -11
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +53 -9
- package/dist/database.d.ts +1 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +19 -11
- package/dist/function.d.ts.map +1 -1
- package/dist/function.js +25 -5
- package/dist/hooks/react.d.ts +1 -1
- package/dist/hooks/react.d.ts.map +1 -1
- package/dist/hooks/react.js +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/storage.d.ts +4 -4
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +44 -18
- package/package.json +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -3,17 +3,26 @@ interface SessionEventsType {
|
|
|
3
3
|
on(event: SessionEvent, callback: () => void): () => void;
|
|
4
4
|
emit(event: SessionEvent): void;
|
|
5
5
|
}
|
|
6
|
+
declare const getTokenKey: (workspace: string) => string;
|
|
7
|
+
declare const getToken: (workspace: string) => string;
|
|
8
|
+
declare const setToken: (workspace: string, token: string | null) => void;
|
|
9
|
+
export { getToken, setToken, getTokenKey };
|
|
6
10
|
export declare const SessionEvents: SessionEventsType;
|
|
7
11
|
export declare const AuraAuth: (url: string, workspace: string) => {
|
|
8
|
-
Logout:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
Logout: () => Promise<{
|
|
13
|
+
data: {
|
|
14
|
+
success: boolean;
|
|
15
|
+
};
|
|
16
|
+
error: null;
|
|
17
|
+
} | {
|
|
18
|
+
data: null;
|
|
19
|
+
error: {
|
|
20
|
+
code?: string | undefined | undefined;
|
|
21
|
+
message?: string | undefined | undefined;
|
|
22
|
+
status: number;
|
|
23
|
+
statusText: string;
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
17
26
|
Email: {
|
|
18
27
|
SignUp: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<{
|
|
19
28
|
name: string;
|
|
@@ -665,7 +674,7 @@ export declare const AuraAuth: (url: string, workspace: string) => {
|
|
|
665
674
|
statusText: string;
|
|
666
675
|
};
|
|
667
676
|
}>;
|
|
668
|
-
|
|
677
|
+
Reddit: (data?: Omit<import("better-auth").Prettify<{
|
|
669
678
|
provider: (string & {}) | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "huggingface" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linear" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "vercel";
|
|
670
679
|
callbackURL?: string | undefined;
|
|
671
680
|
newUserCallbackURL?: string | undefined;
|
|
@@ -1238,5 +1247,4 @@ export declare const AuraAuth: (url: string, workspace: string) => {
|
|
|
1238
1247
|
}, FetchOptions["throw"] extends true ? true : false>>;
|
|
1239
1248
|
};
|
|
1240
1249
|
};
|
|
1241
|
-
export {};
|
|
1242
1250
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAKA,KAAK,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElD,UAAU,iBAAiB;IACzB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CACjC;AAGD,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAKA,KAAK,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElD,UAAU,iBAAiB;IACzB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CACjC;AAGD,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,SAOxD,CAAC;AAGF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AAI3C,eAAO,MAAM,aAAa,EAAE,iBAuCxB,CAAC;AACL,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,WAAW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAwE3B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;yBAQxB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAtGpD,CAAD;iBAAe,CAAC;;;;;;;;;;;;;;;;qBAlB2B,CAAC;;;;;;;;;;;;;;;;CAmM9C,CAAC"}
|
package/dist/auth.js
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import { createAuthClient } from "better-auth/client";
|
|
2
2
|
import { anonymousClient } from "better-auth/client/plugins";
|
|
3
3
|
import { computed } from "nanostores";
|
|
4
|
+
// Token storage key - unique per workspace to avoid conflicts
|
|
5
|
+
const getTokenKey = (workspace) => `aura_bearer_token_${workspace}`;
|
|
6
|
+
// Helper to get/set token from localStorage (with SSR safety)
|
|
7
|
+
const getToken = (workspace) => {
|
|
8
|
+
if (typeof window === 'undefined')
|
|
9
|
+
return '';
|
|
10
|
+
return localStorage.getItem(getTokenKey(workspace)) || '';
|
|
11
|
+
};
|
|
12
|
+
const setToken = (workspace, token) => {
|
|
13
|
+
if (typeof window === 'undefined')
|
|
14
|
+
return;
|
|
15
|
+
if (token) {
|
|
16
|
+
localStorage.setItem(getTokenKey(workspace), token);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
localStorage.removeItem(getTokenKey(workspace));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
// Export for use in other modules
|
|
23
|
+
export { getToken, setToken, getTokenKey };
|
|
4
24
|
// Only create once on the global object
|
|
25
|
+
// Returns a no-op implementation for SSR/Node.js environments
|
|
5
26
|
export const SessionEvents = (() => {
|
|
27
|
+
// Check if running in browser environment
|
|
28
|
+
if (typeof window === 'undefined') {
|
|
29
|
+
return {
|
|
30
|
+
on: () => () => { },
|
|
31
|
+
emit: () => { },
|
|
32
|
+
};
|
|
33
|
+
}
|
|
6
34
|
if (window.__SessionEvents)
|
|
7
35
|
return window.__SessionEvents;
|
|
8
36
|
const listeners = {
|
|
@@ -39,19 +67,31 @@ export const AuraAuth = (url, workspace) => {
|
|
|
39
67
|
baseURL: url + "/api/auth/" + workspace,
|
|
40
68
|
plugins: [anonymousClient()],
|
|
41
69
|
fetchOptions: {
|
|
42
|
-
|
|
70
|
+
// Use Bearer token authentication instead of cookies
|
|
71
|
+
auth: {
|
|
72
|
+
type: "Bearer",
|
|
73
|
+
token: () => getToken(workspace)
|
|
74
|
+
},
|
|
75
|
+
// Store the token from response headers on every successful request
|
|
76
|
+
onSuccess: (ctx) => {
|
|
77
|
+
const authToken = ctx.response.headers.get("set-auth-token");
|
|
78
|
+
if (authToken) {
|
|
79
|
+
setToken(workspace, authToken);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
43
82
|
},
|
|
44
83
|
});
|
|
45
84
|
authClient.useSession.subscribe(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Events
|
|
85
|
+
if (typeof window !== 'undefined') {
|
|
86
|
+
const Events = window.__SessionEvents;
|
|
87
|
+
if (Events) {
|
|
88
|
+
Events.emit("change");
|
|
89
|
+
}
|
|
49
90
|
}
|
|
50
91
|
});
|
|
51
92
|
const Session = computed(authClient.useSession, (session) => {
|
|
52
93
|
if (!session?.data?.user)
|
|
53
94
|
return session;
|
|
54
|
-
const Events = window.__SessionEvents;
|
|
55
95
|
return {
|
|
56
96
|
...session,
|
|
57
97
|
data: {
|
|
@@ -88,7 +128,7 @@ export const AuraAuth = (url, workspace) => {
|
|
|
88
128
|
};
|
|
89
129
|
const OnUserLoaded = (fn) => {
|
|
90
130
|
if (_initialized && User) {
|
|
91
|
-
Promise.resolve(fn());
|
|
131
|
+
Promise.resolve(fn()).catch(console.error);
|
|
92
132
|
}
|
|
93
133
|
else {
|
|
94
134
|
_onUserLoadedCallbacks.push(fn);
|
|
@@ -96,7 +136,7 @@ export const AuraAuth = (url, workspace) => {
|
|
|
96
136
|
};
|
|
97
137
|
const OnUserNotFound = (fn) => {
|
|
98
138
|
if (_initialized && !User) {
|
|
99
|
-
Promise.resolve(fn());
|
|
139
|
+
Promise.resolve(fn()).catch(console.error);
|
|
100
140
|
}
|
|
101
141
|
else {
|
|
102
142
|
_onUserNotFoundCallbacks.push(fn);
|
|
@@ -105,7 +145,11 @@ export const AuraAuth = (url, workspace) => {
|
|
|
105
145
|
// Initialize auth on creation
|
|
106
146
|
initialize();
|
|
107
147
|
return {
|
|
108
|
-
Logout:
|
|
148
|
+
Logout: async () => {
|
|
149
|
+
const result = await authClient.signOut();
|
|
150
|
+
setToken(workspace, null); // Clear token on logout
|
|
151
|
+
return result;
|
|
152
|
+
},
|
|
109
153
|
Email: {
|
|
110
154
|
SignUp: authClient.signUp.email,
|
|
111
155
|
Login: authClient.signIn.email,
|
|
@@ -133,7 +177,7 @@ export const AuraAuth = (url, workspace) => {
|
|
|
133
177
|
HuggingFace: (data) => withDefaultCallback("hf", data),
|
|
134
178
|
Linkedin: (data) => withDefaultCallback("linkedin", data),
|
|
135
179
|
Microsoft: (data) => withDefaultCallback("microsoft", data),
|
|
136
|
-
|
|
180
|
+
Reddit: (data) => withDefaultCallback("reddit", data),
|
|
137
181
|
Polar: (data) => withDefaultCallback("polar", data),
|
|
138
182
|
Spotify: (data) => withDefaultCallback("spotify", data),
|
|
139
183
|
Tiktok: (data) => withDefaultCallback("tiktok", data),
|
package/dist/database.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ declare class RemoteTable<TDef extends Record<string, any>> {
|
|
|
3
3
|
private URL;
|
|
4
4
|
private Name;
|
|
5
5
|
private WorkSpace;
|
|
6
|
+
private getAuthHeaders;
|
|
6
7
|
constructor(url: string, name: string, workspace: string);
|
|
7
8
|
Get: () => {
|
|
8
9
|
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 ? () => {
|
package/dist/database.d.ts.map
CHANGED
|
@@ -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;
|
|
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;AAKjE,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,gBAc7J;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"}
|
package/dist/database.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { createFluentBuilder } from "./fluent";
|
|
2
2
|
import axios from "axios";
|
|
3
|
+
import { getToken } from "./auth";
|
|
3
4
|
class RemoteTable {
|
|
4
5
|
URL;
|
|
5
6
|
Name;
|
|
6
7
|
WorkSpace;
|
|
8
|
+
getAuthHeaders() {
|
|
9
|
+
const token = getToken(this.WorkSpace);
|
|
10
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
11
|
+
}
|
|
7
12
|
constructor(url, name, workspace) {
|
|
8
13
|
this.URL = url;
|
|
9
14
|
this.Name = name;
|
|
@@ -15,7 +20,7 @@ class RemoteTable {
|
|
|
15
20
|
operation: 'Get',
|
|
16
21
|
settings: data,
|
|
17
22
|
}, {
|
|
18
|
-
|
|
23
|
+
headers: this.getAuthHeaders()
|
|
19
24
|
})).data;
|
|
20
25
|
});
|
|
21
26
|
};
|
|
@@ -25,7 +30,7 @@ class RemoteTable {
|
|
|
25
30
|
operation: 'GetOne',
|
|
26
31
|
settings: data,
|
|
27
32
|
}, {
|
|
28
|
-
|
|
33
|
+
headers: this.getAuthHeaders()
|
|
29
34
|
})).data;
|
|
30
35
|
});
|
|
31
36
|
};
|
|
@@ -35,7 +40,7 @@ class RemoteTable {
|
|
|
35
40
|
operation: 'Delete',
|
|
36
41
|
settings: { ...data, returning: true },
|
|
37
42
|
}, {
|
|
38
|
-
|
|
43
|
+
headers: this.getAuthHeaders()
|
|
39
44
|
})).data;
|
|
40
45
|
});
|
|
41
46
|
};
|
|
@@ -48,7 +53,7 @@ class RemoteTable {
|
|
|
48
53
|
},
|
|
49
54
|
data: record
|
|
50
55
|
}, {
|
|
51
|
-
|
|
56
|
+
headers: this.getAuthHeaders()
|
|
52
57
|
})).data;
|
|
53
58
|
});
|
|
54
59
|
};
|
|
@@ -61,7 +66,7 @@ class RemoteTable {
|
|
|
61
66
|
},
|
|
62
67
|
data: record
|
|
63
68
|
}, {
|
|
64
|
-
|
|
69
|
+
headers: this.getAuthHeaders()
|
|
65
70
|
})).data;
|
|
66
71
|
});
|
|
67
72
|
};
|
|
@@ -70,8 +75,9 @@ class RemoteTable {
|
|
|
70
75
|
return (await axios.post(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}`, {
|
|
71
76
|
operation: 'Update',
|
|
72
77
|
settings: { ...data, returning: true },
|
|
78
|
+
data: record
|
|
73
79
|
}, {
|
|
74
|
-
|
|
80
|
+
headers: this.getAuthHeaders()
|
|
75
81
|
})).data;
|
|
76
82
|
});
|
|
77
83
|
};
|
|
@@ -81,7 +87,7 @@ class RemoteTable {
|
|
|
81
87
|
operation: 'Count',
|
|
82
88
|
settings: data,
|
|
83
89
|
}, {
|
|
84
|
-
|
|
90
|
+
headers: this.getAuthHeaders()
|
|
85
91
|
})).data;
|
|
86
92
|
});
|
|
87
93
|
};
|
|
@@ -91,7 +97,7 @@ class RemoteTable {
|
|
|
91
97
|
operation: 'Exist',
|
|
92
98
|
settings: data,
|
|
93
99
|
}, {
|
|
94
|
-
|
|
100
|
+
headers: this.getAuthHeaders()
|
|
95
101
|
})).data;
|
|
96
102
|
});
|
|
97
103
|
};
|
|
@@ -101,10 +107,12 @@ class RemoteTable {
|
|
|
101
107
|
params.push("where=" + JSON.stringify(where));
|
|
102
108
|
if (init)
|
|
103
109
|
params.push("init=true");
|
|
110
|
+
// Add token to query params for EventSource (doesn't support headers)
|
|
111
|
+
const token = getToken(this.WorkSpace);
|
|
112
|
+
if (token)
|
|
113
|
+
params.push("token=" + encodeURIComponent(token));
|
|
104
114
|
const query = params.length ? "?" + params.join("&") : "";
|
|
105
|
-
const eventSource = new EventSource(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}${query}
|
|
106
|
-
withCredentials: true
|
|
107
|
-
});
|
|
115
|
+
const eventSource = new EventSource(`${this.URL}/api/db/${this.WorkSpace}/${this.Name}${query}`);
|
|
108
116
|
eventSource.addEventListener(this.Name, (event) => {
|
|
109
117
|
const { op, data } = JSON.parse(event.data);
|
|
110
118
|
callback({ action: op, data });
|
package/dist/function.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/function.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
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
|
+
};
|
|
2
8
|
const handler = new Proxy({}, {
|
|
3
9
|
get(_, prop) {
|
|
4
10
|
return createNestedProxy([prop]);
|
|
@@ -15,20 +21,22 @@ export function createFunctionHandler(baseUrl, workspace, functionsFolder) {
|
|
|
15
21
|
const url = [baseUrl, "api", "fn", workspace, ...path].join("/");
|
|
16
22
|
const isFormData = args != null && args.length === 1 && args[0] instanceof FormData;
|
|
17
23
|
const body = isFormData ? args[0] : JSON.stringify(args ?? {});
|
|
24
|
+
const token = getToken();
|
|
18
25
|
const headers = {
|
|
19
26
|
"Accept": "text/event-stream,application/json",
|
|
20
27
|
};
|
|
21
28
|
if (!isFormData)
|
|
22
29
|
headers["Content-Type"] = "application/json";
|
|
30
|
+
if (token)
|
|
31
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
23
32
|
// 2. Start the fetch properly (without await)
|
|
24
33
|
const requestPromise = fetch(url, {
|
|
25
34
|
method: "POST",
|
|
26
35
|
body,
|
|
27
36
|
headers,
|
|
28
|
-
credentials: "include",
|
|
29
37
|
});
|
|
30
|
-
// 3. Return a custom "Thenable" object
|
|
31
|
-
|
|
38
|
+
// 3. Return a custom "Thenable" object with full Promise interface
|
|
39
|
+
const thenable = {
|
|
32
40
|
then(onFulfilled, onRejected) {
|
|
33
41
|
requestPromise.then(async (response) => {
|
|
34
42
|
const contentType = response.headers.get("Content-Type") || "";
|
|
@@ -36,6 +44,11 @@ export function createFunctionHandler(baseUrl, workspace, functionsFolder) {
|
|
|
36
44
|
// SSE PATH
|
|
37
45
|
// ─────────────────────────────────────────────
|
|
38
46
|
if (contentType.includes("text/event-stream")) {
|
|
47
|
+
if (!response.body) {
|
|
48
|
+
if (onRejected)
|
|
49
|
+
onRejected(new Error("Response body is null"));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
39
52
|
const reader = response.body.getReader();
|
|
40
53
|
const decoder = new TextDecoder("utf-8");
|
|
41
54
|
let buffer = "";
|
|
@@ -84,10 +97,17 @@ export function createFunctionHandler(baseUrl, workspace, functionsFolder) {
|
|
|
84
97
|
if (onRejected)
|
|
85
98
|
onRejected(err);
|
|
86
99
|
});
|
|
87
|
-
// Return 'this' to allow chaining
|
|
88
|
-
return
|
|
100
|
+
// Return 'this' to allow chaining
|
|
101
|
+
return thenable;
|
|
102
|
+
},
|
|
103
|
+
catch(onRejected) {
|
|
104
|
+
return thenable.then(() => { }, onRejected);
|
|
105
|
+
},
|
|
106
|
+
finally(onFinally) {
|
|
107
|
+
return thenable.then((value) => { onFinally?.(); return value; }, (err) => { onFinally?.(); throw err; });
|
|
89
108
|
}
|
|
90
109
|
};
|
|
110
|
+
return thenable;
|
|
91
111
|
},
|
|
92
112
|
});
|
|
93
113
|
}
|
package/dist/hooks/react.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { CreateAura } from '..';
|
|
|
2
2
|
type ValueOf<T> = T[keyof T];
|
|
3
3
|
export declare function useTable<TDef extends ValueOf<Awaited<ReturnType<typeof CreateAura<any, any>>>['Database']>>(table: TDef, Options?: {
|
|
4
4
|
where: Parameters<Awaited<ReturnType<TDef['GetOne']>['where']>>[0];
|
|
5
|
-
}): ({ [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)[]
|
|
5
|
+
}): ({ [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)[];
|
|
6
6
|
export declare function useRecord<TDef extends ValueOf<Awaited<ReturnType<typeof CreateAura<any, any>>>['Database']>>(table: TDef, Options: {
|
|
7
7
|
where: Parameters<Awaited<ReturnType<TDef['GetOne']>['where']>>[0];
|
|
8
8
|
}): ({ [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) | undefined;
|
|
@@ -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;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,
|
|
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,guBAiEF;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,0uBA+DF;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"}
|
package/dist/hooks/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useStore } from '@nanostores/react';
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useEffect, useState, useRef } from 'react';
|
|
3
3
|
function deepEqual(a, b) {
|
|
4
4
|
if (a === b)
|
|
5
5
|
return true;
|
|
@@ -21,6 +21,12 @@ export function useTable(table, Options) {
|
|
|
21
21
|
const [data, setData] = useState([]);
|
|
22
22
|
// Dummy state to force rerun when session changes
|
|
23
23
|
const [sessionVersion, setSessionVersion] = useState(0);
|
|
24
|
+
// Use ref to track where clause changes with deep comparison
|
|
25
|
+
const whereRef = useRef(Options?.where);
|
|
26
|
+
const whereString = JSON.stringify(Options?.where);
|
|
27
|
+
if (JSON.stringify(whereRef.current) !== whereString) {
|
|
28
|
+
whereRef.current = Options?.where;
|
|
29
|
+
}
|
|
24
30
|
useEffect(() => {
|
|
25
31
|
const handler = () => {
|
|
26
32
|
setSessionVersion((v) => v + 1);
|
|
@@ -57,13 +63,19 @@ export function useTable(table, Options) {
|
|
|
57
63
|
return () => {
|
|
58
64
|
unsubscribe();
|
|
59
65
|
};
|
|
60
|
-
}, [table,
|
|
66
|
+
}, [table, whereString, sessionVersion]); // <--- include sessionVersion here
|
|
61
67
|
return data;
|
|
62
68
|
}
|
|
63
69
|
export function useRecord(table, Options) {
|
|
64
|
-
const [data, setData] = useState();
|
|
70
|
+
const [data, setData] = useState(undefined);
|
|
65
71
|
// Dummy state to trigger rerun on session change
|
|
66
72
|
const [sessionVersion, setSessionVersion] = useState(0);
|
|
73
|
+
// Use ref to track where clause changes with deep comparison
|
|
74
|
+
const whereRef = useRef(Options.where);
|
|
75
|
+
const whereString = JSON.stringify(Options.where);
|
|
76
|
+
if (JSON.stringify(whereRef.current) !== whereString) {
|
|
77
|
+
whereRef.current = Options.where;
|
|
78
|
+
}
|
|
67
79
|
// Subscribe to global session changes
|
|
68
80
|
useEffect(() => {
|
|
69
81
|
const handler = () => {
|
|
@@ -100,7 +112,7 @@ export function useRecord(table, Options) {
|
|
|
100
112
|
});
|
|
101
113
|
}, Options.where, true);
|
|
102
114
|
return () => unsubscribe();
|
|
103
|
-
}, [table,
|
|
115
|
+
}, [table, whereString, sessionVersion]); // <--- include sessionVersion
|
|
104
116
|
return data;
|
|
105
117
|
}
|
|
106
118
|
export const useUser = (provider) => {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,13 @@ export * from "@inflector/optima/types";
|
|
|
6
6
|
export * from "./lib";
|
|
7
7
|
export * from "./hooks/react";
|
|
8
8
|
export const CreateAura = (Config) => {
|
|
9
|
+
// Validate required config properties
|
|
10
|
+
if (!Config.config?.Url || typeof Config.config.Url !== 'string') {
|
|
11
|
+
throw new Error("CreateAura: Config.Url is required and must be a string");
|
|
12
|
+
}
|
|
13
|
+
if (!Config.config?.WorkSpace || typeof Config.config.WorkSpace !== 'string') {
|
|
14
|
+
throw new Error("CreateAura: Config.WorkSpace is required and must be a string");
|
|
15
|
+
}
|
|
9
16
|
const auth = AuraAuth(Config.config.Url, Config.config.WorkSpace);
|
|
10
17
|
return {
|
|
11
18
|
Database: AuraDatabase(Config.config.Url, Config.config.WorkSpace, Config.Tables),
|
package/dist/storage.d.ts
CHANGED
|
@@ -11,16 +11,16 @@ export declare const AuraStorage: (url: string, workspace: string, userAtom: any
|
|
|
11
11
|
Upload: (file?: File, config?: {
|
|
12
12
|
openSelector?: boolean;
|
|
13
13
|
allowedTypes?: string[];
|
|
14
|
-
}) => Promise<
|
|
14
|
+
}) => Promise<FileAura>;
|
|
15
15
|
File: (id: string) => string;
|
|
16
16
|
Delete: (id: string) => Promise<any>;
|
|
17
|
-
Get: (id: string) => Promise<FileAura
|
|
17
|
+
Get: (id: string) => Promise<FileAura>;
|
|
18
18
|
List: () => Promise<FileAura[]>;
|
|
19
19
|
UploadMultiple: (files?: File[], config?: {
|
|
20
20
|
openSelector?: boolean;
|
|
21
21
|
allowedTypes?: string[];
|
|
22
|
-
}) => Promise<
|
|
23
|
-
Exists: (id: string) => Promise<boolean
|
|
22
|
+
}) => Promise<FileAura[]>;
|
|
23
|
+
Exists: (id: string) => Promise<boolean>;
|
|
24
24
|
Download: (id: string, download?: boolean, asBase64?: boolean) => Promise<{
|
|
25
25
|
blob: any;
|
|
26
26
|
fileName: string;
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/storage.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
+
import { getToken } from "./auth";
|
|
2
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
|
+
};
|
|
3
9
|
const UploadFn = async (file, config = {}) => {
|
|
4
10
|
if (!userAtom.get().data)
|
|
5
|
-
|
|
11
|
+
throw new Error("User not authenticated");
|
|
6
12
|
// If no file is passed, or openSelector is true, open a file input dialog automatically
|
|
7
13
|
if (!file || config.openSelector) {
|
|
8
14
|
return new Promise(async (resolve, reject) => {
|
|
@@ -14,27 +20,37 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
14
20
|
}
|
|
15
21
|
input.style.display = "none";
|
|
16
22
|
document.body.appendChild(input);
|
|
23
|
+
const cleanup = () => {
|
|
24
|
+
if (document.body.contains(input)) {
|
|
25
|
+
document.body.removeChild(input);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
17
28
|
input.onchange = async () => {
|
|
18
29
|
try {
|
|
19
30
|
const selectedFile = input.files?.[0];
|
|
20
31
|
if (!selectedFile) {
|
|
21
32
|
reject(new Error("No file selected"));
|
|
22
|
-
|
|
33
|
+
cleanup();
|
|
23
34
|
return;
|
|
24
35
|
}
|
|
25
36
|
const fd = new FormData();
|
|
26
37
|
fd.set("operation", "Upload");
|
|
27
38
|
fd.set("owner", userAtom.get().data.user.id);
|
|
28
39
|
fd.set("file", selectedFile);
|
|
29
|
-
const result = (await axios.post(url + "/api/storage/" + workspace, fd)).data;
|
|
40
|
+
const result = (await axios.post(url + "/api/storage/" + workspace, fd, { headers: getAuthHeaders() })).data;
|
|
30
41
|
resolve(result);
|
|
31
|
-
|
|
42
|
+
cleanup();
|
|
32
43
|
}
|
|
33
44
|
catch (e) {
|
|
34
45
|
reject(e);
|
|
35
|
-
|
|
46
|
+
cleanup();
|
|
36
47
|
}
|
|
37
48
|
};
|
|
49
|
+
// Handle cancel - cleanup after a delay if no file selected
|
|
50
|
+
input.addEventListener('cancel', () => {
|
|
51
|
+
reject(new Error("File selection cancelled"));
|
|
52
|
+
cleanup();
|
|
53
|
+
});
|
|
38
54
|
input.click();
|
|
39
55
|
});
|
|
40
56
|
}
|
|
@@ -44,7 +60,7 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
44
60
|
fd.set("owner", userAtom.get().data.user.id);
|
|
45
61
|
fd.set("file", file);
|
|
46
62
|
return (await axios.post(url + "/api/storage/" + workspace, fd, {
|
|
47
|
-
|
|
63
|
+
headers: getAuthHeaders()
|
|
48
64
|
})).data;
|
|
49
65
|
}
|
|
50
66
|
};
|
|
@@ -55,7 +71,7 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
55
71
|
},
|
|
56
72
|
Delete: async (id) => {
|
|
57
73
|
if (!userAtom.get().data)
|
|
58
|
-
|
|
74
|
+
throw new Error("User not authenticated");
|
|
59
75
|
return (await axios.post(url + "/api/storage/" + workspace, {
|
|
60
76
|
operation: "Delete",
|
|
61
77
|
settings: {
|
|
@@ -63,12 +79,12 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
63
79
|
Owner: userAtom.get().data.user.id
|
|
64
80
|
}
|
|
65
81
|
}, {
|
|
66
|
-
|
|
82
|
+
headers: getAuthHeaders()
|
|
67
83
|
})).data;
|
|
68
84
|
},
|
|
69
85
|
Get: async (id) => {
|
|
70
86
|
if (!userAtom.get().data)
|
|
71
|
-
|
|
87
|
+
throw new Error("User not authenticated");
|
|
72
88
|
return (await axios.post(url + "/api/storage/" + workspace, {
|
|
73
89
|
operation: "Get",
|
|
74
90
|
settings: {
|
|
@@ -76,19 +92,19 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
76
92
|
Owner: userAtom.get().data.user.id
|
|
77
93
|
}
|
|
78
94
|
}, {
|
|
79
|
-
|
|
95
|
+
headers: getAuthHeaders()
|
|
80
96
|
})).data;
|
|
81
97
|
},
|
|
82
98
|
List: async () => {
|
|
83
99
|
if (!userAtom.get().data)
|
|
84
|
-
|
|
100
|
+
throw new Error("User not authenticated");
|
|
85
101
|
return (await axios.post(url + "/api/storage/" + workspace, {
|
|
86
102
|
operation: "List",
|
|
87
103
|
settings: {
|
|
88
104
|
Owner: userAtom.get().data.user.id
|
|
89
105
|
}
|
|
90
106
|
}, {
|
|
91
|
-
|
|
107
|
+
headers: getAuthHeaders()
|
|
92
108
|
})).data;
|
|
93
109
|
},
|
|
94
110
|
UploadMultiple: async (files, config = {}) => {
|
|
@@ -104,12 +120,17 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
104
120
|
}
|
|
105
121
|
input.style.display = "none";
|
|
106
122
|
document.body.appendChild(input);
|
|
123
|
+
const cleanup = () => {
|
|
124
|
+
if (document.body.contains(input)) {
|
|
125
|
+
document.body.removeChild(input);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
107
128
|
input.onchange = async () => {
|
|
108
129
|
const selectedFiles = Array.from(input.files ?? []);
|
|
109
130
|
try {
|
|
110
131
|
if (selectedFiles.length === 0) {
|
|
111
132
|
reject(new Error("No files selected"));
|
|
112
|
-
|
|
133
|
+
cleanup();
|
|
113
134
|
return;
|
|
114
135
|
}
|
|
115
136
|
const uploadResults = await Promise.all(selectedFiles.map(f => UploadFn(f, config)));
|
|
@@ -119,9 +140,14 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
119
140
|
reject(e);
|
|
120
141
|
}
|
|
121
142
|
finally {
|
|
122
|
-
|
|
143
|
+
cleanup();
|
|
123
144
|
}
|
|
124
145
|
};
|
|
146
|
+
// Handle cancel
|
|
147
|
+
input.addEventListener('cancel', () => {
|
|
148
|
+
reject(new Error("File selection cancelled"));
|
|
149
|
+
cleanup();
|
|
150
|
+
});
|
|
125
151
|
input.click();
|
|
126
152
|
});
|
|
127
153
|
}
|
|
@@ -132,22 +158,22 @@ export const AuraStorage = (url, workspace, userAtom) => {
|
|
|
132
158
|
},
|
|
133
159
|
Exists: async (id) => {
|
|
134
160
|
if (!userAtom.get().data)
|
|
135
|
-
|
|
161
|
+
throw new Error("User not authenticated");
|
|
136
162
|
return (await axios.post(url + "/api/storage/" + workspace, {
|
|
137
|
-
operation: "
|
|
163
|
+
operation: "Exists",
|
|
138
164
|
settings: {
|
|
139
165
|
FileID: id,
|
|
140
166
|
Owner: userAtom.get().data.user.id
|
|
141
167
|
}
|
|
142
168
|
}, {
|
|
143
|
-
|
|
169
|
+
headers: getAuthHeaders()
|
|
144
170
|
})).data;
|
|
145
171
|
},
|
|
146
172
|
Download: async (id, download = true, asBase64) => {
|
|
147
173
|
try {
|
|
148
174
|
const response = await axios.get(`${url}/api/storage/${workspace}/${id}?download=${download ? '1' : '0'}&base64=${asBase64 ? '1' : '0'}`, {
|
|
149
175
|
responseType: "blob",
|
|
150
|
-
|
|
176
|
+
headers: getAuthHeaders()
|
|
151
177
|
});
|
|
152
178
|
// Extract filename from content-disposition
|
|
153
179
|
const contentDisposition = response.headers["content-disposition"];
|