@almadar/server 2.0.9 → 2.1.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/package.json +10 -4
- package/dist/contracts.d.ts +0 -174
- package/dist/contracts.d.ts.map +0 -1
- package/dist/deepagent/__tests__/memory.test.d.ts +0 -6
- package/dist/deepagent/__tests__/memory.test.d.ts.map +0 -1
- package/dist/deepagent/__tests__/session.test.d.ts +0 -6
- package/dist/deepagent/__tests__/session.test.d.ts.map +0 -1
- package/dist/deepagent/__tests__/skill-agent.test.d.ts +0 -6
- package/dist/deepagent/__tests__/skill-agent.test.d.ts.map +0 -1
- package/dist/deepagent/memory.d.ts +0 -17
- package/dist/deepagent/memory.d.ts.map +0 -1
- package/dist/deepagent/memory.js +0 -48
- package/dist/deepagent/memory.js.map +0 -1
- package/dist/deepagent/session.d.ts +0 -17
- package/dist/deepagent/session.d.ts.map +0 -1
- package/dist/deepagent/session.js +0 -68
- package/dist/deepagent/session.js.map +0 -1
- package/dist/deepagent/skill-agent.d.ts +0 -22
- package/dist/deepagent/skill-agent.d.ts.map +0 -1
- package/dist/deepagent/skill-agent.js +0 -114
- package/dist/deepagent/skill-agent.js.map +0 -1
- package/dist/index.d.ts +0 -42
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2460
- package/dist/index.js.map +0 -1
- package/dist/lib/db.d.ts +0 -36
- package/dist/lib/db.d.ts.map +0 -1
- package/dist/lib/debugRouter.d.ts +0 -21
- package/dist/lib/debugRouter.d.ts.map +0 -1
- package/dist/lib/env.d.ts +0 -16
- package/dist/lib/env.d.ts.map +0 -1
- package/dist/lib/eventBus.d.ts +0 -44
- package/dist/lib/eventBus.d.ts.map +0 -1
- package/dist/lib/eventBusTransport.d.ts +0 -143
- package/dist/lib/eventBusTransport.d.ts.map +0 -1
- package/dist/lib/eventPersistence.d.ts +0 -151
- package/dist/lib/eventPersistence.d.ts.map +0 -1
- package/dist/lib/index.d.ts +0 -6
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js +0 -288
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/logger.d.ts +0 -7
- package/dist/lib/logger.d.ts.map +0 -1
- package/dist/lib/serviceDiscovery.d.ts +0 -168
- package/dist/lib/serviceDiscovery.d.ts.map +0 -1
- package/dist/lib/websocket.d.ts +0 -41
- package/dist/lib/websocket.d.ts.map +0 -1
- package/dist/middleware/__tests__/multi-user.test.d.ts +0 -6
- package/dist/middleware/__tests__/multi-user.test.d.ts.map +0 -1
- package/dist/middleware/authenticateFirebase.d.ts +0 -4
- package/dist/middleware/authenticateFirebase.d.ts.map +0 -1
- package/dist/middleware/errorHandler.d.ts +0 -53
- package/dist/middleware/errorHandler.d.ts.map +0 -1
- package/dist/middleware/index.d.ts +0 -4
- package/dist/middleware/index.d.ts.map +0 -1
- package/dist/middleware/index.js +0 -284
- package/dist/middleware/index.js.map +0 -1
- package/dist/middleware/multi-user.d.ts +0 -34
- package/dist/middleware/multi-user.d.ts.map +0 -1
- package/dist/middleware/multi-user.js +0 -76
- package/dist/middleware/multi-user.js.map +0 -1
- package/dist/middleware/validation.d.ts +0 -15
- package/dist/middleware/validation.d.ts.map +0 -1
- package/dist/routes/__tests__/observability.test.d.ts +0 -6
- package/dist/routes/__tests__/observability.test.d.ts.map +0 -1
- package/dist/routes/observability.d.ts +0 -11
- package/dist/routes/observability.d.ts.map +0 -1
- package/dist/routes/observability.js +0 -62
- package/dist/routes/observability.js.map +0 -1
- package/dist/services/DataService.d.ts +0 -70
- package/dist/services/DataService.d.ts.map +0 -1
- package/dist/services/MockDataService.d.ts +0 -110
- package/dist/services/MockDataService.d.ts.map +0 -1
- package/dist/services/index.d.ts +0 -8
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js +0 -735
- package/dist/services/index.js.map +0 -1
- package/dist/stores/ChangeSetStore.d.ts +0 -24
- package/dist/stores/ChangeSetStore.d.ts.map +0 -1
- package/dist/stores/SchemaProtectionService.d.ts +0 -23
- package/dist/stores/SchemaProtectionService.d.ts.map +0 -1
- package/dist/stores/SchemaStore.d.ts +0 -52
- package/dist/stores/SchemaStore.d.ts.map +0 -1
- package/dist/stores/SnapshotStore.d.ts +0 -26
- package/dist/stores/SnapshotStore.d.ts.map +0 -1
- package/dist/stores/ValidationStore.d.ts +0 -19
- package/dist/stores/ValidationStore.d.ts.map +0 -1
- package/dist/stores/firestoreFormat.d.ts +0 -21
- package/dist/stores/firestoreFormat.d.ts.map +0 -1
- package/dist/stores/index.d.ts +0 -14
- package/dist/stores/index.d.ts.map +0 -1
- package/dist/stores/index.js +0 -519
- package/dist/stores/index.js.map +0 -1
- package/dist/utils/index.d.ts +0 -9
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -106
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/queryFilters.d.ts +0 -87
- package/dist/utils/queryFilters.d.ts.map +0 -1
- package/dist/websocket/__tests__/state-sync.test.d.ts +0 -6
- package/dist/websocket/__tests__/state-sync.test.d.ts.map +0 -1
- package/dist/websocket/state-sync.d.ts +0 -39
- package/dist/websocket/state-sync.d.ts.map +0 -1
- package/dist/websocket/state-sync.js +0 -77
- package/dist/websocket/state-sync.js.map +0 -1
package/dist/services/index.js
DELETED
|
@@ -1,735 +0,0 @@
|
|
|
1
|
-
import { faker } from '@faker-js/faker';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import dotenv from 'dotenv';
|
|
4
|
-
import admin from 'firebase-admin';
|
|
5
|
-
|
|
6
|
-
// src/services/MockDataService.ts
|
|
7
|
-
dotenv.config();
|
|
8
|
-
var envSchema = z.object({
|
|
9
|
-
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
10
|
-
PORT: z.string().default("3030").transform((val) => parseInt(val, 10)),
|
|
11
|
-
CORS_ORIGIN: z.string().default("http://localhost:5173").transform((val) => val.includes(",") ? val.split(",").map((s) => s.trim()) : val),
|
|
12
|
-
// Database (Prisma/SQL) - optional
|
|
13
|
-
DATABASE_URL: z.string().optional(),
|
|
14
|
-
// Firebase/Firestore configuration
|
|
15
|
-
FIREBASE_PROJECT_ID: z.string().optional(),
|
|
16
|
-
FIREBASE_CLIENT_EMAIL: z.string().optional(),
|
|
17
|
-
FIREBASE_PRIVATE_KEY: z.string().optional(),
|
|
18
|
-
FIREBASE_SERVICE_ACCOUNT_PATH: z.string().optional(),
|
|
19
|
-
FIRESTORE_EMULATOR_HOST: z.string().optional(),
|
|
20
|
-
FIREBASE_AUTH_EMULATOR_HOST: z.string().optional(),
|
|
21
|
-
// API configuration
|
|
22
|
-
API_PREFIX: z.string().default("/api"),
|
|
23
|
-
// Mock data configuration
|
|
24
|
-
USE_MOCK_DATA: z.string().default("true").transform((v) => v === "true"),
|
|
25
|
-
MOCK_SEED: z.string().optional().transform((v) => v ? parseInt(v, 10) : void 0)
|
|
26
|
-
});
|
|
27
|
-
var parsed = envSchema.safeParse(process.env);
|
|
28
|
-
if (!parsed.success) {
|
|
29
|
-
console.error("\u274C Invalid environment variables:", parsed.error.flatten().fieldErrors);
|
|
30
|
-
throw new Error("Invalid environment variables");
|
|
31
|
-
}
|
|
32
|
-
var env = parsed.data;
|
|
33
|
-
|
|
34
|
-
// src/lib/logger.ts
|
|
35
|
-
var colors = {
|
|
36
|
-
debug: "\x1B[36m",
|
|
37
|
-
// Cyan
|
|
38
|
-
info: "\x1B[32m",
|
|
39
|
-
// Green
|
|
40
|
-
warn: "\x1B[33m",
|
|
41
|
-
// Yellow
|
|
42
|
-
error: "\x1B[31m",
|
|
43
|
-
// Red
|
|
44
|
-
reset: "\x1B[0m"
|
|
45
|
-
};
|
|
46
|
-
var shouldLog = (level) => {
|
|
47
|
-
const levels = ["debug", "info", "warn", "error"];
|
|
48
|
-
const minLevel = env.NODE_ENV === "production" ? "info" : "debug";
|
|
49
|
-
return levels.indexOf(level) >= levels.indexOf(minLevel);
|
|
50
|
-
};
|
|
51
|
-
var formatMessage = (level, message, meta) => {
|
|
52
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
53
|
-
const color = colors[level];
|
|
54
|
-
const prefix = `${color}[${level.toUpperCase()}]${colors.reset}`;
|
|
55
|
-
const metaStr = meta ? ` ${JSON.stringify(meta)}` : "";
|
|
56
|
-
return `${timestamp} ${prefix} ${message}${metaStr}`;
|
|
57
|
-
};
|
|
58
|
-
var logger = {
|
|
59
|
-
debug: (message, meta) => {
|
|
60
|
-
if (shouldLog("debug")) {
|
|
61
|
-
console.log(formatMessage("debug", message, meta));
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
info: (message, meta) => {
|
|
65
|
-
if (shouldLog("info")) {
|
|
66
|
-
console.log(formatMessage("info", message, meta));
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
warn: (message, meta) => {
|
|
70
|
-
if (shouldLog("warn")) {
|
|
71
|
-
console.warn(formatMessage("warn", message, meta));
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
error: (message, meta) => {
|
|
75
|
-
if (shouldLog("error")) {
|
|
76
|
-
console.error(formatMessage("error", message, meta));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// src/services/MockDataService.ts
|
|
82
|
-
var MockDataService = class {
|
|
83
|
-
stores = /* @__PURE__ */ new Map();
|
|
84
|
-
schemas = /* @__PURE__ */ new Map();
|
|
85
|
-
idCounters = /* @__PURE__ */ new Map();
|
|
86
|
-
constructor() {
|
|
87
|
-
if (env.MOCK_SEED !== void 0) {
|
|
88
|
-
faker.seed(env.MOCK_SEED);
|
|
89
|
-
logger.info(`[Mock] Using seed: ${env.MOCK_SEED}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// ============================================================================
|
|
93
|
-
// Store Management
|
|
94
|
-
// ============================================================================
|
|
95
|
-
/**
|
|
96
|
-
* Initialize store for an entity.
|
|
97
|
-
*/
|
|
98
|
-
getStore(entityName) {
|
|
99
|
-
const normalized = entityName.toLowerCase();
|
|
100
|
-
if (!this.stores.has(normalized)) {
|
|
101
|
-
this.stores.set(normalized, /* @__PURE__ */ new Map());
|
|
102
|
-
this.idCounters.set(normalized, 0);
|
|
103
|
-
}
|
|
104
|
-
return this.stores.get(normalized);
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Generate next ID for an entity.
|
|
108
|
-
*/
|
|
109
|
-
nextId(entityName) {
|
|
110
|
-
const normalized = entityName.toLowerCase();
|
|
111
|
-
const counter = (this.idCounters.get(normalized) ?? 0) + 1;
|
|
112
|
-
this.idCounters.set(normalized, counter);
|
|
113
|
-
return `mock-${normalized}-${counter}`;
|
|
114
|
-
}
|
|
115
|
-
// ============================================================================
|
|
116
|
-
// Schema & Seeding
|
|
117
|
-
// ============================================================================
|
|
118
|
-
/**
|
|
119
|
-
* Register an entity schema.
|
|
120
|
-
*/
|
|
121
|
-
registerSchema(entityName, schema) {
|
|
122
|
-
this.schemas.set(entityName.toLowerCase(), schema);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Seed an entity with mock data.
|
|
126
|
-
*/
|
|
127
|
-
seed(entityName, fields, count = 10) {
|
|
128
|
-
const store = this.getStore(entityName);
|
|
129
|
-
const normalized = entityName.toLowerCase();
|
|
130
|
-
logger.info(`[Mock] Seeding ${count} ${entityName}...`);
|
|
131
|
-
for (let i = 0; i < count; i++) {
|
|
132
|
-
const item = this.generateMockItem(normalized, fields, i + 1);
|
|
133
|
-
store.set(item.id, item);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Generate a single mock item based on field schemas.
|
|
138
|
-
*/
|
|
139
|
-
generateMockItem(entityName, fields, index) {
|
|
140
|
-
const id = this.nextId(entityName);
|
|
141
|
-
const now = /* @__PURE__ */ new Date();
|
|
142
|
-
const item = {
|
|
143
|
-
id,
|
|
144
|
-
createdAt: faker.date.past({ years: 1 }),
|
|
145
|
-
updatedAt: now
|
|
146
|
-
};
|
|
147
|
-
for (const field of fields) {
|
|
148
|
-
if (field.name === "id" || field.name === "createdAt" || field.name === "updatedAt") {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
item[field.name] = this.generateFieldValue(entityName, field, index);
|
|
152
|
-
}
|
|
153
|
-
return item;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Generate a mock value for a field based on its schema.
|
|
157
|
-
*/
|
|
158
|
-
generateFieldValue(entityName, field, index) {
|
|
159
|
-
if (!field.required && Math.random() > 0.8) {
|
|
160
|
-
return void 0;
|
|
161
|
-
}
|
|
162
|
-
switch (field.type) {
|
|
163
|
-
case "string":
|
|
164
|
-
return this.generateStringValue(entityName, field, index);
|
|
165
|
-
case "number":
|
|
166
|
-
return faker.number.int({
|
|
167
|
-
min: field.min ?? 0,
|
|
168
|
-
max: field.max ?? 1e3
|
|
169
|
-
});
|
|
170
|
-
case "boolean":
|
|
171
|
-
return faker.datatype.boolean();
|
|
172
|
-
case "date":
|
|
173
|
-
return this.generateDateValue(field);
|
|
174
|
-
case "enum":
|
|
175
|
-
if (field.enumValues && field.enumValues.length > 0) {
|
|
176
|
-
return faker.helpers.arrayElement(field.enumValues);
|
|
177
|
-
}
|
|
178
|
-
return null;
|
|
179
|
-
case "relation":
|
|
180
|
-
if (field.relatedEntity) {
|
|
181
|
-
const relatedStore = this.stores.get(field.relatedEntity.toLowerCase());
|
|
182
|
-
if (relatedStore && relatedStore.size > 0) {
|
|
183
|
-
const ids = Array.from(relatedStore.keys());
|
|
184
|
-
return faker.helpers.arrayElement(ids);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return null;
|
|
188
|
-
case "array":
|
|
189
|
-
return [];
|
|
190
|
-
default:
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Generate a string value based on field name heuristics.
|
|
196
|
-
* Generic name/title fields use a clean readable format (e.g., "Title 1").
|
|
197
|
-
* Specific fields (email, phone, etc.) use faker.
|
|
198
|
-
*/
|
|
199
|
-
generateStringValue(_entityName, field, index) {
|
|
200
|
-
const name = field.name.toLowerCase();
|
|
201
|
-
if (field.enumValues && field.enumValues.length > 0) {
|
|
202
|
-
return faker.helpers.arrayElement(field.enumValues);
|
|
203
|
-
}
|
|
204
|
-
if (name.includes("email")) return faker.internet.email();
|
|
205
|
-
if (name === "name" || name === "fullname" || name === "full_name") return faker.person.fullName();
|
|
206
|
-
if (name === "firstname" || name === "first_name") return faker.person.firstName();
|
|
207
|
-
if (name === "lastname" || name === "last_name") return faker.person.lastName();
|
|
208
|
-
if (name.includes("username") || name === "handle") return faker.internet.username();
|
|
209
|
-
if (name.includes("phone") || name.includes("mobile") || name.includes("tel")) return faker.phone.number();
|
|
210
|
-
if (name.includes("address") || name.includes("street")) return faker.location.streetAddress();
|
|
211
|
-
if (name.includes("city")) return faker.location.city();
|
|
212
|
-
if (name.includes("state") || name.includes("province")) return faker.location.state();
|
|
213
|
-
if (name.includes("country")) return faker.location.country();
|
|
214
|
-
if (name.includes("zip") || name.includes("postal")) return faker.location.zipCode();
|
|
215
|
-
if (name === "title" || name === "headline" || name === "subject") return faker.lorem.sentence({ min: 3, max: 7 }).replace(/\.$/, "");
|
|
216
|
-
if (name === "description" || name === "summary" || name === "bio" || name === "about") return faker.lorem.paragraph(2);
|
|
217
|
-
if (name === "content" || name === "body" || name === "text") return faker.lorem.paragraphs(2);
|
|
218
|
-
if (name === "excerpt" || name === "snippet" || name === "preview") return faker.lorem.sentence({ min: 8, max: 15 });
|
|
219
|
-
if (name === "label" || name === "tag" || name === "category") return faker.word.noun();
|
|
220
|
-
if (name === "note" || name === "comment" || name === "message" || name === "feedback") return faker.lorem.sentence();
|
|
221
|
-
if (name === "status") return faker.helpers.arrayElement(["active", "pending", "completed", "draft", "archived"]);
|
|
222
|
-
if (name === "priority") return faker.helpers.arrayElement(["low", "medium", "high", "critical"]);
|
|
223
|
-
if (name === "type" || name === "kind") return faker.helpers.arrayElement(["standard", "premium", "basic", "custom"]);
|
|
224
|
-
if (name === "role") return faker.helpers.arrayElement(["admin", "editor", "viewer", "member"]);
|
|
225
|
-
if (name === "level" || name === "tier") return faker.helpers.arrayElement(["beginner", "intermediate", "advanced", "expert"]);
|
|
226
|
-
if (name === "severity") return faker.helpers.arrayElement(["info", "warning", "error", "critical"]);
|
|
227
|
-
if (name === "difficulty") return faker.helpers.arrayElement(["easy", "medium", "hard"]);
|
|
228
|
-
if (name.includes("url") || name.includes("website") || name.includes("link")) return faker.internet.url();
|
|
229
|
-
if (name.includes("avatar") || name.includes("image") || name.includes("photo") || name.includes("thumbnail")) return faker.image.avatar();
|
|
230
|
-
if (name.includes("color") || name.includes("colour")) return faker.color.human();
|
|
231
|
-
if (name.includes("uuid") || name === "guid") return faker.string.uuid();
|
|
232
|
-
if (name.includes("icon")) return faker.helpers.arrayElement(["star", "heart", "check", "alert-circle", "info", "folder", "file", "user"]);
|
|
233
|
-
if (name === "slug") return faker.helpers.slugify(faker.lorem.words(3));
|
|
234
|
-
if (name === "company" || name === "organization" || name === "org") return faker.company.name();
|
|
235
|
-
if (name === "department") return faker.commerce.department();
|
|
236
|
-
if (name === "product" || name === "productname" || name === "product_name") return faker.commerce.productName();
|
|
237
|
-
if (name === "brand") return faker.company.name();
|
|
238
|
-
if (name === "sku" || name === "code") return faker.string.alphanumeric(8).toUpperCase();
|
|
239
|
-
if (name === "currency") return faker.finance.currencyCode();
|
|
240
|
-
if (name.includes("price") || name.includes("cost") || name.includes("amount")) return faker.commerce.price();
|
|
241
|
-
if (name === "latitude" || name === "lat") return String(faker.location.latitude());
|
|
242
|
-
if (name === "longitude" || name === "lng" || name === "lon") return String(faker.location.longitude());
|
|
243
|
-
if (name === "location" || name === "place" || name === "venue") return `${faker.location.city()}, ${faker.location.country()}`;
|
|
244
|
-
if (name === "region" || name === "zone" || name === "area") return faker.location.state();
|
|
245
|
-
if (name === "ip" || name.includes("ipaddress") || name === "ip_address") return faker.internet.ip();
|
|
246
|
-
if (name === "useragent" || name === "user_agent") return faker.internet.userAgent();
|
|
247
|
-
if (name === "version" || name === "firmware") return faker.system.semver();
|
|
248
|
-
if (name === "platform" || name === "os") return faker.helpers.arrayElement(["iOS", "Android", "Windows", "macOS", "Linux"]);
|
|
249
|
-
if (name === "browser") return faker.helpers.arrayElement(["Chrome", "Firefox", "Safari", "Edge"]);
|
|
250
|
-
if (name === "unit") return faker.helpers.arrayElement(["kg", "lb", "cm", "m", "L", "mL", "\xB0C", "\xB0F", "psi", "rpm"]);
|
|
251
|
-
if (name === "metric") return faker.helpers.arrayElement(["temperature", "pressure", "humidity", "speed", "voltage"]);
|
|
252
|
-
if (name === "operator") return faker.helpers.arrayElement(["gt", "lt", "eq", "gte", "lte"]);
|
|
253
|
-
if (name === "format" || name === "mimetype" || name === "mime_type") return faker.system.mimeType();
|
|
254
|
-
if (name === "extension" || name === "ext") return faker.system.fileExt();
|
|
255
|
-
if (name === "filename" || name === "file_name") return faker.system.fileName();
|
|
256
|
-
if (name.endsWith("id") || name.endsWith("_id")) return faker.string.alphanumeric(8).toUpperCase();
|
|
257
|
-
if (name.endsWith("name") || name.endsWith("_name")) return faker.person.fullName();
|
|
258
|
-
if (name.endsWith("type") || name.endsWith("_type")) return faker.helpers.arrayElement(["standard", "premium", "basic", "custom", "special"]);
|
|
259
|
-
if (name.endsWith("date") || name.endsWith("_date") || name.endsWith("at")) return faker.date.recent({ days: 90 }).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" });
|
|
260
|
-
if (name.endsWith("count") || name.endsWith("_count")) return String(faker.number.int({ min: 1, max: 100 }));
|
|
261
|
-
if (name.includes("reason") || name.includes("detail")) return faker.lorem.sentence({ min: 4, max: 8 }).replace(/\.$/, "");
|
|
262
|
-
if (name.includes("field") || name.includes("key") || name.includes("attribute")) return faker.word.noun();
|
|
263
|
-
if (name.includes("value") || name.includes("result") || name.includes("output")) return faker.word.words({ count: { min: 1, max: 3 } });
|
|
264
|
-
if (name.includes("direction") || name.includes("position") || name.includes("mode")) return faker.helpers.arrayElement(["left", "right", "center", "top", "bottom", "auto"]);
|
|
265
|
-
return faker.word.words({ count: { min: 1, max: 3 } });
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Capitalize first letter of a string.
|
|
269
|
-
*/
|
|
270
|
-
capitalizeFirst(str) {
|
|
271
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Generate a date value based on field name heuristics.
|
|
275
|
-
*/
|
|
276
|
-
generateDateValue(field) {
|
|
277
|
-
const name = field.name.toLowerCase();
|
|
278
|
-
if (name.includes("created") || name.includes("start") || name.includes("birth")) {
|
|
279
|
-
return faker.date.past({ years: 2 });
|
|
280
|
-
}
|
|
281
|
-
if (name.includes("updated") || name.includes("modified")) {
|
|
282
|
-
return faker.date.recent({ days: 30 });
|
|
283
|
-
}
|
|
284
|
-
if (name.includes("deadline") || name.includes("due") || name.includes("end") || name.includes("expires")) {
|
|
285
|
-
return faker.date.future({ years: 1 });
|
|
286
|
-
}
|
|
287
|
-
return faker.date.anytime();
|
|
288
|
-
}
|
|
289
|
-
// ============================================================================
|
|
290
|
-
// CRUD Operations
|
|
291
|
-
// ============================================================================
|
|
292
|
-
/**
|
|
293
|
-
* List all items of an entity.
|
|
294
|
-
*/
|
|
295
|
-
list(entityName) {
|
|
296
|
-
const store = this.getStore(entityName);
|
|
297
|
-
return Array.from(store.values());
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Get a single item by ID.
|
|
301
|
-
*/
|
|
302
|
-
getById(entityName, id) {
|
|
303
|
-
const store = this.getStore(entityName);
|
|
304
|
-
const item = store.get(id);
|
|
305
|
-
return item ?? null;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Create a new item.
|
|
309
|
-
*/
|
|
310
|
-
create(entityName, data) {
|
|
311
|
-
const store = this.getStore(entityName);
|
|
312
|
-
const id = this.nextId(entityName);
|
|
313
|
-
const now = /* @__PURE__ */ new Date();
|
|
314
|
-
const item = {
|
|
315
|
-
...data,
|
|
316
|
-
id,
|
|
317
|
-
createdAt: now,
|
|
318
|
-
updatedAt: now
|
|
319
|
-
};
|
|
320
|
-
store.set(id, item);
|
|
321
|
-
return item;
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Update an existing item.
|
|
325
|
-
*/
|
|
326
|
-
update(entityName, id, data) {
|
|
327
|
-
const store = this.getStore(entityName);
|
|
328
|
-
const existing = store.get(id);
|
|
329
|
-
if (!existing) {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
const updated = {
|
|
333
|
-
...existing,
|
|
334
|
-
...data,
|
|
335
|
-
id,
|
|
336
|
-
// Preserve original ID
|
|
337
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
338
|
-
};
|
|
339
|
-
store.set(id, updated);
|
|
340
|
-
return updated;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Delete an item.
|
|
344
|
-
*/
|
|
345
|
-
delete(entityName, id) {
|
|
346
|
-
const store = this.getStore(entityName);
|
|
347
|
-
if (!store.has(id)) {
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
store.delete(id);
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
// ============================================================================
|
|
354
|
-
// Utilities
|
|
355
|
-
// ============================================================================
|
|
356
|
-
/**
|
|
357
|
-
* Clear all data for an entity.
|
|
358
|
-
*/
|
|
359
|
-
clear(entityName) {
|
|
360
|
-
const normalized = entityName.toLowerCase();
|
|
361
|
-
this.stores.delete(normalized);
|
|
362
|
-
this.idCounters.delete(normalized);
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Clear all data.
|
|
366
|
-
*/
|
|
367
|
-
clearAll() {
|
|
368
|
-
this.stores.clear();
|
|
369
|
-
this.idCounters.clear();
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Get count of items for an entity.
|
|
373
|
-
*/
|
|
374
|
-
count(entityName) {
|
|
375
|
-
const store = this.getStore(entityName);
|
|
376
|
-
return store.size;
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
var _mockDataService = null;
|
|
380
|
-
function getMockDataService() {
|
|
381
|
-
if (!_mockDataService) {
|
|
382
|
-
_mockDataService = new MockDataService();
|
|
383
|
-
}
|
|
384
|
-
return _mockDataService;
|
|
385
|
-
}
|
|
386
|
-
function resetMockDataService() {
|
|
387
|
-
_mockDataService?.clearAll();
|
|
388
|
-
_mockDataService = null;
|
|
389
|
-
}
|
|
390
|
-
function getApp() {
|
|
391
|
-
if (admin.apps.length === 0) {
|
|
392
|
-
throw new Error(
|
|
393
|
-
"@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
return admin.app();
|
|
397
|
-
}
|
|
398
|
-
function getFirestore() {
|
|
399
|
-
return getApp().firestore();
|
|
400
|
-
}
|
|
401
|
-
var db = new Proxy({}, {
|
|
402
|
-
get(_target, prop, receiver) {
|
|
403
|
-
const firestore = getFirestore();
|
|
404
|
-
const value = Reflect.get(firestore, prop, receiver);
|
|
405
|
-
return typeof value === "function" ? value.bind(firestore) : value;
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
// src/utils/queryFilters.ts
|
|
410
|
-
function applyFiltersToQuery(collection, filters) {
|
|
411
|
-
let query = collection;
|
|
412
|
-
for (const filter of filters) {
|
|
413
|
-
query = query.where(
|
|
414
|
-
filter.field,
|
|
415
|
-
filter.operator,
|
|
416
|
-
filter.value
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
return query;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// src/services/DataService.ts
|
|
423
|
-
function applyFilterCondition(value, operator, filterValue) {
|
|
424
|
-
if (value === null || value === void 0) {
|
|
425
|
-
return operator === "!=" ? filterValue !== null : false;
|
|
426
|
-
}
|
|
427
|
-
switch (operator) {
|
|
428
|
-
case "==":
|
|
429
|
-
return value === filterValue;
|
|
430
|
-
case "!=":
|
|
431
|
-
return value !== filterValue;
|
|
432
|
-
case ">":
|
|
433
|
-
return value > filterValue;
|
|
434
|
-
case ">=":
|
|
435
|
-
return value >= filterValue;
|
|
436
|
-
case "<":
|
|
437
|
-
return value < filterValue;
|
|
438
|
-
case "<=":
|
|
439
|
-
return value <= filterValue;
|
|
440
|
-
case "array-contains":
|
|
441
|
-
return Array.isArray(value) && value.includes(filterValue);
|
|
442
|
-
case "array-contains-any":
|
|
443
|
-
return Array.isArray(value) && Array.isArray(filterValue) && filterValue.some((v) => value.includes(v));
|
|
444
|
-
case "in":
|
|
445
|
-
return Array.isArray(filterValue) && filterValue.includes(value);
|
|
446
|
-
case "not-in":
|
|
447
|
-
return Array.isArray(filterValue) && !filterValue.includes(value);
|
|
448
|
-
default:
|
|
449
|
-
return true;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
var MockDataServiceAdapter = class {
|
|
453
|
-
async list(collection) {
|
|
454
|
-
return getMockDataService().list(collection);
|
|
455
|
-
}
|
|
456
|
-
async listPaginated(collection, options = {}) {
|
|
457
|
-
const {
|
|
458
|
-
page = 1,
|
|
459
|
-
pageSize = 20,
|
|
460
|
-
search,
|
|
461
|
-
searchFields,
|
|
462
|
-
sortBy,
|
|
463
|
-
sortOrder = "asc",
|
|
464
|
-
filters
|
|
465
|
-
} = options;
|
|
466
|
-
let items = getMockDataService().list(collection);
|
|
467
|
-
if (filters && filters.length > 0) {
|
|
468
|
-
items = items.filter((item) => {
|
|
469
|
-
const record = item;
|
|
470
|
-
return filters.every((filter) => {
|
|
471
|
-
const value = record[filter.field];
|
|
472
|
-
return applyFilterCondition(value, filter.operator, filter.value);
|
|
473
|
-
});
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
if (search && search.trim()) {
|
|
477
|
-
const searchLower = search.toLowerCase();
|
|
478
|
-
items = items.filter((item) => {
|
|
479
|
-
const record = item;
|
|
480
|
-
const fieldsToSearch = searchFields || Object.keys(record);
|
|
481
|
-
return fieldsToSearch.some((field) => {
|
|
482
|
-
const value = record[field];
|
|
483
|
-
if (value === null || value === void 0) return false;
|
|
484
|
-
return String(value).toLowerCase().includes(searchLower);
|
|
485
|
-
});
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
if (sortBy) {
|
|
489
|
-
items = [...items].sort((a, b) => {
|
|
490
|
-
const aVal = a[sortBy];
|
|
491
|
-
const bVal = b[sortBy];
|
|
492
|
-
if (aVal === bVal) return 0;
|
|
493
|
-
if (aVal === null || aVal === void 0) return 1;
|
|
494
|
-
if (bVal === null || bVal === void 0) return -1;
|
|
495
|
-
const comparison = aVal < bVal ? -1 : 1;
|
|
496
|
-
return sortOrder === "asc" ? comparison : -comparison;
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
const total = items.length;
|
|
500
|
-
const totalPages = Math.ceil(total / pageSize);
|
|
501
|
-
const startIndex = (page - 1) * pageSize;
|
|
502
|
-
const data = items.slice(startIndex, startIndex + pageSize);
|
|
503
|
-
return { data, total, page, pageSize, totalPages };
|
|
504
|
-
}
|
|
505
|
-
async getById(collection, id) {
|
|
506
|
-
return getMockDataService().getById(collection, id);
|
|
507
|
-
}
|
|
508
|
-
async create(collection, data) {
|
|
509
|
-
return getMockDataService().create(collection, data);
|
|
510
|
-
}
|
|
511
|
-
async update(collection, id, data) {
|
|
512
|
-
return getMockDataService().update(collection, id, data);
|
|
513
|
-
}
|
|
514
|
-
async delete(collection, id) {
|
|
515
|
-
return getMockDataService().delete(collection, id);
|
|
516
|
-
}
|
|
517
|
-
async query(collection, filters) {
|
|
518
|
-
let items = getMockDataService().list(collection);
|
|
519
|
-
for (const filter of filters) {
|
|
520
|
-
items = items.filter((item) => {
|
|
521
|
-
const value = item[filter.field];
|
|
522
|
-
return applyFilterCondition(value, filter.op, filter.value);
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
return items;
|
|
526
|
-
}
|
|
527
|
-
getStore(collection) {
|
|
528
|
-
const adapter = this;
|
|
529
|
-
return {
|
|
530
|
-
async getById(id) {
|
|
531
|
-
return adapter.getById(collection, id);
|
|
532
|
-
},
|
|
533
|
-
async create(data) {
|
|
534
|
-
return adapter.create(collection, data);
|
|
535
|
-
},
|
|
536
|
-
async update(id, data) {
|
|
537
|
-
const result = await adapter.update(collection, id, data);
|
|
538
|
-
if (!result) throw new Error(`Entity ${id} not found in ${collection}`);
|
|
539
|
-
return result;
|
|
540
|
-
},
|
|
541
|
-
async delete(id) {
|
|
542
|
-
adapter.delete(collection, id);
|
|
543
|
-
},
|
|
544
|
-
async query(filters) {
|
|
545
|
-
return adapter.query(collection, filters);
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
};
|
|
550
|
-
var FirebaseDataService = class {
|
|
551
|
-
async list(collection) {
|
|
552
|
-
const snapshot = await db.collection(collection).get();
|
|
553
|
-
return snapshot.docs.map((doc) => ({
|
|
554
|
-
id: doc.id,
|
|
555
|
-
...doc.data()
|
|
556
|
-
}));
|
|
557
|
-
}
|
|
558
|
-
async listPaginated(collection, options = {}) {
|
|
559
|
-
const {
|
|
560
|
-
page = 1,
|
|
561
|
-
pageSize = 20,
|
|
562
|
-
search,
|
|
563
|
-
searchFields,
|
|
564
|
-
sortBy,
|
|
565
|
-
sortOrder = "asc",
|
|
566
|
-
filters
|
|
567
|
-
} = options;
|
|
568
|
-
let query = db.collection(collection);
|
|
569
|
-
if (filters && filters.length > 0) {
|
|
570
|
-
query = applyFiltersToQuery(query, filters);
|
|
571
|
-
}
|
|
572
|
-
if (sortBy && !search) {
|
|
573
|
-
query = query.orderBy(sortBy, sortOrder);
|
|
574
|
-
}
|
|
575
|
-
const snapshot = await query.get();
|
|
576
|
-
let items = snapshot.docs.map((doc) => ({
|
|
577
|
-
id: doc.id,
|
|
578
|
-
...doc.data()
|
|
579
|
-
}));
|
|
580
|
-
if (search && search.trim()) {
|
|
581
|
-
const searchLower = search.toLowerCase();
|
|
582
|
-
items = items.filter((item) => {
|
|
583
|
-
const record = item;
|
|
584
|
-
const fieldsToSearch = searchFields || Object.keys(record);
|
|
585
|
-
return fieldsToSearch.some((field) => {
|
|
586
|
-
const value = record[field];
|
|
587
|
-
if (value === null || value === void 0) return false;
|
|
588
|
-
return String(value).toLowerCase().includes(searchLower);
|
|
589
|
-
});
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
if (sortBy && search) {
|
|
593
|
-
items = [...items].sort((a, b) => {
|
|
594
|
-
const aVal = a[sortBy];
|
|
595
|
-
const bVal = b[sortBy];
|
|
596
|
-
if (aVal === bVal) return 0;
|
|
597
|
-
if (aVal === null || aVal === void 0) return 1;
|
|
598
|
-
if (bVal === null || bVal === void 0) return -1;
|
|
599
|
-
const comparison = aVal < bVal ? -1 : 1;
|
|
600
|
-
return sortOrder === "asc" ? comparison : -comparison;
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
const total = items.length;
|
|
604
|
-
const totalPages = Math.ceil(total / pageSize);
|
|
605
|
-
const startIndex = (page - 1) * pageSize;
|
|
606
|
-
const data = items.slice(startIndex, startIndex + pageSize);
|
|
607
|
-
return { data, total, page, pageSize, totalPages };
|
|
608
|
-
}
|
|
609
|
-
async getById(collection, id) {
|
|
610
|
-
const doc = await db.collection(collection).doc(id).get();
|
|
611
|
-
if (!doc.exists) {
|
|
612
|
-
return null;
|
|
613
|
-
}
|
|
614
|
-
return { id: doc.id, ...doc.data() };
|
|
615
|
-
}
|
|
616
|
-
async create(collection, data) {
|
|
617
|
-
const now = /* @__PURE__ */ new Date();
|
|
618
|
-
const docRef = await db.collection(collection).add({
|
|
619
|
-
...data,
|
|
620
|
-
createdAt: now,
|
|
621
|
-
updatedAt: now
|
|
622
|
-
});
|
|
623
|
-
return {
|
|
624
|
-
...data,
|
|
625
|
-
id: docRef.id,
|
|
626
|
-
createdAt: now,
|
|
627
|
-
updatedAt: now
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
async update(collection, id, data) {
|
|
631
|
-
const docRef = db.collection(collection).doc(id);
|
|
632
|
-
const doc = await docRef.get();
|
|
633
|
-
if (!doc.exists) {
|
|
634
|
-
return null;
|
|
635
|
-
}
|
|
636
|
-
const now = /* @__PURE__ */ new Date();
|
|
637
|
-
await docRef.update({
|
|
638
|
-
...data,
|
|
639
|
-
updatedAt: now
|
|
640
|
-
});
|
|
641
|
-
return {
|
|
642
|
-
...doc.data(),
|
|
643
|
-
...data,
|
|
644
|
-
id,
|
|
645
|
-
updatedAt: now
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
async delete(collection, id) {
|
|
649
|
-
const docRef = db.collection(collection).doc(id);
|
|
650
|
-
const doc = await docRef.get();
|
|
651
|
-
if (!doc.exists) {
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
await docRef.delete();
|
|
655
|
-
return true;
|
|
656
|
-
}
|
|
657
|
-
async query(collection, filters) {
|
|
658
|
-
let query = db.collection(collection);
|
|
659
|
-
const memoryFilters = [];
|
|
660
|
-
for (const filter of filters) {
|
|
661
|
-
if (["==", "!=", "<", "<=", ">", ">=", "in", "not-in"].includes(filter.op)) {
|
|
662
|
-
query = query.where(filter.field, filter.op, filter.value);
|
|
663
|
-
} else {
|
|
664
|
-
memoryFilters.push(filter);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
const snapshot = await query.get();
|
|
668
|
-
let items = snapshot.docs.map((doc) => ({
|
|
669
|
-
id: doc.id,
|
|
670
|
-
...doc.data()
|
|
671
|
-
}));
|
|
672
|
-
for (const filter of memoryFilters) {
|
|
673
|
-
items = items.filter((item) => {
|
|
674
|
-
const value = item[filter.field];
|
|
675
|
-
return applyFilterCondition(value, filter.op, filter.value);
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
return items;
|
|
679
|
-
}
|
|
680
|
-
getStore(collection) {
|
|
681
|
-
const svc = this;
|
|
682
|
-
return {
|
|
683
|
-
async getById(id) {
|
|
684
|
-
return svc.getById(collection, id);
|
|
685
|
-
},
|
|
686
|
-
async create(data) {
|
|
687
|
-
return svc.create(collection, data);
|
|
688
|
-
},
|
|
689
|
-
async update(id, data) {
|
|
690
|
-
const result = await svc.update(collection, id, data);
|
|
691
|
-
if (!result) throw new Error(`Entity ${id} not found in ${collection}`);
|
|
692
|
-
return result;
|
|
693
|
-
},
|
|
694
|
-
async delete(id) {
|
|
695
|
-
await svc.delete(collection, id);
|
|
696
|
-
},
|
|
697
|
-
async query(filters) {
|
|
698
|
-
return svc.query(collection, filters);
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
function createDataService() {
|
|
704
|
-
if (env.USE_MOCK_DATA) {
|
|
705
|
-
logger.info("[DataService] Using MockDataService");
|
|
706
|
-
return new MockDataServiceAdapter();
|
|
707
|
-
}
|
|
708
|
-
logger.info("[DataService] Using FirebaseDataService");
|
|
709
|
-
return new FirebaseDataService();
|
|
710
|
-
}
|
|
711
|
-
var _dataService = null;
|
|
712
|
-
function getDataService() {
|
|
713
|
-
if (!_dataService) {
|
|
714
|
-
_dataService = createDataService();
|
|
715
|
-
}
|
|
716
|
-
return _dataService;
|
|
717
|
-
}
|
|
718
|
-
function resetDataService() {
|
|
719
|
-
_dataService = null;
|
|
720
|
-
}
|
|
721
|
-
function seedMockData(entities) {
|
|
722
|
-
if (!env.USE_MOCK_DATA) {
|
|
723
|
-
logger.info("[DataService] Mock mode disabled, skipping seed");
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
logger.info("[DataService] Seeding mock data...");
|
|
727
|
-
for (const entity of entities) {
|
|
728
|
-
getMockDataService().seed(entity.name, entity.fields, entity.seedCount);
|
|
729
|
-
}
|
|
730
|
-
logger.info("[DataService] Mock data seeding complete");
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
export { MockDataService, getDataService, getMockDataService, resetDataService, resetMockDataService, seedMockData };
|
|
734
|
-
//# sourceMappingURL=index.js.map
|
|
735
|
-
//# sourceMappingURL=index.js.map
|