@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.
- package/README.md +143 -0
- package/database/collection.ts +160 -0
- package/database/decorator.ts +172 -0
- package/database/file.ts +93 -0
- package/database/mongodbadapter.ts +1128 -0
- package/database/rest.ts +14 -0
- package/database/schema.ts +160 -0
- package/database/tenant.ts +37 -0
- package/database/workflow.ts +384 -0
- package/index.ts +28 -0
- package/lib/asyncContextStorage.ts +68 -0
- package/lib/define.ts +114 -0
- package/lib/error.ts +21 -0
- package/lib/files.ts +459 -0
- package/lib/middleware.ts +66 -0
- package/lib/routes.ts +44 -0
- package/lib/scripts.ts +47 -0
- package/lib/services.ts +45 -0
- package/lib/sockets.ts +44 -0
- package/lib/workflow.ts +60 -0
- package/package.json +31 -0
- package/server/api.ts +789 -0
- package/server/boot.ts +101 -0
- package/server/config.ts +107 -0
- package/server/env.ts +16 -0
- package/server/hono.ts +176 -0
- package/server/io.ts +15 -0
- package/server/routes.ts +48 -0
- package/server/security.ts +138 -0
- package/tests/api.test.ts +281 -0
- package/tsconfig.json +36 -0
- package/types/activity.d.ts +45 -0
- package/types/api.d.ts +85 -0
- package/types/collection.d.ts +82 -0
- package/types/config.d.ts +55 -0
- package/types/field.d.ts +72 -0
- package/types/file.d.ts +120 -0
- package/types/hook.d.ts +30 -0
- package/types/middleware.d.ts +18 -0
- package/types/mongo.d.ts +61 -0
- package/types/options.d.ts +7 -0
- package/types/rest.d.ts +18 -0
- package/types/route.d.ts +19 -0
- package/types/schema.d.ts +0 -0
- package/types/scripts.d.ts +10 -0
- package/types/service.d.ts +37 -0
- package/types/task.d.ts +12 -0
- package/types/tenant.d.ts +16 -0
- package/types/token.d.ts +14 -0
- package/types/websocket.d.ts +15 -0
- package/types/workflow.d.ts +91 -0
- package/utils/cache.ts +96 -0
- package/utils/crypto.ts +226 -0
- package/utils/func.ts +1037 -0
- 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
|
+
}
|
package/lib/services.ts
ADDED
|
@@ -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
|
+
}
|
package/lib/workflow.ts
ADDED
|
@@ -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
|
+
}
|