hola-server 1.0.11 → 3.0.0
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 +382 -1
- package/dist/config/index.d.ts +46 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +55 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/array.d.ts +27 -0
- package/dist/core/array.d.ts.map +1 -0
- package/dist/core/array.js +66 -0
- package/dist/core/array.js.map +1 -0
- package/dist/core/bash.d.ts +51 -0
- package/dist/core/bash.d.ts.map +1 -0
- package/dist/core/bash.js +161 -0
- package/dist/core/bash.js.map +1 -0
- package/dist/core/chart.d.ts +11 -0
- package/dist/core/chart.d.ts.map +1 -0
- package/dist/core/chart.js +35 -0
- package/dist/core/chart.js.map +1 -0
- package/dist/core/date.d.ts +11 -0
- package/dist/core/date.d.ts.map +1 -0
- package/dist/core/date.js +18 -0
- package/dist/core/date.js.map +1 -0
- package/dist/core/encrypt.d.ts +18 -0
- package/dist/core/encrypt.d.ts.map +1 -0
- package/dist/core/encrypt.js +50 -0
- package/dist/core/encrypt.js.map +1 -0
- package/dist/core/file.d.ts +22 -0
- package/dist/core/file.d.ts.map +1 -0
- package/dist/core/file.js +21 -0
- package/dist/core/file.js.map +1 -0
- package/dist/core/lhs.d.ts +17 -0
- package/dist/core/lhs.d.ts.map +1 -0
- package/dist/core/lhs.js +30 -0
- package/dist/core/lhs.js.map +1 -0
- package/dist/core/meta.d.ts +200 -0
- package/dist/core/meta.d.ts.map +1 -0
- package/dist/core/meta.js +336 -0
- package/dist/core/meta.js.map +1 -0
- package/dist/core/number.d.ts +37 -0
- package/dist/core/number.d.ts.map +1 -0
- package/dist/core/number.js +99 -0
- package/dist/core/number.js.map +1 -0
- package/dist/core/obj.d.ts +9 -0
- package/dist/core/obj.d.ts.map +1 -0
- package/dist/core/obj.js +15 -0
- package/dist/core/obj.js.map +1 -0
- package/dist/core/random.d.ts +7 -0
- package/dist/core/random.d.ts.map +1 -0
- package/dist/core/random.js +7 -0
- package/dist/core/random.js.map +1 -0
- package/dist/core/role.d.ts +42 -0
- package/dist/core/role.d.ts.map +1 -0
- package/dist/core/role.js +81 -0
- package/dist/core/role.js.map +1 -0
- package/dist/core/thread.d.ts +7 -0
- package/dist/core/thread.d.ts.map +1 -0
- package/dist/core/thread.js +7 -0
- package/dist/core/thread.js.map +1 -0
- package/dist/core/type.d.ts +46 -0
- package/dist/core/type.d.ts.map +1 -0
- package/dist/core/type.js +281 -0
- package/dist/core/type.js.map +1 -0
- package/dist/core/url.d.ts +20 -0
- package/dist/core/url.d.ts.map +1 -0
- package/dist/core/url.js +24 -0
- package/dist/core/url.js.map +1 -0
- package/dist/core/validate.d.ts +11 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +19 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/db/db.d.ts +72 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +225 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/entity.d.ts +77 -0
- package/dist/db/entity.d.ts.map +1 -0
- package/dist/db/entity.js +671 -0
- package/dist/db/entity.js.map +1 -0
- package/dist/db/gridfs.d.ts +29 -0
- package/dist/db/gridfs.d.ts.map +1 -0
- package/dist/db/gridfs.js +125 -0
- package/dist/db/gridfs.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +8 -0
- package/dist/db/index.js.map +1 -0
- package/dist/errors/auth.d.ts +15 -0
- package/dist/errors/auth.d.ts.map +1 -0
- package/dist/errors/auth.js +21 -0
- package/dist/errors/auth.js.map +1 -0
- package/dist/errors/http.d.ts +15 -0
- package/dist/errors/http.d.ts.map +1 -0
- package/dist/errors/http.js +21 -0
- package/dist/errors/http.js.map +1 -0
- package/dist/errors/index.d.ts +18 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +18 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/validation.d.ts +11 -0
- package/dist/errors/validation.d.ts.map +1 -0
- package/dist/errors/validation.js +15 -0
- package/dist/errors/validation.js.map +1 -0
- package/dist/http/code.d.ts +21 -0
- package/dist/http/code.d.ts.map +1 -0
- package/dist/http/code.js +27 -0
- package/dist/http/code.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/meta/index.d.ts +9 -0
- package/dist/meta/index.d.ts.map +1 -0
- package/dist/meta/index.js +11 -0
- package/dist/meta/index.js.map +1 -0
- package/dist/meta/router.d.ts +26 -0
- package/dist/meta/router.d.ts.map +1 -0
- package/dist/meta/router.js +258 -0
- package/dist/meta/router.js.map +1 -0
- package/dist/meta/schema.d.ts +41 -0
- package/dist/meta/schema.d.ts.map +1 -0
- package/dist/meta/schema.js +69 -0
- package/dist/meta/schema.js.map +1 -0
- package/dist/plugins/auth.d.ts +248 -0
- package/dist/plugins/auth.d.ts.map +1 -0
- package/dist/plugins/auth.js +121 -0
- package/dist/plugins/auth.js.map +1 -0
- package/dist/plugins/body.d.ts +47 -0
- package/dist/plugins/body.d.ts.map +1 -0
- package/dist/plugins/body.js +36 -0
- package/dist/plugins/body.js.map +1 -0
- package/dist/plugins/cors.d.ts +62 -0
- package/dist/plugins/cors.d.ts.map +1 -0
- package/dist/plugins/cors.js +17 -0
- package/dist/plugins/cors.js.map +1 -0
- package/dist/plugins/error.d.ts +51 -0
- package/dist/plugins/error.d.ts.map +1 -0
- package/dist/plugins/error.js +51 -0
- package/dist/plugins/error.js.map +1 -0
- package/dist/plugins/index.d.ts +9 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/setting.d.ts +66 -0
- package/dist/setting.d.ts.map +1 -0
- package/dist/setting.js +27 -0
- package/dist/setting.js.map +1 -0
- package/dist/tool/gen_i18n.d.ts +10 -0
- package/dist/tool/gen_i18n.d.ts.map +1 -0
- package/dist/tool/gen_i18n.js +51 -0
- package/dist/tool/gen_i18n.js.map +1 -0
- package/dist/tool/vector_store.d.ts +72 -0
- package/dist/tool/vector_store.d.ts.map +1 -0
- package/dist/tool/vector_store.js +203 -0
- package/dist/tool/vector_store.js.map +1 -0
- package/package.json +38 -23
- package/core/array.js +0 -187
- package/core/bash.js +0 -345
- package/core/chart.js +0 -36
- package/core/cron.js +0 -10
- package/core/date.js +0 -55
- package/core/encrypt.js +0 -16
- package/core/file.js +0 -38
- package/core/lhs.js +0 -27
- package/core/meta.js +0 -359
- package/core/msg.js +0 -11
- package/core/number.js +0 -179
- package/core/obj.js +0 -22
- package/core/random.js +0 -9
- package/core/role.js +0 -116
- package/core/thread.js +0 -3
- package/core/type.js +0 -329
- package/core/url.js +0 -22
- package/core/validate.js +0 -32
- package/db/db.js +0 -376
- package/db/entity.js +0 -1252
- package/db/gridfs.js +0 -221
- package/http/code.js +0 -18
- package/http/context.js +0 -17
- package/http/cors.js +0 -15
- package/http/error.js +0 -21
- package/http/express.js +0 -75
- package/http/params.js +0 -57
- package/http/router.js +0 -72
- package/http/session.js +0 -50
- package/index.js +0 -36
- package/router/clone.js +0 -73
- package/router/create.js +0 -59
- package/router/delete.js +0 -53
- package/router/read.js +0 -177
- package/router/update.js +0 -107
- package/setting.js +0 -51
- package/test/core/date.js +0 -37
- package/test/core/encrypt.js +0 -14
- package/test/core/meta.js +0 -594
- package/test/core/number.js +0 -17
- package/test/crud/router.js +0 -99
- package/test/db/db.js +0 -72
- package/test/entity/create.js +0 -442
- package/test/entity/delete.js +0 -480
- package/test/entity/read.js +0 -285
- package/test/entity/update.js +0 -252
- package/test/router/role.js +0 -15
- package/test/router/user.js +0 -17
- package/tool/gen_i18n.js +0 -30
- package/tool/test.json +0 -25
package/README.md
CHANGED
|
@@ -1 +1,382 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Hola Server
|
|
2
|
+
|
|
3
|
+
A meta-programming framework for building RESTful APIs with **Bun + Elysia + MongoDB**. Define entity schemas declaratively and get fully-featured CRUD APIs with built-in authentication, role-based access control, file handling, and vector search — all out of the box.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- **Meta-Driven CRUD** — Define entity schemas with metadata, get full RESTful APIs automatically
|
|
8
|
+
- **Role-Based Access Control** — Fine-grained permissions per entity and operation (`admin:*`, `user:r`, `editor:cru`)
|
|
9
|
+
- **JWT Authentication** — Access + refresh token flow with hybrid delivery (cookies & Authorization header)
|
|
10
|
+
- **Type System** — 20+ built-in types with extensible validation and conversion
|
|
11
|
+
- **Schema Validation** — Auto-generated TypeBox schemas for request body validation
|
|
12
|
+
- **File Handling** — Built-in GridFS integration for file uploads and streaming
|
|
13
|
+
- **Vector Search** — SQLite-based vector similarity search via `sqlite-vec` for AI applications
|
|
14
|
+
- **Entity Relationships** — References with cascade/keep delete behavior and ref validation
|
|
15
|
+
- **Lifecycle Hooks** — Before/after hooks for create, update, clone, delete, and read operations
|
|
16
|
+
- **Query Building** — Advanced search, filtering, comparison operators, and pagination
|
|
17
|
+
- **Environment Config** — Configuration loader with environment-specific files (dev/test/prod)
|
|
18
|
+
- **Comprehensive Testing** — 25 test files covering core, database, entity, and cleanup
|
|
19
|
+
|
|
20
|
+
## 📦 Tech Stack
|
|
21
|
+
|
|
22
|
+
| Layer | Technology |
|
|
23
|
+
|-------|-----------|
|
|
24
|
+
| Runtime | [Bun](https://bun.sh) |
|
|
25
|
+
| HTTP Framework | [Elysia](https://elysiajs.com) v1.2+ |
|
|
26
|
+
| Database | [MongoDB](https://www.mongodb.com) 6.x |
|
|
27
|
+
| File Storage | MongoDB GridFS |
|
|
28
|
+
| Vector Search | [sqlite-vec](https://github.com/asg017/sqlite-vec) + better-sqlite3 |
|
|
29
|
+
| Auth | [@elysiajs/jwt](https://www.npmjs.com/package/@elysiajs/jwt) |
|
|
30
|
+
| Language | TypeScript 5.7+ |
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
### Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bun install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 1. Define an Entity
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { init_router } from "hola-server";
|
|
44
|
+
|
|
45
|
+
export const userRouter = init_router({
|
|
46
|
+
collection: "user",
|
|
47
|
+
primary_keys: ["email"],
|
|
48
|
+
ref_label: "name",
|
|
49
|
+
|
|
50
|
+
creatable: true,
|
|
51
|
+
readable: true,
|
|
52
|
+
updatable: true,
|
|
53
|
+
deleteable: true,
|
|
54
|
+
|
|
55
|
+
fields: [
|
|
56
|
+
{ name: "name", type: "string", required: true },
|
|
57
|
+
{ name: "email", type: "string", required: true },
|
|
58
|
+
{ name: "age", type: "uint" },
|
|
59
|
+
{ name: "role", ref: "role" },
|
|
60
|
+
{ name: "avatar", type: "file" },
|
|
61
|
+
],
|
|
62
|
+
|
|
63
|
+
roles: ["admin:*", "user:r", "editor:cru"],
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. Start the Server
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { Elysia } from "elysia";
|
|
71
|
+
import { plugins, db, meta } from "hola-server";
|
|
72
|
+
import { userRouter } from "./router/user.js";
|
|
73
|
+
|
|
74
|
+
const app = new Elysia()
|
|
75
|
+
.use(plugins.holaCors({ origin: ["http://localhost:5173"] }))
|
|
76
|
+
.use(plugins.holaBody({ limit: "10mb" }))
|
|
77
|
+
.use(plugins.holaAuth({ secret: process.env.JWT_SECRET! }))
|
|
78
|
+
.use(plugins.holaError())
|
|
79
|
+
.use(userRouter)
|
|
80
|
+
.onStart(async () => {
|
|
81
|
+
await db.get_db();
|
|
82
|
+
meta.validate_all_metas();
|
|
83
|
+
console.log("✓ Server ready on port 3000");
|
|
84
|
+
})
|
|
85
|
+
.listen(3000);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 📡 API Endpoints
|
|
89
|
+
|
|
90
|
+
Each entity router automatically generates these endpoints:
|
|
91
|
+
|
|
92
|
+
| Method | Path | Description |
|
|
93
|
+
|--------|------|-------------|
|
|
94
|
+
| `GET` | `/{entity}` | Simple list with query params |
|
|
95
|
+
| `POST` | `/{entity}/list` | List entities (full query: filter, sort, paginate) |
|
|
96
|
+
| `GET` | `/{entity}/:id` | Get single entity by ID |
|
|
97
|
+
| `POST` | `/{entity}` | Create entity |
|
|
98
|
+
| `PUT` | `/{entity}/:id` | Update entity |
|
|
99
|
+
| `DELETE` | `/{entity}/:id` | Delete entity |
|
|
100
|
+
| `GET` | `/{entity}/meta` | Get entity metadata and permissions |
|
|
101
|
+
| `GET` | `/{entity}/ref` | Get reference labels |
|
|
102
|
+
| `POST` | `/{entity}/:id/clone` | Clone entity (if cloneable) |
|
|
103
|
+
|
|
104
|
+
## 🏗 Entity Metadata
|
|
105
|
+
|
|
106
|
+
### Field Definition
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
interface FieldDefinition {
|
|
110
|
+
name: string; // Field name
|
|
111
|
+
type?: string; // Type for validation/conversion (default: "string")
|
|
112
|
+
required?: boolean; // Required on create
|
|
113
|
+
default?: FieldValue;// Default value
|
|
114
|
+
ref?: string; // Reference to another entity (collection name)
|
|
115
|
+
link?: string; // Link to another entity
|
|
116
|
+
delete?: "keep" | "cascade"; // Ref delete behavior
|
|
117
|
+
create?: boolean; // Include in create operation
|
|
118
|
+
list?: boolean; // Include in list response
|
|
119
|
+
search?: boolean; // Enable as search field
|
|
120
|
+
update?: boolean; // Include in update operation
|
|
121
|
+
clone?: boolean; // Include in clone operation
|
|
122
|
+
sys?: boolean; // System field (auto-managed)
|
|
123
|
+
secure?: boolean; // Exclude from client responses
|
|
124
|
+
view?: string; // View-based visibility
|
|
125
|
+
role?: string | string[]; // Role-based field visibility
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Built-in Types
|
|
130
|
+
|
|
131
|
+
| Category | Types |
|
|
132
|
+
|----------|-------|
|
|
133
|
+
| **String** | `string`, `lstr`, `text`, `enum`, `email`, `url`, `ip` |
|
|
134
|
+
| **Numeric** | `number`, `int`, `uint`, `float`, `ufloat`, `decimal`, `percentage`, `currency` |
|
|
135
|
+
| **Boolean** | `boolean` |
|
|
136
|
+
| **Date/Time** | `date`, `datetime` |
|
|
137
|
+
| **Security** | `password` (bcrypt hashed), `secret` (AES-256 encrypted) |
|
|
138
|
+
| **Other** | `file`, `array`, `obj`, `json`, `log_category` |
|
|
139
|
+
|
|
140
|
+
Custom types can be registered via `register_type()`.
|
|
141
|
+
|
|
142
|
+
### Operation Flags
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
{
|
|
146
|
+
creatable: true, // Enable POST endpoint
|
|
147
|
+
readable: true, // Enable GET endpoints
|
|
148
|
+
updatable: true, // Enable PUT endpoint
|
|
149
|
+
deleteable: true, // Enable DELETE endpoint
|
|
150
|
+
cloneable: true, // Enable clone endpoint
|
|
151
|
+
importable: true, // Enable bulk import
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Role Configuration
|
|
156
|
+
|
|
157
|
+
Format: `role_name:permissions` or `role_name:permissions:view`
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
roles: [
|
|
161
|
+
"admin:*", // Admin can do everything
|
|
162
|
+
"user:r", // User can only read
|
|
163
|
+
"editor:cru", // Editor can create/read/update
|
|
164
|
+
"viewer:r:basic" // Viewer can read with "basic" view only
|
|
165
|
+
]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Lifecycle Hooks
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
init_router({
|
|
172
|
+
collection: "order",
|
|
173
|
+
// ...fields and options...
|
|
174
|
+
|
|
175
|
+
before_create: async ({ entity, data }) => { /* validate before insert */ },
|
|
176
|
+
create: async ({ entity, data }) => { /* custom create logic */ },
|
|
177
|
+
after_create: async ({ entity, data }) => { /* post-create side effects */ },
|
|
178
|
+
|
|
179
|
+
before_update: async ({ id, entity, data }) => { /* pre-update checks */ },
|
|
180
|
+
update: async ({ id, entity, data }) => { /* custom update logic */ },
|
|
181
|
+
after_update: async ({ id, entity, data }) => { /* post-update actions */ },
|
|
182
|
+
|
|
183
|
+
before_delete: async ({ entity, ids }) => { /* pre-delete validation */ },
|
|
184
|
+
after_delete: async ({ entity, ids }) => { /* cleanup after delete */ },
|
|
185
|
+
|
|
186
|
+
after_read: async ({ id, entity, result }) => { /* transform read results */ },
|
|
187
|
+
list_query: async ({ entity, query }) => { /* modify list queries */ },
|
|
188
|
+
|
|
189
|
+
route: (router, meta) => { /* add custom routes */ },
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 🔌 Plugins
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import { plugins } from "hola-server";
|
|
197
|
+
|
|
198
|
+
// CORS with allowed origins
|
|
199
|
+
app.use(plugins.holaCors({ origin: ["http://localhost:5173"] }));
|
|
200
|
+
|
|
201
|
+
// Request body parsing with size limit
|
|
202
|
+
app.use(plugins.holaBody({ limit: "10mb" }));
|
|
203
|
+
|
|
204
|
+
// JWT auth with access + refresh tokens
|
|
205
|
+
app.use(plugins.holaAuth({
|
|
206
|
+
secret: "your-secret",
|
|
207
|
+
accessExpiry: "15m", // default
|
|
208
|
+
refreshExpiry: "7d", // default
|
|
209
|
+
excludeUrls: ["/health", /^\/public/],
|
|
210
|
+
}));
|
|
211
|
+
|
|
212
|
+
// Auth routes (POST /auth/refresh, POST /auth/logout)
|
|
213
|
+
app.use(plugins.holaAuthRoutes());
|
|
214
|
+
|
|
215
|
+
// Global error handling
|
|
216
|
+
app.use(plugins.holaError());
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 🗄 Database
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { db } from "hola-server";
|
|
223
|
+
|
|
224
|
+
// Direct MongoDB access
|
|
225
|
+
const database = await db.get_db();
|
|
226
|
+
const users = await database.collection("user").find({}).toArray();
|
|
227
|
+
|
|
228
|
+
// Entity-level operations
|
|
229
|
+
const entity = new db.Entity("user");
|
|
230
|
+
await entity.create_entity(data, "*");
|
|
231
|
+
await entity.read_entity(id, "*", "*");
|
|
232
|
+
await entity.update_entity(id, updates, "*");
|
|
233
|
+
await entity.delete_entity([id]);
|
|
234
|
+
await entity.list_entity(queryParams, query, searchParams, role);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 📁 File Storage (GridFS)
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { db } from "hola-server";
|
|
241
|
+
|
|
242
|
+
// Save file from buffer (FormData uploads)
|
|
243
|
+
await db.save_file_from_buffer("avatars", "user_123.png", buffer);
|
|
244
|
+
|
|
245
|
+
// Read file
|
|
246
|
+
const fileBuffer = await db.read_file("avatars", "user_123.png");
|
|
247
|
+
|
|
248
|
+
// Stream file
|
|
249
|
+
const stream = await db.read_file_stream("avatars", "user_123.png");
|
|
250
|
+
|
|
251
|
+
// Delete file
|
|
252
|
+
await db.delete_file("avatars", "user_123.png");
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## 🔍 Vector Search
|
|
256
|
+
|
|
257
|
+
SQLite-based vector similarity search for AI/embedding applications:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { VectorStore, initVectorStore } from "hola-server";
|
|
261
|
+
|
|
262
|
+
const store = await initVectorStore({
|
|
263
|
+
dbPath: "./data/vectors.db",
|
|
264
|
+
dimensions: 1536,
|
|
265
|
+
tableName: "embeddings",
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Insert vectors with metadata
|
|
269
|
+
await store.insert("doc_1", embedding, { category: "article" });
|
|
270
|
+
await store.insertBatch(records);
|
|
271
|
+
|
|
272
|
+
// Search similar vectors
|
|
273
|
+
const results = await store.search(queryEmbedding, 10, { category: "article" });
|
|
274
|
+
// => [{ id, distance, score, metadata }]
|
|
275
|
+
|
|
276
|
+
// Manage vectors
|
|
277
|
+
await store.delete("doc_1");
|
|
278
|
+
await store.deleteByFilter({ category: "old" });
|
|
279
|
+
const count = await store.count();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## ⚙️ Configuration
|
|
283
|
+
|
|
284
|
+
### Environment-Based Config
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { config } from "hola-server";
|
|
288
|
+
|
|
289
|
+
const appConfig = await config.load_config(__dirname + "/config");
|
|
290
|
+
// Loads config/dev.ts, config/test.ts, or config/prod.ts based on NODE_ENV
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Settings
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { init_settings } from "hola-server";
|
|
297
|
+
|
|
298
|
+
init_settings({
|
|
299
|
+
mongo: { url: "mongodb://localhost:27017/myapp", pool: 10 },
|
|
300
|
+
encrypt: { key: "my-encryption-key" },
|
|
301
|
+
roles: [{ name: "admin", root: true }, { name: "user" }],
|
|
302
|
+
server: {
|
|
303
|
+
service_port: 8088,
|
|
304
|
+
client_web_url: ["http://localhost:5173"],
|
|
305
|
+
keep_session: true,
|
|
306
|
+
check_user: true,
|
|
307
|
+
exclude_urls: ["/"],
|
|
308
|
+
session: { cookie_max_age: 86400000, secret: "session-secret" },
|
|
309
|
+
threshold: { max_download_size: 5000, body_limit: "10mb", default_list_limit: 1000 },
|
|
310
|
+
routes: ["router"],
|
|
311
|
+
},
|
|
312
|
+
axios: { retry: 3, retry_delay: 1000, proxy: null },
|
|
313
|
+
log: { col_log: "log", log_level: 0, save_db: true },
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## 🧰 Core Utilities
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { array, date, validate, encrypt, random, bash, file, obj, number, lhs } from "hola-server";
|
|
321
|
+
|
|
322
|
+
// Array utilities
|
|
323
|
+
array.unique([1, 2, 2, 3]); // [1, 2, 3]
|
|
324
|
+
|
|
325
|
+
// Encryption
|
|
326
|
+
const hashed = encrypt_pwd("password");
|
|
327
|
+
const encrypted = encrypt_secret("api-key");
|
|
328
|
+
const decrypted = decrypt_secret(encrypted);
|
|
329
|
+
|
|
330
|
+
// And more: date formatting, validation, bash execution, file I/O, etc.
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## 🧪 Testing
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
bun test
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
25 test files covering:
|
|
340
|
+
- **Core**: array, chart, date, encrypt, file, lhs, meta, number, obj, random, thread, type, validate
|
|
341
|
+
- **Database**: connection, operations, entity class, GridFS
|
|
342
|
+
- **Entity CRUD**: create, read, update, delete, clone, ref-filter
|
|
343
|
+
|
|
344
|
+
## 📂 Project Structure
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
hola-server/
|
|
348
|
+
├── src/
|
|
349
|
+
│ ├── index.ts # Public API entry point
|
|
350
|
+
│ ├── setting.ts # Application settings
|
|
351
|
+
│ ├── config/ # Environment-based config loader
|
|
352
|
+
│ ├── core/ # Core utilities (16 modules)
|
|
353
|
+
│ │ ├── meta.ts # Entity metadata & lifecycle hooks
|
|
354
|
+
│ │ ├── type.ts # Type system & validation
|
|
355
|
+
│ │ ├── role.ts # Role-based access control
|
|
356
|
+
│ │ ├── encrypt.ts # Password hashing & AES encryption
|
|
357
|
+
│ │ └── ... # array, bash, chart, date, file, etc.
|
|
358
|
+
│ ├── db/ # Database layer
|
|
359
|
+
│ │ ├── db.ts # MongoDB connection & helpers
|
|
360
|
+
│ │ ├── entity.ts # Entity CRUD operations
|
|
361
|
+
│ │ └── gridfs.ts # GridFS file storage
|
|
362
|
+
│ ├── meta/ # Meta programming
|
|
363
|
+
│ │ ├── router.ts # Auto RESTful route generation
|
|
364
|
+
│ │ └── schema.ts # TypeBox schema generation
|
|
365
|
+
│ ├── plugins/ # Elysia plugins
|
|
366
|
+
│ │ ├── auth.ts # JWT authentication
|
|
367
|
+
│ │ ├── cors.ts # CORS configuration
|
|
368
|
+
│ │ ├── body.ts # Body parser
|
|
369
|
+
│ │ └── error.ts # Error handling
|
|
370
|
+
│ ├── errors/ # Error classes (auth, http, validation)
|
|
371
|
+
│ ├── http/ # HTTP status codes
|
|
372
|
+
│ └── tool/ # Tools
|
|
373
|
+
│ ├── gen_i18n.ts # i18n key generation
|
|
374
|
+
│ └── vector_store.ts # Vector similarity search
|
|
375
|
+
├── test/ # Test suite (25 test files)
|
|
376
|
+
├── package.json
|
|
377
|
+
└── tsconfig.json
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## 📄 License
|
|
381
|
+
|
|
382
|
+
ISC
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for environment-based settings.
|
|
3
|
+
* @module config
|
|
4
|
+
*/
|
|
5
|
+
export interface AppConfig {
|
|
6
|
+
/** Server port */
|
|
7
|
+
port: number;
|
|
8
|
+
/** JWT configuration */
|
|
9
|
+
jwt: {
|
|
10
|
+
secret: string;
|
|
11
|
+
accessExpiry: string;
|
|
12
|
+
refreshExpiry: string;
|
|
13
|
+
};
|
|
14
|
+
/** CORS configuration */
|
|
15
|
+
cors: {
|
|
16
|
+
origin: string[] | true;
|
|
17
|
+
credentials?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Body parser configuration */
|
|
20
|
+
body: {
|
|
21
|
+
limit: string | number;
|
|
22
|
+
};
|
|
23
|
+
/** Database configuration */
|
|
24
|
+
db: {
|
|
25
|
+
url: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Load configuration from environment-specific file.
|
|
30
|
+
* Looks for config files in the specified directory based on NODE_ENV.
|
|
31
|
+
*
|
|
32
|
+
* @param config_dir Directory containing config files (dev.ts, test.ts, prod.ts)
|
|
33
|
+
* @returns Promise resolving to AppConfig
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const config = await load_config(__dirname + '/config');
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare const load_config: (config_dir: string) => Promise<AppConfig>;
|
|
41
|
+
/**
|
|
42
|
+
* Create a base config with common defaults.
|
|
43
|
+
* Use this as a starting point for environment configs.
|
|
44
|
+
*/
|
|
45
|
+
export declare const create_base_config: (overrides?: Partial<AppConfig>) => AppConfig;
|
|
46
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACtB,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,GAAG,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,yBAAyB;IACzB,IAAI,EAAE;QACF,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,WAAW,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,gCAAgC;IAChC,IAAI,EAAE;QACF,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;KAC1B,CAAC;IACF,6BAA6B;IAC7B,EAAE,EAAE;QACA,GAAG,EAAE,MAAM,CAAC;KACf,CAAC;CACL;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,SAAS,CAUvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,YAAW,OAAO,CAAC,SAAS,CAAM,KAAG,SAsBtE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for environment-based settings.
|
|
3
|
+
* @module config
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Load configuration from environment-specific file.
|
|
7
|
+
* Looks for config files in the specified directory based on NODE_ENV.
|
|
8
|
+
*
|
|
9
|
+
* @param config_dir Directory containing config files (dev.ts, test.ts, prod.ts)
|
|
10
|
+
* @returns Promise resolving to AppConfig
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const config = await load_config(__dirname + '/config');
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export const load_config = async (config_dir) => {
|
|
18
|
+
const env = process.env.NODE_ENV || 'dev';
|
|
19
|
+
const config_path = `${config_dir}/${env}`;
|
|
20
|
+
try {
|
|
21
|
+
const module = await import(config_path);
|
|
22
|
+
return module.default;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new Error(`Failed to load config for environment '${env}' from ${config_path}: ${error}`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Create a base config with common defaults.
|
|
30
|
+
* Use this as a starting point for environment configs.
|
|
31
|
+
*/
|
|
32
|
+
export const create_base_config = (overrides = {}) => ({
|
|
33
|
+
port: 3000,
|
|
34
|
+
jwt: {
|
|
35
|
+
secret: 'change-this-in-production',
|
|
36
|
+
accessExpiry: '15m',
|
|
37
|
+
refreshExpiry: '7d',
|
|
38
|
+
...overrides.jwt
|
|
39
|
+
},
|
|
40
|
+
cors: {
|
|
41
|
+
origin: ['http://localhost:5173'],
|
|
42
|
+
credentials: true,
|
|
43
|
+
...overrides.cors
|
|
44
|
+
},
|
|
45
|
+
body: {
|
|
46
|
+
limit: '10mb',
|
|
47
|
+
...overrides.body
|
|
48
|
+
},
|
|
49
|
+
db: {
|
|
50
|
+
url: 'mongodb://localhost:27017/hola',
|
|
51
|
+
...overrides.db
|
|
52
|
+
},
|
|
53
|
+
...overrides
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,UAAkB,EAAsB,EAAE;IACxE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC1C,MAAM,WAAW,GAAG,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC;IAE3C,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,OAAoB,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,UAAU,WAAW,KAAK,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;AACL,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,YAAgC,EAAE,EAAa,EAAE,CAAC,CAAC;IAClF,IAAI,EAAE,IAAI;IACV,GAAG,EAAE;QACD,MAAM,EAAE,2BAA2B;QACnC,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,IAAI;QACnB,GAAG,SAAS,CAAC,GAAG;KACnB;IACD,IAAI,EAAE;QACF,MAAM,EAAE,CAAC,uBAAuB,CAAC;QACjC,WAAW,EAAE,IAAI;QACjB,GAAG,SAAS,CAAC,IAAI;KACpB;IACD,IAAI,EAAE;QACF,KAAK,EAAE,MAAM;QACb,GAAG,SAAS,CAAC,IAAI;KACpB;IACD,EAAE,EAAE;QACA,GAAG,EAAE,gCAAgC;QACrC,GAAG,SAAS,CAAC,EAAE;KAClB;IACD,GAAG,SAAS;CACf,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array manipulation utility functions.
|
|
3
|
+
* @module core/array
|
|
4
|
+
*/
|
|
5
|
+
/** Shuffle array elements randomly in place. */
|
|
6
|
+
export declare const shuffle: <T>(arr: T[]) => void;
|
|
7
|
+
/** Remove elements from array by matching field value. */
|
|
8
|
+
export declare const remove_element: <T, K extends keyof T>(array: T[], field: K, value: T[K]) => void;
|
|
9
|
+
export declare const pop_n: <T>(array: T[], n: number) => T[] | undefined;
|
|
10
|
+
export declare const shift_n: <T>(array: T[], n: number) => T[] | undefined;
|
|
11
|
+
/** Calculate sum of number array. */
|
|
12
|
+
export declare const sum: (arr: number[]) => number;
|
|
13
|
+
/** Calculate average of number array. */
|
|
14
|
+
export declare const avg: (arr: number[]) => number;
|
|
15
|
+
/** Convert array of objects to key-value object. */
|
|
16
|
+
export declare const map_array_to_obj: <T, K extends keyof T, V extends keyof T>(arr: T[], key_attr: K, value_attr: V) => Record<string, T[V]>;
|
|
17
|
+
/** Sort array of objects by attribute. */
|
|
18
|
+
export declare const sort_by_attr: <T extends Record<string, number>>(arr: T[], attr: keyof T, desc?: boolean) => T[];
|
|
19
|
+
export declare const sort_desc: <T extends Record<string, number>>(arr: T[], attr: keyof T) => T[];
|
|
20
|
+
export declare const sort_asc: <T extends Record<string, number>>(arr: T[], attr: keyof T) => T[];
|
|
21
|
+
/** Sort array by predefined key sequence. */
|
|
22
|
+
export declare const sort_by_key_seq: <T, K extends keyof T>(arr: T[], attr: K, keys: T[K][]) => T[];
|
|
23
|
+
/** Create cartesian product of two object arrays. */
|
|
24
|
+
export declare const combine: <T extends object, U extends object>(arr1: T[], arr2: U[]) => (T & U)[];
|
|
25
|
+
/** Remove duplicate elements from array. */
|
|
26
|
+
export declare const unique: <T>(array: T[]) => T[];
|
|
27
|
+
//# sourceMappingURL=array.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/core/array.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,gDAAgD;AAChD,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,KAAK,CAAC,EAAE,KAAG,IAKrC,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAG,IAIxF,CAAC;AAaF,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,MAAM,KAAG,CAAC,EAAE,GAAG,SAAuC,CAAC;AAC/F,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,MAAM,KAAG,CAAC,EAAE,GAAG,SAAyC,CAAC;AAEnG,qCAAqC;AACrC,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,KAAG,MAAiE,CAAC;AAEtG,yCAAyC;AACzC,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,KAAG,MAAuE,CAAC;AAE5G,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAEnI,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,MAAM,CAAC,EAAE,OAAM,OAAe,KAAG,CAAC,EAGhH,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,MAAM,CAAC,KAAG,CAAC,EAAmC,CAAC;AAC3H,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,MAAM,CAAC,KAAG,CAAC,EAAoC,CAAC;AAE3H,6CAA6C;AAC7C,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAG,CAAC,EAGxF,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,KAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAEzF,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,OAAO,CAAC,EAAE,KAAG,CAAC,EAMvC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array manipulation utility functions.
|
|
3
|
+
* @module core/array
|
|
4
|
+
*/
|
|
5
|
+
import { round_to_fixed2 } from './number.js';
|
|
6
|
+
/** Shuffle array elements randomly in place. */
|
|
7
|
+
export const shuffle = (arr) => {
|
|
8
|
+
for (let i = arr.length; i; i--) {
|
|
9
|
+
const j = Math.floor(Math.random() * i);
|
|
10
|
+
[arr[i - 1], arr[j]] = [arr[j], arr[i - 1]];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/** Remove elements from array by matching field value. */
|
|
14
|
+
export const remove_element = (array, field, value) => {
|
|
15
|
+
for (let i = array.length - 1; i >= 0; --i) {
|
|
16
|
+
if (array[i][field] == value)
|
|
17
|
+
array.splice(i, 1);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/** Extract n elements from array using specified method. */
|
|
21
|
+
const extract_n = (array, n, method) => {
|
|
22
|
+
const result = [];
|
|
23
|
+
while (result.length < n) {
|
|
24
|
+
const ele = array[method]();
|
|
25
|
+
if (ele !== undefined)
|
|
26
|
+
result.push(ele);
|
|
27
|
+
else
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
return result.length > 0 ? result : undefined;
|
|
31
|
+
};
|
|
32
|
+
export const pop_n = (array, n) => extract_n(array, n, 'pop');
|
|
33
|
+
export const shift_n = (array, n) => extract_n(array, n, 'shift');
|
|
34
|
+
/** Calculate sum of number array. */
|
|
35
|
+
export const sum = (arr) => round_to_fixed2(arr.reduce((pre, cur) => pre + cur, 0));
|
|
36
|
+
/** Calculate average of number array. */
|
|
37
|
+
export const avg = (arr) => arr.length === 0 ? 0 : round_to_fixed2(sum(arr) / arr.length);
|
|
38
|
+
/** Convert array of objects to key-value object. */
|
|
39
|
+
export const map_array_to_obj = (arr, key_attr, value_attr) => {
|
|
40
|
+
return arr.reduce((obj, el) => ({ ...obj, [String(el[key_attr])]: el[value_attr] }), {});
|
|
41
|
+
};
|
|
42
|
+
/** Sort array of objects by attribute. */
|
|
43
|
+
export const sort_by_attr = (arr, attr, desc = false) => {
|
|
44
|
+
arr.sort((a, b) => desc ? b[attr] - a[attr] : a[attr] - b[attr]);
|
|
45
|
+
return arr;
|
|
46
|
+
};
|
|
47
|
+
export const sort_desc = (arr, attr) => sort_by_attr(arr, attr, true);
|
|
48
|
+
export const sort_asc = (arr, attr) => sort_by_attr(arr, attr, false);
|
|
49
|
+
/** Sort array by predefined key sequence. */
|
|
50
|
+
export const sort_by_key_seq = (arr, attr, keys) => {
|
|
51
|
+
arr.sort((a, b) => keys.indexOf(a[attr]) - keys.indexOf(b[attr]));
|
|
52
|
+
return arr;
|
|
53
|
+
};
|
|
54
|
+
/** Create cartesian product of two object arrays. */
|
|
55
|
+
export const combine = (arr1, arr2) => {
|
|
56
|
+
return arr1.flatMap(obj1 => arr2.map(obj2 => ({ ...obj1, ...obj2 })));
|
|
57
|
+
};
|
|
58
|
+
/** Remove duplicate elements from array. */
|
|
59
|
+
export const unique = (array) => {
|
|
60
|
+
const seen = new Map();
|
|
61
|
+
return array.filter(value => {
|
|
62
|
+
const key = JSON.stringify(value);
|
|
63
|
+
return seen.has(key) ? false : (seen.set(key, true), true);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=array.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../src/core/array.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,gDAAgD;AAChD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,GAAQ,EAAQ,EAAE;IACzC,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;AACL,CAAC,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAuB,KAAU,EAAE,KAAQ,EAAE,KAAW,EAAQ,EAAE;IAC5F,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACzC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;AACL,CAAC,CAAC;AAEF,4DAA4D;AAC5D,MAAM,SAAS,GAAG,CAAI,KAAU,EAAE,CAAS,EAAE,MAAuB,EAAmB,EAAE;IACrF,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;YACnC,MAAM;IACf,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CAAI,KAAU,EAAE,CAAS,EAAmB,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AAC/F,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,KAAU,EAAE,CAAS,EAAmB,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AAEnG,qCAAqC;AACrC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAa,EAAU,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtG,yCAAyC;AACzC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAa,EAAU,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;AAE5G,oDAAoD;AACpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAA0C,GAAQ,EAAE,QAAW,EAAE,UAAa,EAAwB,EAAE;IACpI,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAA0B,CAAC,CAAC;AACrH,CAAC,CAAC;AAEF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAmC,GAAQ,EAAE,IAAa,EAAE,OAAgB,KAAK,EAAO,EAAE;IAClH,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,OAAO,GAAG,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAmC,GAAQ,EAAE,IAAa,EAAO,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC3H,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAmC,GAAQ,EAAE,IAAa,EAAO,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAE3H,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAuB,GAAQ,EAAE,IAAO,EAAE,IAAY,EAAO,EAAE;IAC1F,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,GAAG,CAAC;AACf,CAAC,CAAC;AAEF,qDAAqD;AACrD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAqC,IAAS,EAAE,IAAS,EAAa,EAAE;IAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAI,KAAU,EAAO,EAAE;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;IACxC,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bash command execution and SSH utility functions.
|
|
3
|
+
* @module core/bash
|
|
4
|
+
*/
|
|
5
|
+
/** Serializable log value types. */
|
|
6
|
+
export type LogValue = string | number | boolean | null | undefined | LogValue[] | {
|
|
7
|
+
[key: string]: LogValue;
|
|
8
|
+
};
|
|
9
|
+
export type LogExtra = Record<string, LogValue>;
|
|
10
|
+
export interface Host {
|
|
11
|
+
name: string;
|
|
12
|
+
ip: string;
|
|
13
|
+
port: number;
|
|
14
|
+
user: string;
|
|
15
|
+
auth: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CommandResult {
|
|
18
|
+
stdout: string;
|
|
19
|
+
err?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SystemAttribute {
|
|
22
|
+
name: string;
|
|
23
|
+
cmd: string;
|
|
24
|
+
}
|
|
25
|
+
/** Run command on local host. */
|
|
26
|
+
export declare const run_local_cmd: (cmd: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
27
|
+
/** Run simple command locally and get trimmed result. */
|
|
28
|
+
export declare const run_simple_local_cmd: (cmd: string, log_extra?: LogExtra) => Promise<string | null>;
|
|
29
|
+
/** Run script on remote host via SSH. */
|
|
30
|
+
export declare const run_script: (host: Host, script: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
31
|
+
/** Run script on remote host with file redirect to avoid progress bar issues. */
|
|
32
|
+
export declare const run_script_extra: (host: Host, script: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
33
|
+
/** Run script file on remote host. */
|
|
34
|
+
export declare const run_script_file: (host: Host, script_file: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
35
|
+
/** SCP remote file to local. */
|
|
36
|
+
export declare const scp: (host: Host, remote_file: string, local_file: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
37
|
+
/** SCP local file to remote. */
|
|
38
|
+
export declare const scpr: (host: Host, local_file: string, remote_file: string, log_extra?: LogExtra) => Promise<CommandResult>;
|
|
39
|
+
/** Run simple command on remote host and get trimmed result. */
|
|
40
|
+
export declare const run_simple_cmd: (host: Host, cmd: string, log_extra?: LogExtra) => Promise<string | null>;
|
|
41
|
+
/** Extract info from stdout using regex pattern matching. */
|
|
42
|
+
export declare const get_info: (stdout: string, key: string, log_extra?: LogExtra) => string[];
|
|
43
|
+
/** Read key-value pairs from stdout. */
|
|
44
|
+
export declare const read_key_value_line: (stdout: string, delimiter?: string, lines?: number[], config?: Record<string, boolean>, exclude_mode?: boolean) => Record<string, string>;
|
|
45
|
+
/** Read structured lines into array of objects. */
|
|
46
|
+
export declare const read_obj_line: (stdout: string, keys: string[], ignore?: number, delimiter?: string) => Record<string, string>[];
|
|
47
|
+
/** Get multiple system attributes from remote host. */
|
|
48
|
+
export declare const get_system_attributes: (host: Host, attrs: SystemAttribute[], log_extra?: LogExtra) => Promise<Record<string, string>>;
|
|
49
|
+
/** Stop process on remote host if running. */
|
|
50
|
+
export declare const stop_process: (host: Host, process_name: string, stop_cmd: string, using_full?: boolean, log_extra?: LogExtra) => Promise<boolean>;
|
|
51
|
+
//# sourceMappingURL=bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/core/bash.ts"],"names":[],"mappings":"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"}
|