@anteros/core 0.0.1-alpha.1

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.
Files changed (55) hide show
  1. package/README.md +143 -0
  2. package/database/collection.ts +160 -0
  3. package/database/decorator.ts +172 -0
  4. package/database/file.ts +93 -0
  5. package/database/mongodbadapter.ts +1128 -0
  6. package/database/rest.ts +14 -0
  7. package/database/schema.ts +160 -0
  8. package/database/tenant.ts +37 -0
  9. package/database/workflow.ts +384 -0
  10. package/index.ts +28 -0
  11. package/lib/asyncContextStorage.ts +68 -0
  12. package/lib/define.ts +114 -0
  13. package/lib/error.ts +21 -0
  14. package/lib/files.ts +459 -0
  15. package/lib/middleware.ts +66 -0
  16. package/lib/routes.ts +44 -0
  17. package/lib/scripts.ts +47 -0
  18. package/lib/services.ts +45 -0
  19. package/lib/sockets.ts +44 -0
  20. package/lib/workflow.ts +60 -0
  21. package/package.json +31 -0
  22. package/server/api.ts +789 -0
  23. package/server/boot.ts +101 -0
  24. package/server/config.ts +107 -0
  25. package/server/env.ts +16 -0
  26. package/server/hono.ts +176 -0
  27. package/server/io.ts +15 -0
  28. package/server/routes.ts +48 -0
  29. package/server/security.ts +138 -0
  30. package/tests/api.test.ts +281 -0
  31. package/tsconfig.json +36 -0
  32. package/types/activity.d.ts +45 -0
  33. package/types/api.d.ts +85 -0
  34. package/types/collection.d.ts +82 -0
  35. package/types/config.d.ts +55 -0
  36. package/types/field.d.ts +72 -0
  37. package/types/file.d.ts +120 -0
  38. package/types/hook.d.ts +30 -0
  39. package/types/middleware.d.ts +18 -0
  40. package/types/mongo.d.ts +61 -0
  41. package/types/options.d.ts +7 -0
  42. package/types/rest.d.ts +18 -0
  43. package/types/route.d.ts +19 -0
  44. package/types/schema.d.ts +0 -0
  45. package/types/scripts.d.ts +10 -0
  46. package/types/service.d.ts +37 -0
  47. package/types/task.d.ts +12 -0
  48. package/types/tenant.d.ts +16 -0
  49. package/types/token.d.ts +14 -0
  50. package/types/websocket.d.ts +15 -0
  51. package/types/workflow.d.ts +91 -0
  52. package/utils/cache.ts +96 -0
  53. package/utils/crypto.ts +226 -0
  54. package/utils/func.ts +1037 -0
  55. package/utils/index.ts +17 -0
package/lib/scripts.ts ADDED
@@ -0,0 +1,47 @@
1
+ import { Glob } from "bun"
2
+ import { cfg } from "../server/config"
3
+ import path from "path"
4
+ import fs from "fs/promises"
5
+ import type { Script } from "../types/scripts"
6
+ import { useRest } from "../database/rest"
7
+ import { asyncContextStorage, requestCtxStorage } from "./asyncContextStorage"
8
+
9
+
10
+ async function runScripts() {
11
+ let scripts: (Script & { rest: InstanceType<typeof useRest> })[] = []
12
+ for (let tenant of cfg.tenants ?? []) {
13
+ const TENANT_PATH = path.join(process.cwd(), tenant.dir)
14
+ const SCRIPTS_PATH = path.join(TENANT_PATH, 'scripts')
15
+ let exist = await fs.exists(SCRIPTS_PATH)
16
+ if (!exist) continue;
17
+ const isDirectory = await (await fs.stat(SCRIPTS_PATH)).isDirectory()
18
+ if (isDirectory) {
19
+ const glob = new Glob(path.join(SCRIPTS_PATH, '**/*.run.ts'))
20
+ for await (let file of glob.scan('.')) {
21
+ let scriptModule = await import(file)
22
+ if (scriptModule?.default?._isScript_ && scriptModule?.default?.enabled) {
23
+ scripts.push({
24
+ ...scriptModule?.default,
25
+ rest: new useRest({
26
+ tenant_id: tenant.id,
27
+ })
28
+ })
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ for (let script of scripts) {
35
+ asyncContextStorage.run(new Map(), async () => {
36
+ requestCtxStorage.set('trace', { id: crypto.randomUUID() })
37
+ requestCtxStorage.set('internal', true)
38
+
39
+ await script.exec({
40
+ rest: script.rest
41
+ })
42
+ })
43
+ }
44
+ }
45
+ export {
46
+ runScripts
47
+ }
@@ -0,0 +1,45 @@
1
+ import { Glob } from "bun"
2
+ import { cfg } from "../server/config"
3
+ import path from "path"
4
+ import fs from "fs/promises"
5
+ import { useRest } from "../database/rest"
6
+
7
+
8
+ async function loadServices() {
9
+ try {
10
+ let services = []
11
+ for (let tenant of cfg.tenants ?? []) {
12
+ const TENANT_PATH = path.join(process.cwd(), tenant.dir)
13
+ const SERVICES_PATH = path.join(TENANT_PATH, 'services')
14
+ let exist = await fs.exists(SERVICES_PATH)
15
+ if (!exist) continue;
16
+ const isDirectory = await (await fs.stat(SERVICES_PATH)).isDirectory()
17
+ if (isDirectory) {
18
+ const glob = new Glob(path.join(SERVICES_PATH, '**/*.service.ts'))
19
+ for await (let file of glob.scan('.')) {
20
+ let serviceModule = await import(file)
21
+ if (serviceModule?.default?._isService_) {
22
+ services.push({
23
+ ...serviceModule?.default,
24
+ _tenant_: tenant.id,
25
+ rest: new useRest({
26
+ tenant_id: tenant.id,
27
+ })
28
+ })
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ cfg.services = services
35
+
36
+ } catch (err: any) {
37
+ console.error(err?.message)
38
+ }
39
+
40
+
41
+ }
42
+
43
+ export {
44
+ loadServices
45
+ }
package/lib/sockets.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { Glob } from "bun"
2
+ import { cfg } from "../server/config"
3
+ import path from "path"
4
+ import fs from "fs/promises"
5
+ import { useRest } from "../database/rest"
6
+ import { io } from "../server/io"
7
+ import type { WebSocketHandler } from "../types/websocket"
8
+
9
+
10
+ async function loadSockets() {
11
+ try {
12
+ for (let tenant of cfg.tenants ?? []) {
13
+ const TENANT_PATH = path.join(process.cwd(), tenant.dir)
14
+ const SOCKETS_PATH = path.join(TENANT_PATH, 'sockets')
15
+ const exist = await fs.exists(SOCKETS_PATH)
16
+ if (!exist) continue
17
+ const isDirectory = await (await fs.stat(SOCKETS_PATH)).isDirectory()
18
+ if (!isDirectory) continue
19
+
20
+ const glob = new Glob(path.join(SOCKETS_PATH, '**/*.ws.ts'))
21
+ for await (let file of glob.scan('.')) {
22
+ const socketModule = await import(file)
23
+ const handler = socketModule?.default as WebSocketHandler | undefined
24
+
25
+ if (handler?._isWebSocket_ && handler.enabled) {
26
+ const rest = new useRest({ tenant_id: tenant.id })
27
+
28
+ io.on('connection', (socket) => {
29
+ handler.exec({ io, rest, socket })
30
+ })
31
+
32
+ console.log(`[socket] ${tenant.id}/${path.basename(file, '.ws.ts')} loaded`)
33
+ }
34
+ }
35
+ }
36
+
37
+ } catch (err: any) {
38
+ console.error('[socket] Failed to load sockets:', err?.message)
39
+ }
40
+ }
41
+
42
+ export {
43
+ loadSockets
44
+ }
@@ -0,0 +1,60 @@
1
+ import { Glob } from "bun"
2
+ import { cfg } from "../server/config"
3
+ import path from "path"
4
+ import fs from "fs/promises"
5
+ import type { WorkflowDefinition } from "../types/workflow"
6
+ import { getTenant } from "../database/tenant"
7
+
8
+ const workflows: Map<string, WorkflowDefinition> = new Map();
9
+
10
+ async function syncWorkflows() {
11
+ try {
12
+ workflows.clear();
13
+ for (let tenant of cfg.tenants ?? []) {
14
+ const TENANT_PATH = path.join(process.cwd(), tenant.dir)
15
+ const WORKFLOWS_PATH = path.join(TENANT_PATH, 'workflows')
16
+ let exist = await fs.exists(WORKFLOWS_PATH)
17
+ if (!exist) continue;
18
+ const isDirectory = await (await fs.stat(WORKFLOWS_PATH)).isDirectory()
19
+ if (!isDirectory) continue;
20
+
21
+ const glob = new Glob(path.join(WORKFLOWS_PATH, '**/*.workflow.ts'))
22
+ for await (let file of glob.scan('.')) {
23
+ let module = await import(file)
24
+ if (module?.default?._isWorkflow_) {
25
+ const wf: WorkflowDefinition = { ...module.default, _tenant_: tenant.id }
26
+ workflows.set(`${tenant.id}:${wf.id}`, wf)
27
+ }
28
+ }
29
+ }
30
+
31
+ // Créer les indexes sur _workflows_ pour les contextes définis
32
+ for (const [key, wf] of workflows) {
33
+ const tenantId = key.split(':')[0]
34
+ if (!wf.context || !tenantId) continue
35
+ const tenant = getTenant(tenantId)
36
+ const db = tenant?.database?.db
37
+ if (!db) continue
38
+
39
+ for (const [field, config] of Object.entries(wf.context)) {
40
+ const direction = config.index === true || config.index === 1 ? 1 : config.index === -1 ? -1 : 0
41
+ if (direction === 0) continue
42
+
43
+ try {
44
+ const indexKey = `context.${field}`
45
+ await db.collection('_workflows_').createIndex({ [indexKey]: direction })
46
+ } catch (err: any) {
47
+ console.error(`Failed to create index on _workflows_.${field}:`, err?.message)
48
+ }
49
+ }
50
+ }
51
+ } catch (err: any) {
52
+ console.error('Failed to sync workflows:', err?.message)
53
+ }
54
+ }
55
+
56
+ function getWorkflow(id: string, tenantId: string): WorkflowDefinition | undefined {
57
+ return workflows.get(`${tenantId}:${id}`)
58
+ }
59
+
60
+ export { syncWorkflows, getWorkflow }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@anteros/core",
3
+ "module": "index.ts",
4
+ "version": "0.0.1-alpha.1",
5
+ "type": "module",
6
+ "description": "Anteros Core",
7
+ "private": false,
8
+ "engines": {
9
+ "bun": ">=1.3.0"
10
+ },
11
+ "devDependencies": {
12
+ "@types/bun": "^1.3.14"
13
+ },
14
+ "peerDependencies": {
15
+ "typescript": "6.0.3"
16
+ },
17
+ "dependencies": {
18
+ "@colors/colors": "^1.6.0",
19
+ "@socket.io/bun-engine": "^0.1.1",
20
+ "bentocache": "^1.6.1",
21
+ "boxen": "^8.0.1",
22
+ "dayjs": "^1.11.21",
23
+ "hono": "^4.12.25",
24
+ "ioredis": "^5.11.1",
25
+ "joi": "^18.2.1",
26
+ "jose": "^6.2.3",
27
+ "mongodb": "7.2.0",
28
+ "socket.io": "^4.8.3",
29
+ "ufo": "^1.6.4"
30
+ }
31
+ }