@dnax/core 0.3.4 → 0.3.6
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/app/hono.ts +88 -79
- package/define/index.ts +6 -0
- package/index.ts +1 -2
- package/lib/asyncLocalStorage.ts +8 -45
- package/lib/index.ts +4 -0
- package/lib/permissions.ts +85 -0
- package/package.json +1 -4
- package/types/index.ts +39 -28
- package/ai/gemini.ts +0 -97
- package/ai/index.ts +0 -2
- package/ai/mistral.ts +0 -63
package/app/hono.ts
CHANGED
|
@@ -18,6 +18,8 @@ import { MediaDrive } from "../lib/media";
|
|
|
18
18
|
import { isStudio } from "../lib/studio";
|
|
19
19
|
import { pick } from "radash";
|
|
20
20
|
import { secureHeaders } from "hono/secure-headers";
|
|
21
|
+
import { getTenant } from "../lib/tenant";
|
|
22
|
+
import { checkPermission, getPermission } from "../lib/permissions";
|
|
21
23
|
const app = new Hono();
|
|
22
24
|
|
|
23
25
|
const API_PATH = "/api";
|
|
@@ -31,7 +33,7 @@ function HonoInstance(): typeof app {
|
|
|
31
33
|
})
|
|
32
34
|
);
|
|
33
35
|
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoibm9tIiwiaWF0IjoxNzE3Nzc0MDQzLCJleHAiOjE3MTc3NzQxMDN9.Ud4-0y8pa4SMIcSn8PU1A-sjC-hT4ZVe_u3AdChyIJU
|
|
34
|
-
//
|
|
36
|
+
// Middlewares Injection
|
|
35
37
|
app.use(async (c, next) => {
|
|
36
38
|
return asyncLocalStorage.run(new Map(), async () => {
|
|
37
39
|
let cookie = getCookie(c);
|
|
@@ -53,20 +55,20 @@ function HonoInstance(): typeof app {
|
|
|
53
55
|
};
|
|
54
56
|
c.set("_v", _v);
|
|
55
57
|
c.set("tenant-id", c.req.header()["tenant-id"]);
|
|
58
|
+
|
|
56
59
|
if (token && valid) {
|
|
57
60
|
session.set({
|
|
61
|
+
// token: token,
|
|
58
62
|
state: decode?.state || {},
|
|
59
|
-
|
|
63
|
+
role: decode?.role || null,
|
|
60
64
|
_v: { ...(_v || {}) },
|
|
61
|
-
token: token,
|
|
62
65
|
});
|
|
63
66
|
} else {
|
|
64
67
|
// no valid token
|
|
65
68
|
session.set({
|
|
66
69
|
state: {},
|
|
67
|
-
|
|
70
|
+
role: undefined,
|
|
68
71
|
_v: { ...(_v || {}) },
|
|
69
|
-
token: null,
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -80,58 +82,7 @@ function HonoInstance(): typeof app {
|
|
|
80
82
|
});
|
|
81
83
|
});
|
|
82
84
|
|
|
83
|
-
//
|
|
84
|
-
app.get(
|
|
85
|
-
"/assets/*",
|
|
86
|
-
serveStatic({
|
|
87
|
-
root: "uploads",
|
|
88
|
-
//rewriteRequestPath: (path) => path?.replace(/^\/assets/, ""),
|
|
89
|
-
})
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
app.post("/api/studio", (c, next) => {
|
|
93
|
-
let cookie = getCookie(c);
|
|
94
|
-
let secretKeyStudio = cookie["_STUDIO_SECRET_KEY_"];
|
|
95
|
-
let canPerform = isStudio(secretKeyStudio);
|
|
96
|
-
let cf = {
|
|
97
|
-
collections: Cfg.collections?.map((c) =>
|
|
98
|
-
pick(c, ["fields", "slug", "tenant_id", "type"])
|
|
99
|
-
),
|
|
100
|
-
tenants: Cfg.tenants.map((t) => t?.id),
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
if (canPerform) {
|
|
104
|
-
return c.json({
|
|
105
|
-
auth: true,
|
|
106
|
-
data: cf,
|
|
107
|
-
});
|
|
108
|
-
} else {
|
|
109
|
-
c.status(403);
|
|
110
|
-
return c.json({ message: "Unauthorized" });
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
Cfg.collections?.map((c) => {
|
|
115
|
-
if (c?.type == "media" && c.media?.enabled) {
|
|
116
|
-
let mediaPath = cleanPath(
|
|
117
|
-
"/files/" + (c?.media?.overwriteFolderName || c?.slug) + "/public/*"
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
//console.log("Media Path :", mediaPath);
|
|
121
|
-
app.get(
|
|
122
|
-
mediaPath,
|
|
123
|
-
serveStatic({
|
|
124
|
-
root: cleanPath("uploads"),
|
|
125
|
-
rewriteRequestPath: (path) => path?.replace(/^\/files/, ""),
|
|
126
|
-
onNotFound: (path, c) => {
|
|
127
|
-
console.log(`${path} is not found, you access ${c.req.path}`);
|
|
128
|
-
},
|
|
129
|
-
})
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// access controle for api
|
|
85
|
+
// Access controle for api
|
|
135
86
|
app.use(cleanPath(API_PATH), async (c, next) => {
|
|
136
87
|
let session = sessionStorage();
|
|
137
88
|
|
|
@@ -141,9 +92,8 @@ function HonoInstance(): typeof app {
|
|
|
141
92
|
let col = getCollection(collection, tenant_id);
|
|
142
93
|
let colAccess =
|
|
143
94
|
col?.access?.hasOwnProperty(action) ||
|
|
144
|
-
session.get()?.
|
|
145
|
-
|
|
146
|
-
null;
|
|
95
|
+
getPermission(session.get()?.role, tenant_id) ||
|
|
96
|
+
null;
|
|
147
97
|
let nextLifecyle: any = false;
|
|
148
98
|
|
|
149
99
|
// Middleware for apis
|
|
@@ -195,23 +145,30 @@ function HonoInstance(): typeof app {
|
|
|
195
145
|
if (col && action && colAccess) {
|
|
196
146
|
let basicNextAccess = false;
|
|
197
147
|
|
|
198
|
-
if (session.get()
|
|
199
|
-
basicNextAccess =
|
|
148
|
+
if (getPermission(session.get()?.role, tenant_id)) {
|
|
149
|
+
basicNextAccess = checkPermission(
|
|
150
|
+
session.get()?.role,
|
|
151
|
+
tenant_id,
|
|
152
|
+
collection,
|
|
153
|
+
action
|
|
154
|
+
);
|
|
200
155
|
}
|
|
201
156
|
|
|
202
|
-
if (session.get().access.hasOwnProperty("allAction")) {
|
|
157
|
+
/* if (session.get().access.hasOwnProperty("allAction")) {
|
|
203
158
|
basicNextAccess = session.get().access["allAction"];
|
|
159
|
+
} */
|
|
160
|
+
|
|
161
|
+
nextLifecyle = basicNextAccess;
|
|
162
|
+
|
|
163
|
+
if (col?.access?.hasOwnProperty(action)) {
|
|
164
|
+
nextLifecyle = await col?.access[action]({
|
|
165
|
+
session: sessionStorage(),
|
|
166
|
+
action: action,
|
|
167
|
+
c: c,
|
|
168
|
+
isAuth: c.var?._v?.isAuth || false,
|
|
169
|
+
rest: new useRest({ tenant_id: tenant_id }),
|
|
170
|
+
});
|
|
204
171
|
}
|
|
205
|
-
|
|
206
|
-
nextLifecyle = basicNextAccess
|
|
207
|
-
? basicNextAccess
|
|
208
|
-
: await col?.access[action]({
|
|
209
|
-
session: sessionStorage(),
|
|
210
|
-
action: action,
|
|
211
|
-
c: c,
|
|
212
|
-
isAuth: c.var?._v?.isAuth || false,
|
|
213
|
-
rest: new useRest({ tenant_id: tenant_id }),
|
|
214
|
-
});
|
|
215
172
|
}
|
|
216
173
|
}
|
|
217
174
|
|
|
@@ -228,6 +185,11 @@ function HonoInstance(): typeof app {
|
|
|
228
185
|
// API REST
|
|
229
186
|
app.post(cleanPath(API_PATH), async (c) => {
|
|
230
187
|
try {
|
|
188
|
+
// control tenant
|
|
189
|
+
if (!c.var["tenant-id"] || !getTenant(c.var["tenant-id"])) {
|
|
190
|
+
throw new contextError(`Tenant Id missiong or not found`, 404);
|
|
191
|
+
}
|
|
192
|
+
|
|
231
193
|
var response;
|
|
232
194
|
var parseBody;
|
|
233
195
|
const { action, collection, cleanDeep, useCache, name } =
|
|
@@ -272,12 +234,7 @@ function HonoInstance(): typeof app {
|
|
|
272
234
|
});
|
|
273
235
|
}
|
|
274
236
|
|
|
275
|
-
|
|
276
|
-
if (
|
|
277
|
-
!getCollection(collection, c.var["tenant-id"]) &&
|
|
278
|
-
getAction(action) &&
|
|
279
|
-
collection
|
|
280
|
-
) {
|
|
237
|
+
if (!getAction(action) || !collection) {
|
|
281
238
|
throw new contextError(`Collection ${collection} not found`, 404);
|
|
282
239
|
}
|
|
283
240
|
|
|
@@ -431,6 +388,49 @@ function HonoInstance(): typeof app {
|
|
|
431
388
|
}
|
|
432
389
|
});
|
|
433
390
|
|
|
391
|
+
app.post("/api/studio", (c, next) => {
|
|
392
|
+
let cookie = getCookie(c);
|
|
393
|
+
let secretKeyStudio = cookie["_STUDIO_SECRET_KEY_"];
|
|
394
|
+
let canPerform = isStudio(secretKeyStudio);
|
|
395
|
+
let cf = {
|
|
396
|
+
collections: Cfg.collections?.map((c) =>
|
|
397
|
+
pick(c, ["fields", "slug", "tenant_id", "type"])
|
|
398
|
+
),
|
|
399
|
+
tenants: Cfg.tenants.map((t) => t?.id),
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
if (canPerform) {
|
|
403
|
+
return c.json({
|
|
404
|
+
auth: true,
|
|
405
|
+
data: cf,
|
|
406
|
+
});
|
|
407
|
+
} else {
|
|
408
|
+
c.status(403);
|
|
409
|
+
return c.json({ message: "Unauthorized" });
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// media endpoints
|
|
414
|
+
Cfg.collections?.map((c) => {
|
|
415
|
+
if (c?.type == "media" && c.media?.enabled) {
|
|
416
|
+
let mediaPath = cleanPath(
|
|
417
|
+
"/files/" + (c?.media?.overwriteFolderName || c?.slug) + "/public/*"
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
//console.log("Media Path :", mediaPath);
|
|
421
|
+
app.get(
|
|
422
|
+
mediaPath,
|
|
423
|
+
serveStatic({
|
|
424
|
+
root: cleanPath("uploads"),
|
|
425
|
+
rewriteRequestPath: (path) => path?.replace(/^\/files/, ""),
|
|
426
|
+
onNotFound: (path, c) => {
|
|
427
|
+
console.log(`${path} is not found, you access ${c.req.path}`);
|
|
428
|
+
},
|
|
429
|
+
})
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
434
|
// Endpoint
|
|
435
435
|
Cfg?.endpoints?.map((e) => {
|
|
436
436
|
if (e?.enabled) {
|
|
@@ -443,4 +443,13 @@ function HonoInstance(): typeof app {
|
|
|
443
443
|
return app;
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
+
// Public assets
|
|
447
|
+
app.get(
|
|
448
|
+
"/assets/*",
|
|
449
|
+
serveStatic({
|
|
450
|
+
root: "uploads",
|
|
451
|
+
//rewriteRequestPath: (path) => path?.replace(/^\/assets/, ""),
|
|
452
|
+
})
|
|
453
|
+
);
|
|
454
|
+
|
|
446
455
|
export { HonoInstance };
|
package/define/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
cronConfig,
|
|
8
8
|
cronCtx,
|
|
9
9
|
middlewareCtx,
|
|
10
|
+
permissionSchema,
|
|
10
11
|
} from "../types";
|
|
11
12
|
import { Cfg } from "../config/";
|
|
12
13
|
import { deepMerge, freeze } from "../utils";
|
|
@@ -40,6 +41,10 @@ function Task(config: cronConfig) {
|
|
|
40
41
|
return config;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function Permission(config: permissionSchema): permissionSchema {
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
const define = {
|
|
44
49
|
Service,
|
|
45
50
|
Config,
|
|
@@ -50,6 +55,7 @@ const define = {
|
|
|
50
55
|
Middleware,
|
|
51
56
|
Task,
|
|
52
57
|
Cron: Task,
|
|
58
|
+
Permission,
|
|
53
59
|
};
|
|
54
60
|
|
|
55
61
|
export default define;
|
package/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ import define from "./define";
|
|
|
7
7
|
import moment from "moment";
|
|
8
8
|
import * as utils from "./utils";
|
|
9
9
|
|
|
10
|
-
import * as ai from "./ai";
|
|
11
10
|
/**
|
|
12
11
|
* v is internal data validation and based of Joi validation.
|
|
13
12
|
* Note : v is an alias of Joi object API .
|
|
@@ -15,4 +14,4 @@ import * as ai from "./ai";
|
|
|
15
14
|
*/
|
|
16
15
|
const v = Joi;
|
|
17
16
|
|
|
18
|
-
export { runApp, define, utils, useRest,
|
|
17
|
+
export { runApp, define, utils, useRest, v };
|
package/lib/asyncLocalStorage.ts
CHANGED
|
@@ -8,40 +8,15 @@ const sessionStorage = () => ({
|
|
|
8
8
|
get(): {
|
|
9
9
|
state: object;
|
|
10
10
|
_v: object;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
allAction?: boolean;
|
|
14
|
-
aggreate?: boolean;
|
|
15
|
-
find?: boolean;
|
|
16
|
-
findOne?: boolean;
|
|
17
|
-
insertOne?: boolean;
|
|
18
|
-
insertMany?: boolean;
|
|
19
|
-
updateOne?: boolean;
|
|
20
|
-
updateMany?: boolean;
|
|
21
|
-
deleteOne?: boolean;
|
|
22
|
-
deleteMany?: boolean;
|
|
23
|
-
upload?: boolean;
|
|
24
|
-
};
|
|
11
|
+
|
|
12
|
+
role: string | null | undefined;
|
|
25
13
|
} {
|
|
26
14
|
let store = asyncLocalStorage.getStore() as InstanceType<typeof Map>;
|
|
27
15
|
return (
|
|
28
16
|
(store.get(key) as {
|
|
29
17
|
state: object;
|
|
30
18
|
_v: object;
|
|
31
|
-
|
|
32
|
-
access: {
|
|
33
|
-
allAction?: boolean;
|
|
34
|
-
aggreate?: boolean;
|
|
35
|
-
find?: boolean;
|
|
36
|
-
findOne?: boolean;
|
|
37
|
-
insertOne?: boolean;
|
|
38
|
-
insertMany?: boolean;
|
|
39
|
-
updateOne?: boolean;
|
|
40
|
-
updateMany?: boolean;
|
|
41
|
-
deleteOne?: boolean;
|
|
42
|
-
deleteMany?: boolean;
|
|
43
|
-
upload?: boolean;
|
|
44
|
-
};
|
|
19
|
+
role: string;
|
|
45
20
|
}) || {
|
|
46
21
|
state: {},
|
|
47
22
|
_v: {},
|
|
@@ -53,30 +28,18 @@ const sessionStorage = () => ({
|
|
|
53
28
|
input: {
|
|
54
29
|
state: object;
|
|
55
30
|
_v?: object;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
allAction?: boolean;
|
|
59
|
-
aggreate?: boolean;
|
|
60
|
-
find?: boolean;
|
|
61
|
-
findOne?: boolean;
|
|
62
|
-
insertOne?: boolean;
|
|
63
|
-
insertMany?: boolean;
|
|
64
|
-
updateOne?: boolean;
|
|
65
|
-
updateMany?: boolean;
|
|
66
|
-
deleteOne?: boolean;
|
|
67
|
-
deleteMany?: boolean;
|
|
68
|
-
upload?: boolean;
|
|
69
|
-
};
|
|
31
|
+
role?: string;
|
|
32
|
+
token?: string | null | undefined;
|
|
70
33
|
} = {
|
|
71
34
|
state: {},
|
|
72
35
|
_v: {},
|
|
73
|
-
|
|
36
|
+
token: null,
|
|
74
37
|
}
|
|
75
38
|
) {
|
|
76
39
|
let store = asyncLocalStorage.getStore() as InstanceType<typeof Map>;
|
|
77
40
|
let generateToken = jwt.sign({
|
|
78
41
|
state: input.state,
|
|
79
|
-
|
|
42
|
+
role: input?.role || {},
|
|
80
43
|
});
|
|
81
44
|
|
|
82
45
|
store.set(key, {
|
|
@@ -89,7 +52,7 @@ const sessionStorage = () => ({
|
|
|
89
52
|
...(input?._v || {}),
|
|
90
53
|
setAt: new Date().toString(),
|
|
91
54
|
},
|
|
92
|
-
|
|
55
|
+
role: input?.role || null,
|
|
93
56
|
token: generateToken,
|
|
94
57
|
});
|
|
95
58
|
},
|
package/lib/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { connectTenantsDatabase } from "../driver";
|
|
|
3
3
|
import { loadEndpoints } from "./endpoint";
|
|
4
4
|
import { loadServices } from "./service";
|
|
5
5
|
import { initCron } from "./cron";
|
|
6
|
+
import { loadPermissions } from "./permissions";
|
|
6
7
|
import { loadSocket } from "./socket";
|
|
7
8
|
// load all ressource
|
|
8
9
|
async function init(cf = { app: null }) {
|
|
@@ -11,6 +12,9 @@ async function init(cf = { app: null }) {
|
|
|
11
12
|
// load all collections
|
|
12
13
|
await loadAllCollections();
|
|
13
14
|
|
|
15
|
+
// load all permissions
|
|
16
|
+
await loadPermissions();
|
|
17
|
+
|
|
14
18
|
// sync all collections database ( Indexes)
|
|
15
19
|
syncCollectionDatabase();
|
|
16
20
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { omit } from "radash";
|
|
2
|
+
import type {
|
|
3
|
+
Collection,
|
|
4
|
+
Endpoint,
|
|
5
|
+
Field,
|
|
6
|
+
permissionSchema,
|
|
7
|
+
} from "../types/index";
|
|
8
|
+
import { Glob } from "bun";
|
|
9
|
+
import { Cfg } from "../config";
|
|
10
|
+
import { cleanPath, resolvePath } from "../utils";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import { useRest } from "../driver/mongo/rest";
|
|
13
|
+
|
|
14
|
+
async function loadPermissions() {
|
|
15
|
+
let permissions: permissionSchema[] = [];
|
|
16
|
+
if (Cfg.tenants) {
|
|
17
|
+
for await (let t of Cfg.tenants) {
|
|
18
|
+
let tenantPath = `${t.dir}/permissions/**/**.access.{ts,js}`;
|
|
19
|
+
const glob = new Glob(tenantPath);
|
|
20
|
+
for await (let file of glob.scan({
|
|
21
|
+
cwd: Cfg.cwd,
|
|
22
|
+
})) {
|
|
23
|
+
let fullPathFile = path.join(Cfg.cwd || "", file);
|
|
24
|
+
await import(fullPathFile)
|
|
25
|
+
.then((inject) => {
|
|
26
|
+
permissions.push({
|
|
27
|
+
...inject?.default,
|
|
28
|
+
tenant_id: t.id,
|
|
29
|
+
});
|
|
30
|
+
})
|
|
31
|
+
.catch((err) => {
|
|
32
|
+
console.error(err);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Cfg.permissions = permissions;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getPermission(
|
|
42
|
+
role: string,
|
|
43
|
+
tenant_id: string | number
|
|
44
|
+
): permissionSchema | undefined | null {
|
|
45
|
+
if (Cfg?.permissions?.length) {
|
|
46
|
+
return Cfg.permissions.find((col: permissionSchema) => {
|
|
47
|
+
return col.role === role && col.tenant_id === tenant_id;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function checkPermission(
|
|
54
|
+
role: string,
|
|
55
|
+
tenant_id: string | number,
|
|
56
|
+
collection: string,
|
|
57
|
+
action: string
|
|
58
|
+
): boolean {
|
|
59
|
+
let perm = getPermission(role, tenant_id);
|
|
60
|
+
let approved = false;
|
|
61
|
+
|
|
62
|
+
// 1- Check if all connection
|
|
63
|
+
let findAsterixCollection = perm?.access?.find((c) =>
|
|
64
|
+
c.collections.includes("*")
|
|
65
|
+
);
|
|
66
|
+
if (findAsterixCollection) {
|
|
67
|
+
let actionsOnAll = findAsterixCollection.actions.find((a) => a === action);
|
|
68
|
+
actionsOnAll ? (approved = true) : (approved = false);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 2- Check if collection and action
|
|
72
|
+
let findCollection = perm?.access?.find((c) =>
|
|
73
|
+
c.collections.includes(collection)
|
|
74
|
+
);
|
|
75
|
+
if (findCollection) {
|
|
76
|
+
let actionsOnCollection = findCollection.actions.find((a) => a === action);
|
|
77
|
+
actionsOnCollection ? (approved = true) : (approved = false);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// console.log("approved", approved);
|
|
81
|
+
|
|
82
|
+
return approved;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { loadPermissions, getPermission, checkPermission };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnax/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,11 +16,9 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@clack/prompts": "^0.7.0",
|
|
18
18
|
"@colors/colors": "^1.6.0",
|
|
19
|
-
"@google/generative-ai": "0.14.0",
|
|
20
19
|
"@lukeed/ms": "^2.0.2",
|
|
21
20
|
"@types/jsonwebtoken": "^9.0.6",
|
|
22
21
|
"boxen": "^7.1.1",
|
|
23
|
-
"bree": "^9.2.4",
|
|
24
22
|
"chokidar": "^3.6.0",
|
|
25
23
|
"clean-deep": "^3.4.0",
|
|
26
24
|
"collect.js": "^4.36.1",
|
|
@@ -30,7 +28,6 @@
|
|
|
30
28
|
"find-open-port": "^2.0.3",
|
|
31
29
|
"generate-unique-id": "^2.0.3",
|
|
32
30
|
"hono": "^4.4.3",
|
|
33
|
-
"hono-sessions": "^0.5.8",
|
|
34
31
|
"joi": "^17.13.3",
|
|
35
32
|
"json-joy": "^16.8.0",
|
|
36
33
|
"jsonwebtoken": "^9.0.2",
|
package/types/index.ts
CHANGED
|
@@ -162,37 +162,13 @@ export type sessionCtx = {
|
|
|
162
162
|
state: object | any;
|
|
163
163
|
token?: string;
|
|
164
164
|
_v?: object;
|
|
165
|
-
|
|
166
|
-
allAction?: boolean;
|
|
167
|
-
aggreate?: boolean;
|
|
168
|
-
find?: boolean;
|
|
169
|
-
findOne?: boolean;
|
|
170
|
-
insertOne?: boolean;
|
|
171
|
-
insertMany?: boolean;
|
|
172
|
-
updateOne?: boolean;
|
|
173
|
-
updateMany?: boolean;
|
|
174
|
-
deleteOne?: boolean;
|
|
175
|
-
deleteMany?: boolean;
|
|
176
|
-
upload?: boolean;
|
|
177
|
-
};
|
|
165
|
+
role?: string | null | undefined;
|
|
178
166
|
}) => void;
|
|
179
167
|
get: () => {
|
|
180
168
|
state: object;
|
|
181
169
|
_v: object;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
aggreate?: boolean;
|
|
185
|
-
find?: boolean;
|
|
186
|
-
findOne?: boolean;
|
|
187
|
-
insertOne?: boolean;
|
|
188
|
-
insertMany?: boolean;
|
|
189
|
-
updateOne?: boolean;
|
|
190
|
-
updateMany?: boolean;
|
|
191
|
-
deleteOne?: boolean;
|
|
192
|
-
deleteMany?: boolean;
|
|
193
|
-
upload?: boolean;
|
|
194
|
-
};
|
|
195
|
-
token: string;
|
|
170
|
+
role: string | null | undefined;
|
|
171
|
+
token: string | null | undefined;
|
|
196
172
|
};
|
|
197
173
|
};
|
|
198
174
|
|
|
@@ -379,7 +355,7 @@ export type Config = {
|
|
|
379
355
|
* Tenants database for API
|
|
380
356
|
*/
|
|
381
357
|
tenants: Tenant[];
|
|
382
|
-
|
|
358
|
+
permissions?: permissionSchema[];
|
|
383
359
|
/**
|
|
384
360
|
* Dont touch it automatically generated
|
|
385
361
|
*/
|
|
@@ -495,3 +471,38 @@ export type smtpConfigType = {
|
|
|
495
471
|
pass: string;
|
|
496
472
|
};
|
|
497
473
|
};
|
|
474
|
+
|
|
475
|
+
export type AccessFunctionType = (ctx: {
|
|
476
|
+
isAuth: boolean;
|
|
477
|
+
c?: Context;
|
|
478
|
+
session: sessionCtx;
|
|
479
|
+
rest: InstanceType<typeof useRest>;
|
|
480
|
+
}) => boolean | Promise<any>;
|
|
481
|
+
|
|
482
|
+
export type accessType = {
|
|
483
|
+
collections: Array<string> | ["*"];
|
|
484
|
+
actions: Array<
|
|
485
|
+
| {
|
|
486
|
+
action: Actions;
|
|
487
|
+
handler: AccessFunctionType;
|
|
488
|
+
}
|
|
489
|
+
| "*"
|
|
490
|
+
| "allAction"
|
|
491
|
+
| "aggregate"
|
|
492
|
+
| "find"
|
|
493
|
+
| "findOne"
|
|
494
|
+
| "insertOne"
|
|
495
|
+
| "insertMany"
|
|
496
|
+
| "updateOne"
|
|
497
|
+
| "updateMany"
|
|
498
|
+
| "deleteOne"
|
|
499
|
+
| "deleteMany"
|
|
500
|
+
| "upload"
|
|
501
|
+
>;
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
export type permissionSchema = {
|
|
505
|
+
role: string;
|
|
506
|
+
description?: string;
|
|
507
|
+
access: Array<accessType> | [];
|
|
508
|
+
};
|
package/ai/gemini.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
2
|
-
import { Cfg } from "../config";
|
|
3
|
-
import { getCollection } from "../lib/collection";
|
|
4
|
-
|
|
5
|
-
class Gemini {
|
|
6
|
-
#genAI: InstanceType<typeof GoogleGenerativeAI>;
|
|
7
|
-
#api_key: any;
|
|
8
|
-
#tenant_id: any;
|
|
9
|
-
#systemInstruction: string | undefined = "";
|
|
10
|
-
#model: string = "gemini-1.5-flash";
|
|
11
|
-
|
|
12
|
-
constructor(
|
|
13
|
-
opts: {
|
|
14
|
-
tenant_id?: string;
|
|
15
|
-
key?: string;
|
|
16
|
-
systemInstruction?: string;
|
|
17
|
-
model?: string;
|
|
18
|
-
} = {
|
|
19
|
-
model: "gemini-1.5-flash",
|
|
20
|
-
}
|
|
21
|
-
) {
|
|
22
|
-
this.#genAI = new GoogleGenerativeAI(
|
|
23
|
-
opts.key || Cfg.ai?.key || process.env.AI_KEY || ""
|
|
24
|
-
);
|
|
25
|
-
this.#systemInstruction = opts.systemInstruction;
|
|
26
|
-
this.#tenant_id = opts?.tenant_id || null;
|
|
27
|
-
this.#api_key = process.env.key || Cfg.ai?.key || "";
|
|
28
|
-
this.#model = opts.model || "gemini-1.5-flash";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async generateContent(
|
|
32
|
-
content: string,
|
|
33
|
-
options: {
|
|
34
|
-
systemInstruction: string;
|
|
35
|
-
generationConfig?: {
|
|
36
|
-
responseMimeType: string;
|
|
37
|
-
};
|
|
38
|
-
} = {
|
|
39
|
-
systemInstruction: "",
|
|
40
|
-
}
|
|
41
|
-
) {
|
|
42
|
-
let model = this.#genAI.getGenerativeModel({
|
|
43
|
-
model: this.#model,
|
|
44
|
-
systemInstruction: options.systemInstruction || this.#systemInstruction,
|
|
45
|
-
generationConfig: options.generationConfig || {},
|
|
46
|
-
});
|
|
47
|
-
let result = await model.generateContent(content);
|
|
48
|
-
let response = await result.response.text();
|
|
49
|
-
return response;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* async generateFilter(opts: { collection: string; prompt: string }) {
|
|
53
|
-
let col = getCollection(opts.collection, this.#tenant_id);
|
|
54
|
-
let model = this.#genAI.getGenerativeModel({
|
|
55
|
-
model: "gemini-1.5-flash",
|
|
56
|
-
systemInstruction: `
|
|
57
|
-
|
|
58
|
-
En te basant les informations json suivantes :
|
|
59
|
-
Nom de la base de donnée : ${col?.slug}
|
|
60
|
-
et de la structure des champs suivants :
|
|
61
|
-
${col?.fields}
|
|
62
|
-
|
|
63
|
-
Merci de fourni un filtre $match(aggregate) de mongodb qui correspond à la demande du
|
|
64
|
-
l'utilisateur et de retourner ce $match sous forme de JSON parse
|
|
65
|
-
|
|
66
|
-
- Si la demande ne correspond pas à une generation de filter $match
|
|
67
|
-
merci de retourner "{}" comme réponse en json parse .
|
|
68
|
-
|
|
69
|
-
Exemple de format json de retour : {"$match":{"nom":"John"}}
|
|
70
|
-
|
|
71
|
-
`,
|
|
72
|
-
});
|
|
73
|
-
let result = await model.generateContent(opts.prompt);
|
|
74
|
-
let response = await result.response.text();
|
|
75
|
-
|
|
76
|
-
return extractJson(response);
|
|
77
|
-
} */
|
|
78
|
-
}
|
|
79
|
-
function extractJson(chaine: string) {
|
|
80
|
-
try {
|
|
81
|
-
// Utiliser une expression régulière pour extraire le contenu JSON
|
|
82
|
-
const match = chaine.match(/\{.*\}/);
|
|
83
|
-
if (match) {
|
|
84
|
-
// Extraire le contenu JSON
|
|
85
|
-
const jsonStr = match[0];
|
|
86
|
-
// Convertir la chaîne JSON en objet JavaScript
|
|
87
|
-
const jsonData = JSON.parse(jsonStr);
|
|
88
|
-
return jsonData;
|
|
89
|
-
} else {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
} catch (err: any) {
|
|
93
|
-
console.log(err?.message);
|
|
94
|
-
return {};
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
export { Gemini };
|
package/ai/index.ts
DELETED
package/ai/mistral.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
2
|
-
import { Cfg } from "../config";
|
|
3
|
-
import { getCollection } from "../lib/collection";
|
|
4
|
-
|
|
5
|
-
class Mistral {
|
|
6
|
-
#genAI: InstanceType<typeof GoogleGenerativeAI>;
|
|
7
|
-
#api_key: any;
|
|
8
|
-
#tenant_id: any;
|
|
9
|
-
|
|
10
|
-
constructor(opts: { tenant_id?: string; key?: string } = {}) {
|
|
11
|
-
this.#genAI = new GoogleGenerativeAI(
|
|
12
|
-
opts.key || Cfg.ai?.key || process.env.API_KEY || ""
|
|
13
|
-
);
|
|
14
|
-
this.#tenant_id = opts?.tenant_id || null;
|
|
15
|
-
this.#api_key = process.env.key || Cfg.ai?.key || "";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async generateFilter(opts: { collection: string; prompt: string }) {
|
|
19
|
-
let col = getCollection(opts.collection, this.#tenant_id);
|
|
20
|
-
let model = this.#genAI.getGenerativeModel({
|
|
21
|
-
model: "gemini-1.5-flash",
|
|
22
|
-
systemInstruction: `
|
|
23
|
-
|
|
24
|
-
En te basant les informations json suivantes :
|
|
25
|
-
Nom de la base de donnée : ${col?.slug}
|
|
26
|
-
et de la structure des champs suivants :
|
|
27
|
-
${col?.fields}
|
|
28
|
-
|
|
29
|
-
Merci de fourni un filtre $match(aggregate) de mongodb qui correspond à la demande du
|
|
30
|
-
l'utilisateur et de retourner ce $match sous forme de JSON parse
|
|
31
|
-
|
|
32
|
-
- Si la demande ne correspond pas à une generation de filter $match
|
|
33
|
-
merci de retourner "{}" comme réponse en json parse .
|
|
34
|
-
|
|
35
|
-
Exemple de format json de retour : {"$match":{"nom":"John"}}
|
|
36
|
-
|
|
37
|
-
`,
|
|
38
|
-
});
|
|
39
|
-
let result = await model.generateContent(opts.prompt);
|
|
40
|
-
let response = await result.response.text();
|
|
41
|
-
|
|
42
|
-
return extractJson(response);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function extractJson(chaine: string) {
|
|
46
|
-
try {
|
|
47
|
-
// Utiliser une expression régulière pour extraire le contenu JSON
|
|
48
|
-
const match = chaine.match(/\{.*\}/);
|
|
49
|
-
if (match) {
|
|
50
|
-
// Extraire le contenu JSON
|
|
51
|
-
const jsonStr = match[0];
|
|
52
|
-
// Convertir la chaîne JSON en objet JavaScript
|
|
53
|
-
const jsonData = JSON.parse(jsonStr);
|
|
54
|
-
return jsonData;
|
|
55
|
-
} else {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
} catch (err: any) {
|
|
59
|
-
console.log(err?.message);
|
|
60
|
-
return {};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
export { Mistral };
|