@kyro-cms/core 0.6.0 → 0.7.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/dist/api-handler.cjs +75 -35
- package/dist/api-handler.cjs.map +1 -1
- package/dist/api-handler.d.cts +2 -5
- package/dist/api-handler.d.ts +2 -5
- package/dist/api-handler.js +75 -36
- package/dist/api-handler.js.map +1 -1
- package/dist/bootstrap-AKAUP6F6.cjs +32 -0
- package/dist/{bootstrap-EE6BJZWL.cjs.map → bootstrap-AKAUP6F6.cjs.map} +1 -1
- package/dist/bootstrap-JCML6NFO.js +7 -0
- package/dist/{bootstrap-4MH44YKG.js.map → bootstrap-JCML6NFO.js.map} +1 -1
- package/dist/{chunk-WVPOPOEQ.cjs → chunk-2KVHZE6O.cjs} +286 -126
- package/dist/chunk-2KVHZE6O.cjs.map +1 -0
- package/dist/{chunk-RALQO47U.cjs → chunk-2OL4O2TH.cjs} +55 -2
- package/dist/chunk-2OL4O2TH.cjs.map +1 -0
- package/dist/{chunk-XU7AFF6V.js → chunk-35U3FROB.js} +982 -4
- package/dist/chunk-35U3FROB.js.map +1 -0
- package/dist/{chunk-WSCJQI2B.js → chunk-3J4MFTI3.js} +27 -11
- package/dist/chunk-3J4MFTI3.js.map +1 -0
- package/dist/chunk-3ZFYL34R.js +391 -0
- package/dist/chunk-3ZFYL34R.js.map +1 -0
- package/dist/chunk-4DA7QPLA.cjs +356 -0
- package/dist/chunk-4DA7QPLA.cjs.map +1 -0
- package/dist/{chunk-TP5YQFIX.js → chunk-57P6MJKC.js} +3 -715
- package/dist/chunk-57P6MJKC.js.map +1 -0
- package/dist/{chunk-R2YHJN6W.cjs → chunk-5KVM3WEY.cjs} +34 -208
- package/dist/chunk-5KVM3WEY.cjs.map +1 -0
- package/dist/{chunk-Z2OVHWHB.cjs → chunk-6IMPH6WV.cjs} +28 -11
- package/dist/chunk-6IMPH6WV.cjs.map +1 -0
- package/dist/{chunk-QKVA2SOG.js → chunk-DXHRBMGB.js} +27 -284
- package/dist/chunk-DXHRBMGB.js.map +1 -0
- package/dist/{chunk-E3BZLMX6.js → chunk-ES5HNFFT.js} +43 -2
- package/dist/chunk-ES5HNFFT.js.map +1 -0
- package/dist/{chunk-QYZKIPSD.js → chunk-FXYP2HA6.js} +34 -3
- package/dist/chunk-FXYP2HA6.js.map +1 -0
- package/dist/chunk-H727JIG7.js +809 -0
- package/dist/chunk-H727JIG7.js.map +1 -0
- package/dist/{chunk-AM4JKIPP.js → chunk-HXRD4B37.js} +9 -183
- package/dist/chunk-HXRD4B37.js.map +1 -0
- package/dist/chunk-I7HHI6QV.cjs +816 -0
- package/dist/chunk-I7HHI6QV.cjs.map +1 -0
- package/dist/{chunk-RDRJVCL5.cjs → chunk-IA6AU5PI.cjs} +2 -720
- package/dist/chunk-IA6AU5PI.cjs.map +1 -0
- package/dist/{chunk-55BNRTLW.cjs → chunk-LINKCEG4.cjs} +985 -4
- package/dist/chunk-LINKCEG4.cjs.map +1 -0
- package/dist/{chunk-TVVYZ2TH.js → chunk-OHVB4AJ7.js} +56 -3
- package/dist/chunk-OHVB4AJ7.js.map +1 -0
- package/dist/{chunk-XAEBVZTI.cjs → chunk-PDYFVNUX.cjs} +26 -289
- package/dist/chunk-PDYFVNUX.cjs.map +1 -0
- package/dist/{chunk-6WXQRYTW.js → chunk-QPPDLRNR.js} +286 -126
- package/dist/chunk-QPPDLRNR.js.map +1 -0
- package/dist/{chunk-WBCIEYHC.cjs → chunk-QUW2RZTM.cjs} +35 -4
- package/dist/chunk-QUW2RZTM.cjs.map +1 -0
- package/dist/chunk-SA7NSSIQ.cjs +397 -0
- package/dist/chunk-SA7NSSIQ.cjs.map +1 -0
- package/dist/{chunk-H4XCAPA6.cjs → chunk-V3LKPM3O.cjs} +43 -2
- package/dist/chunk-V3LKPM3O.cjs.map +1 -0
- package/dist/chunk-Y3N7UUDO.js +349 -0
- package/dist/chunk-Y3N7UUDO.js.map +1 -0
- package/dist/{chunk-S3FG2NY7.js → chunk-Y3QQN7PN.js} +4 -3
- package/dist/chunk-Y3QQN7PN.js.map +1 -0
- package/dist/{chunk-5HA5OMFH.cjs → chunk-YVUJBEXE.cjs} +7 -6
- package/dist/chunk-YVUJBEXE.cjs.map +1 -0
- package/dist/cli/index.cjs +103 -20
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +103 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/drizzle/index.cjs +12 -12
- package/dist/drizzle/index.d.cts +23 -2
- package/dist/drizzle/index.d.ts +23 -2
- package/dist/drizzle/index.js +3 -3
- package/dist/index.cjs +174 -1054
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -7
- package/dist/index.d.ts +85 -7
- package/dist/index.js +91 -980
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +2 -2
- package/dist/integration.d.cts +3 -16
- package/dist/integration.d.ts +3 -16
- package/dist/integration.js +1 -1
- package/dist/mongo-auth-adapter-NHHUJHVH.cjs +17 -0
- package/dist/mongo-auth-adapter-NHHUJHVH.cjs.map +1 -0
- package/dist/mongo-auth-adapter-NJQUUCTP.js +4 -0
- package/dist/mongo-auth-adapter-NJQUUCTP.js.map +1 -0
- package/dist/mongodb/index.cjs +9 -8
- package/dist/mongodb/index.d.cts +86 -5
- package/dist/mongodb/index.d.ts +86 -5
- package/dist/mongodb/index.js +3 -2
- package/dist/postgres-auth-adapter-3T2NKTSE.js +5 -0
- package/dist/{postgres-auth-adapter-B65BULNS.js.map → postgres-auth-adapter-3T2NKTSE.js.map} +1 -1
- package/dist/postgres-auth-adapter-7IEENCKQ.cjs +14 -0
- package/dist/{postgres-auth-adapter-6742WDCF.cjs.map → postgres-auth-adapter-7IEENCKQ.cjs.map} +1 -1
- package/dist/redis-adapter-D2E2S3GB.cjs +13 -0
- package/dist/{redis-adapter-LPUWLE4Y.cjs.map → redis-adapter-D2E2S3GB.cjs.map} +1 -1
- package/dist/redis-adapter-VQXD7ESY.js +4 -0
- package/dist/{redis-adapter-THYDCGQR.js.map → redis-adapter-VQXD7ESY.js.map} +1 -1
- package/dist/rest/index.cjs +10 -8
- package/dist/rest/index.js +8 -6
- package/dist/sqlite-adapter-LVK5PS4T.cjs +13 -0
- package/dist/sqlite-adapter-LVK5PS4T.cjs.map +1 -0
- package/dist/sqlite-adapter-TR3U3W6Q.js +4 -0
- package/dist/sqlite-adapter-TR3U3W6Q.js.map +1 -0
- package/dist/templates/index.cjs +31 -27
- package/dist/templates/index.d.cts +8 -5
- package/dist/templates/index.d.ts +8 -5
- package/dist/templates/index.js +1 -1
- package/dist/{base-eVegJ_Pr.d.ts → tenant-B1YB0Jy8.d.ts} +10 -1
- package/dist/{base-DvvNqnM-.d.cts → tenant-Cpeveji6.d.cts} +10 -1
- package/dist/{types-DqN4ckOC.d.cts → types-D6ZLRGbH.d.cts} +19 -1
- package/dist/{types-DqN4ckOC.d.ts → types-D6ZLRGbH.d.ts} +19 -1
- package/package.json +56 -9
- package/dist/adapter-BSvBudTG.d.cts +0 -65
- package/dist/adapter-CXGB2Elb.d.ts +0 -65
- package/dist/bootstrap-4MH44YKG.js +0 -6
- package/dist/bootstrap-EE6BJZWL.cjs +0 -31
- package/dist/chunk-55BNRTLW.cjs.map +0 -1
- package/dist/chunk-5HA5OMFH.cjs.map +0 -1
- package/dist/chunk-6WXQRYTW.js.map +0 -1
- package/dist/chunk-A4USRVTQ.js +0 -115
- package/dist/chunk-A4USRVTQ.js.map +0 -1
- package/dist/chunk-AM4JKIPP.js.map +0 -1
- package/dist/chunk-E3BZLMX6.js.map +0 -1
- package/dist/chunk-H4XCAPA6.cjs.map +0 -1
- package/dist/chunk-KOCTZKPV.cjs +0 -117
- package/dist/chunk-KOCTZKPV.cjs.map +0 -1
- package/dist/chunk-QKVA2SOG.js.map +0 -1
- package/dist/chunk-QYZKIPSD.js.map +0 -1
- package/dist/chunk-R2YHJN6W.cjs.map +0 -1
- package/dist/chunk-RALQO47U.cjs.map +0 -1
- package/dist/chunk-RDRJVCL5.cjs.map +0 -1
- package/dist/chunk-S3FG2NY7.js.map +0 -1
- package/dist/chunk-TP5YQFIX.js.map +0 -1
- package/dist/chunk-TVVYZ2TH.js.map +0 -1
- package/dist/chunk-WBCIEYHC.cjs.map +0 -1
- package/dist/chunk-WSCJQI2B.js.map +0 -1
- package/dist/chunk-WVPOPOEQ.cjs.map +0 -1
- package/dist/chunk-XAEBVZTI.cjs.map +0 -1
- package/dist/chunk-XU7AFF6V.js.map +0 -1
- package/dist/chunk-Z2OVHWHB.cjs.map +0 -1
- package/dist/postgres-auth-adapter-6742WDCF.cjs +0 -14
- package/dist/postgres-auth-adapter-B65BULNS.js +0 -5
- package/dist/redis-adapter-LPUWLE4Y.cjs +0 -13
- package/dist/redis-adapter-THYDCGQR.js +0 -4
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { AbstractBaseAdapter } from './chunk-
|
|
2
|
-
import { randomBytes
|
|
3
|
-
import bcrypt from 'bcryptjs';
|
|
1
|
+
import { AbstractBaseAdapter, applyRLS, DEFAULT_RLS_CONFIG, canAccessDocument } from './chunk-3ZFYL34R.js';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
4
3
|
|
|
5
4
|
var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
6
5
|
client;
|
|
@@ -8,6 +7,13 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
|
8
7
|
database;
|
|
9
8
|
connectionString;
|
|
10
9
|
draftsCollectionName = "kyro_drafts";
|
|
10
|
+
tenantContext;
|
|
11
|
+
setTenantContext(context) {
|
|
12
|
+
this.tenantContext = context;
|
|
13
|
+
}
|
|
14
|
+
getTenantContext() {
|
|
15
|
+
return this.tenantContext;
|
|
16
|
+
}
|
|
11
17
|
constructor(options) {
|
|
12
18
|
super();
|
|
13
19
|
if (options.connectionString) {
|
|
@@ -50,7 +56,12 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
|
50
56
|
const { collection: slug, where = {}, sort, limit = 10, page = 1, tenantID, select, draft } = args;
|
|
51
57
|
const config = this.getCollectionConfig(slug);
|
|
52
58
|
const col = this.getMongoCollection(slug);
|
|
53
|
-
|
|
59
|
+
let effectiveWhere = { ...where };
|
|
60
|
+
if (this.tenantContext && config.tenantScoped) {
|
|
61
|
+
const rlsQuery = applyRLS({ where: effectiveWhere }, slug, this.tenantContext, DEFAULT_RLS_CONFIG);
|
|
62
|
+
effectiveWhere = rlsQuery.where || {};
|
|
63
|
+
}
|
|
64
|
+
const filter = this.buildFilter(effectiveWhere, tenantID);
|
|
54
65
|
if (!draft) {
|
|
55
66
|
filter._status = "published";
|
|
56
67
|
}
|
|
@@ -64,6 +75,9 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
|
64
75
|
col.countDocuments(filter)
|
|
65
76
|
]);
|
|
66
77
|
let processedDocs = docs.map((doc) => this.processResult(doc, config));
|
|
78
|
+
if (this.tenantContext && !this.tenantContext.isSuperAdmin) {
|
|
79
|
+
processedDocs = processedDocs.filter((doc) => canAccessDocument(doc, slug, this.tenantContext, DEFAULT_RLS_CONFIG));
|
|
80
|
+
}
|
|
67
81
|
if (draft) {
|
|
68
82
|
processedDocs = await Promise.all(processedDocs.map(async (doc) => {
|
|
69
83
|
if (doc._has_draft) {
|
|
@@ -89,6 +103,12 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
|
89
103
|
const { collection: slug, id, tenantID, draft } = args;
|
|
90
104
|
const config = this.getCollectionConfig(slug);
|
|
91
105
|
const col = this.getMongoCollection(slug);
|
|
106
|
+
if (this.tenantContext && config.tenantScoped) {
|
|
107
|
+
const tempDoc = { _id: id, tenantId: this.tenantContext.tenantId };
|
|
108
|
+
if (!canAccessDocument(tempDoc, slug, this.tenantContext, DEFAULT_RLS_CONFIG)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
92
112
|
const filter = { _id: id };
|
|
93
113
|
if (tenantID) {
|
|
94
114
|
filter.tenantId = tenantID;
|
|
@@ -444,284 +464,7 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
|
|
|
444
464
|
function createMongoDBAdapter(options) {
|
|
445
465
|
return new MongoDBAdapter(options);
|
|
446
466
|
}
|
|
447
|
-
var MongoDBAuthAdapter = class {
|
|
448
|
-
db;
|
|
449
|
-
prefix;
|
|
450
|
-
sessionTTL;
|
|
451
|
-
refreshTokenTTL;
|
|
452
|
-
indexesEnsured = false;
|
|
453
|
-
constructor(options) {
|
|
454
|
-
this.db = options.db;
|
|
455
|
-
this.prefix = options.collectionPrefix || "";
|
|
456
|
-
this.sessionTTL = options.sessionTTL || 86400;
|
|
457
|
-
this.refreshTokenTTL = options.refreshTokenTTL || 604800;
|
|
458
|
-
}
|
|
459
|
-
col(name) {
|
|
460
|
-
return this.db.collection(`${this.prefix}${name}`);
|
|
461
|
-
}
|
|
462
|
-
async connect() {
|
|
463
|
-
if (!this.indexesEnsured) {
|
|
464
|
-
await this.ensureIndexes();
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
async disconnect() {
|
|
468
|
-
}
|
|
469
|
-
async ensureIndexes() {
|
|
470
|
-
await this.col("users").createIndex({ email: 1 }, { unique: true });
|
|
471
|
-
await this.col("users").createIndex({ tenantId: 1 });
|
|
472
|
-
await this.col("users").createIndex({ role: 1 });
|
|
473
|
-
await this.col("sessions").createIndex({ token: 1 }, { unique: true });
|
|
474
|
-
await this.col("sessions").createIndex({ refreshToken: 1 });
|
|
475
|
-
await this.col("sessions").createIndex({ userId: 1 });
|
|
476
|
-
await this.col("sessions").createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
477
|
-
await this.col("audit_logs").createIndex({ timestamp: -1 });
|
|
478
|
-
await this.col("audit_logs").createIndex({ userId: 1 });
|
|
479
|
-
await this.col("audit_logs").createIndex({ action: 1 });
|
|
480
|
-
await this.col("audit_logs").createIndex({ resource: 1 });
|
|
481
|
-
await this.col("password_history").createIndex({ userId: 1, createdAt: -1 });
|
|
482
|
-
await this.col("lockouts").createIndex({ userId: 1 }, { unique: true });
|
|
483
|
-
await this.col("lockouts").createIndex({ lockedUntil: 1 });
|
|
484
|
-
this.indexesEnsured = true;
|
|
485
|
-
}
|
|
486
|
-
async createUser(data) {
|
|
487
|
-
const id = randomUUID();
|
|
488
|
-
const now = /* @__PURE__ */ new Date();
|
|
489
|
-
const passwordHash = await this.hashPassword(data.password);
|
|
490
|
-
const user = {
|
|
491
|
-
_id: id,
|
|
492
|
-
name: data.name || null,
|
|
493
|
-
email: data.email.toLowerCase(),
|
|
494
|
-
passwordHash,
|
|
495
|
-
role: data.role || "customer",
|
|
496
|
-
tenantId: data.tenantId || null,
|
|
497
|
-
emailVerified: false,
|
|
498
|
-
locked: false,
|
|
499
|
-
lastLogin: null,
|
|
500
|
-
failedLoginAttempts: 0,
|
|
501
|
-
createdAt: now,
|
|
502
|
-
updatedAt: now
|
|
503
|
-
};
|
|
504
|
-
await this.col("users").insertOne(user);
|
|
505
|
-
return this.docToAuthUser(user);
|
|
506
|
-
}
|
|
507
|
-
async findUserByEmail(email) {
|
|
508
|
-
const doc = await this.col("users").findOne({ email: email.toLowerCase() });
|
|
509
|
-
return doc ? this.docToAuthUser(doc) : null;
|
|
510
|
-
}
|
|
511
|
-
async findUserById(id) {
|
|
512
|
-
const doc = await this.col("users").findOne({ _id: id });
|
|
513
|
-
return doc ? this.docToAuthUser(doc) : null;
|
|
514
|
-
}
|
|
515
|
-
async updateUser(id, data) {
|
|
516
|
-
const setData = { updatedAt: /* @__PURE__ */ new Date() };
|
|
517
|
-
if (data.name !== void 0) setData.name = data.name;
|
|
518
|
-
if (data.email !== void 0) setData.email = data.email;
|
|
519
|
-
if (data.passwordHash !== void 0) setData.passwordHash = data.passwordHash;
|
|
520
|
-
if (data.role !== void 0) setData.role = data.role;
|
|
521
|
-
if (data.tenantId !== void 0) setData.tenantId = data.tenantId;
|
|
522
|
-
if (data.emailVerified !== void 0) setData.emailVerified = data.emailVerified;
|
|
523
|
-
if (data.locked !== void 0) setData.locked = data.locked;
|
|
524
|
-
if (data.lastLogin !== void 0) setData.lastLogin = data.lastLogin ? new Date(data.lastLogin) : null;
|
|
525
|
-
if (data.failedLoginAttempts !== void 0) setData.failedLoginAttempts = data.failedLoginAttempts;
|
|
526
|
-
const result = await this.col("users").findOneAndUpdate(
|
|
527
|
-
{ _id: id },
|
|
528
|
-
{ $set: setData },
|
|
529
|
-
{ returnDocument: "after" }
|
|
530
|
-
);
|
|
531
|
-
return result ? this.docToAuthUser(result) : null;
|
|
532
|
-
}
|
|
533
|
-
async deleteUser(id) {
|
|
534
|
-
const result = await this.col("users").deleteOne({ _id: id });
|
|
535
|
-
return result.deletedCount > 0;
|
|
536
|
-
}
|
|
537
|
-
async verifyPassword(email, password) {
|
|
538
|
-
const user = await this.findUserByEmail(email);
|
|
539
|
-
if (!user) return null;
|
|
540
|
-
const doc = await this.col("users").findOne(
|
|
541
|
-
{ email: email.toLowerCase() },
|
|
542
|
-
{ projection: { passwordHash: 1 } }
|
|
543
|
-
);
|
|
544
|
-
if (!doc?.passwordHash) return null;
|
|
545
|
-
const valid = await bcrypt.compare(password, doc.passwordHash);
|
|
546
|
-
return valid ? user : null;
|
|
547
|
-
}
|
|
548
|
-
async hashPassword(password) {
|
|
549
|
-
return bcrypt.hash(password, 12);
|
|
550
|
-
}
|
|
551
|
-
async createSession(userId, data) {
|
|
552
|
-
const id = randomUUID();
|
|
553
|
-
const token = randomBytes(32).toString("base64url");
|
|
554
|
-
const refreshToken = randomBytes(32).toString("base64url");
|
|
555
|
-
const now = /* @__PURE__ */ new Date();
|
|
556
|
-
const expiresAt = new Date(now.getTime() + this.sessionTTL * 1e3);
|
|
557
|
-
const session = {
|
|
558
|
-
_id: id,
|
|
559
|
-
userId,
|
|
560
|
-
token,
|
|
561
|
-
refreshToken,
|
|
562
|
-
ipAddress: data?.ipAddress || null,
|
|
563
|
-
userAgent: data?.userAgent || null,
|
|
564
|
-
expiresAt,
|
|
565
|
-
createdAt: now
|
|
566
|
-
};
|
|
567
|
-
await this.col("sessions").insertOne(session);
|
|
568
|
-
return this.docToSession(session);
|
|
569
|
-
}
|
|
570
|
-
async findSessionByToken(token) {
|
|
571
|
-
const doc = await this.col("sessions").findOne({
|
|
572
|
-
token,
|
|
573
|
-
expiresAt: { $gt: /* @__PURE__ */ new Date() }
|
|
574
|
-
});
|
|
575
|
-
return doc ? this.docToSession(doc) : null;
|
|
576
|
-
}
|
|
577
|
-
async findSessionByRefreshToken(refreshToken) {
|
|
578
|
-
const doc = await this.col("sessions").findOne({
|
|
579
|
-
refreshToken,
|
|
580
|
-
expiresAt: { $gt: /* @__PURE__ */ new Date() }
|
|
581
|
-
});
|
|
582
|
-
return doc ? this.docToSession(doc) : null;
|
|
583
|
-
}
|
|
584
|
-
async deleteSession(sessionId) {
|
|
585
|
-
const result = await this.col("sessions").deleteOne({ _id: sessionId });
|
|
586
|
-
return result.deletedCount > 0;
|
|
587
|
-
}
|
|
588
|
-
async deleteUserSessions(userId) {
|
|
589
|
-
const result = await this.col("sessions").deleteMany({ userId });
|
|
590
|
-
return result.deletedCount;
|
|
591
|
-
}
|
|
592
|
-
async hasAnyUsers() {
|
|
593
|
-
const count = await this.col("users").countDocuments();
|
|
594
|
-
return count > 0;
|
|
595
|
-
}
|
|
596
|
-
async addPasswordToHistory(userId, passwordHash) {
|
|
597
|
-
await this.col("password_history").insertOne({
|
|
598
|
-
userId,
|
|
599
|
-
passwordHash,
|
|
600
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
async getPasswordHistory(userId, count = 5) {
|
|
604
|
-
const docs = await this.col("password_history").find({ userId }).sort({ createdAt: -1 }).limit(count).toArray();
|
|
605
|
-
return docs.map((d) => d.passwordHash);
|
|
606
|
-
}
|
|
607
|
-
async isPasswordInHistory(password, userId, historyCount = 5) {
|
|
608
|
-
const history = await this.getPasswordHistory(userId, historyCount);
|
|
609
|
-
for (const hash of history) {
|
|
610
|
-
if (await bcrypt.compare(password, hash)) {
|
|
611
|
-
return true;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
return false;
|
|
615
|
-
}
|
|
616
|
-
async findAuditLogs(filter) {
|
|
617
|
-
const {
|
|
618
|
-
limit = 50,
|
|
619
|
-
offset = 0,
|
|
620
|
-
userId,
|
|
621
|
-
action,
|
|
622
|
-
resource,
|
|
623
|
-
resourceId,
|
|
624
|
-
success,
|
|
625
|
-
startDate,
|
|
626
|
-
endDate
|
|
627
|
-
} = filter;
|
|
628
|
-
const query = {};
|
|
629
|
-
if (userId) query.userId = userId;
|
|
630
|
-
if (action) {
|
|
631
|
-
if (Array.isArray(action)) {
|
|
632
|
-
query.action = { $in: action };
|
|
633
|
-
} else {
|
|
634
|
-
query.action = action;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
if (resource) query.resource = resource;
|
|
638
|
-
if (resourceId) query.resourceId = resourceId;
|
|
639
|
-
if (success !== void 0) query.success = success;
|
|
640
|
-
if (startDate || endDate) {
|
|
641
|
-
query.timestamp = {};
|
|
642
|
-
if (startDate) query.timestamp.$gte = startDate;
|
|
643
|
-
if (endDate) query.timestamp.$lte = endDate;
|
|
644
|
-
}
|
|
645
|
-
const total = await this.col("audit_logs").countDocuments(query);
|
|
646
|
-
const docs = await this.col("audit_logs").find(query).sort({ timestamp: -1 }).skip(offset).limit(limit).toArray();
|
|
647
|
-
return {
|
|
648
|
-
logs: docs.map((doc) => ({
|
|
649
|
-
id: doc._id,
|
|
650
|
-
timestamp: doc.timestamp,
|
|
651
|
-
action: doc.action,
|
|
652
|
-
userId: doc.userId || void 0,
|
|
653
|
-
userEmail: doc.userEmail || void 0,
|
|
654
|
-
role: doc.role || void 0,
|
|
655
|
-
resource: doc.resource,
|
|
656
|
-
resourceId: doc.resourceId || void 0,
|
|
657
|
-
changes: doc.changes || void 0,
|
|
658
|
-
ipAddress: doc.ipAddress || void 0,
|
|
659
|
-
userAgent: doc.userAgent || void 0,
|
|
660
|
-
success: doc.success,
|
|
661
|
-
error: doc.error || void 0,
|
|
662
|
-
metadata: doc.metadata || void 0
|
|
663
|
-
})),
|
|
664
|
-
total
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
async createAuditLog(data) {
|
|
668
|
-
const id = randomUUID();
|
|
669
|
-
const timestamp = /* @__PURE__ */ new Date();
|
|
670
|
-
await this.col("audit_logs").insertOne({
|
|
671
|
-
_id: id,
|
|
672
|
-
action: data.action,
|
|
673
|
-
userId: data.userId || null,
|
|
674
|
-
userEmail: data.userEmail || null,
|
|
675
|
-
role: data.role || null,
|
|
676
|
-
resource: data.resource,
|
|
677
|
-
resourceId: data.resourceId || null,
|
|
678
|
-
changes: data.changes || null,
|
|
679
|
-
ipAddress: data.ipAddress || null,
|
|
680
|
-
userAgent: data.userAgent || null,
|
|
681
|
-
success: data.success,
|
|
682
|
-
error: data.error || null,
|
|
683
|
-
metadata: data.metadata || null,
|
|
684
|
-
timestamp
|
|
685
|
-
});
|
|
686
|
-
return {
|
|
687
|
-
...data,
|
|
688
|
-
id,
|
|
689
|
-
timestamp
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
docToAuthUser(doc) {
|
|
693
|
-
return {
|
|
694
|
-
id: doc._id,
|
|
695
|
-
name: doc.name || void 0,
|
|
696
|
-
email: doc.email,
|
|
697
|
-
passwordHash: doc.passwordHash || void 0,
|
|
698
|
-
role: doc.role,
|
|
699
|
-
tenantId: doc.tenantId || void 0,
|
|
700
|
-
emailVerified: doc.emailVerified || false,
|
|
701
|
-
locked: doc.locked || false,
|
|
702
|
-
lastLogin: doc.lastLogin?.toISOString?.() || doc.lastLogin || void 0,
|
|
703
|
-
failedLoginAttempts: doc.failedLoginAttempts || 0,
|
|
704
|
-
createdAt: doc.createdAt?.toISOString?.() || doc.createdAt,
|
|
705
|
-
updatedAt: doc.updatedAt?.toISOString?.() || doc.updatedAt
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
docToSession(doc) {
|
|
709
|
-
return {
|
|
710
|
-
id: doc._id,
|
|
711
|
-
userId: doc.userId,
|
|
712
|
-
token: doc.token,
|
|
713
|
-
refreshToken: doc.refreshToken || void 0,
|
|
714
|
-
expiresAt: doc.expiresAt?.toISOString?.() || doc.expiresAt,
|
|
715
|
-
createdAt: doc.createdAt?.toISOString?.() || doc.createdAt,
|
|
716
|
-
ipAddress: doc.ipAddress || void 0,
|
|
717
|
-
userAgent: doc.userAgent || void 0
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
function createMongoDBAuthAdapter(options) {
|
|
722
|
-
return new MongoDBAuthAdapter(options);
|
|
723
|
-
}
|
|
724
467
|
|
|
725
|
-
export { MongoDBAdapter,
|
|
726
|
-
//# sourceMappingURL=chunk-
|
|
727
|
-
//# sourceMappingURL=chunk-
|
|
468
|
+
export { MongoDBAdapter, createMongoDBAdapter };
|
|
469
|
+
//# sourceMappingURL=chunk-DXHRBMGB.js.map
|
|
470
|
+
//# sourceMappingURL=chunk-DXHRBMGB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/database/mongodb/adapter.ts"],"names":[],"mappings":"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","file":"chunk-DXHRBMGB.js","sourcesContent":["import { randomBytes } from 'crypto';\nimport { AbstractBaseAdapter } from '../base.js';\nimport type {\n CollectionConfig,\n GlobalConfig,\n FindArgs,\n FindByIDArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n FindResult,\n DraftFindArgs,\n DraftUpsertArgs,\n DraftDeleteArgs,\n DraftSnapshot,\n VersionRecord,\n CreateVersionArgs,\n FindVersionsArgs,\n} from '../../registry/types.js';\nimport type { TenantContext } from '../../auth/rls/tenant.js';\nimport { applyRLS, DEFAULT_RLS_CONFIG, canAccessDocument } from '../../auth/rls/tenant.js';\n\nexport class MongoDBAdapter extends AbstractBaseAdapter {\n public client: any;\n public db: any;\n private database: string;\n private connectionString?: string;\n private readonly draftsCollectionName = 'kyro_drafts';\n private tenantContext?: TenantContext;\n \n setTenantContext(context: TenantContext | undefined): void {\n this.tenantContext = context;\n }\n \n getTenantContext(): TenantContext | undefined {\n return this.tenantContext;\n }\n \n constructor(options: {\n client?: any;\n database?: string;\n connectionString?: string;\n }) {\n super();\n if (options.connectionString) {\n this.connectionString = options.connectionString;\n try {\n const url = new URL(options.connectionString);\n this.database = url.pathname.replace(/^\\//, '') || 'kyro_cms';\n } catch {\n this.database = 'kyro_cms';\n }\n } else {\n this.client = options.client;\n this.database = options.database!;\n }\n }\n\n async connect(): Promise<void> {\n if (this.connectionString && !this.client) {\n const { MongoClient } = await import('mongodb');\n this.client = new MongoClient(this.connectionString);\n await this.client.connect();\n }\n this.db = this.client.db(this.database);\n this.connected = true;\n console.log(`[MongoDBAdapter] Connected to database: ${this.database}`);\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.connected = false;\n console.log(`[MongoDBAdapter] Disconnected`);\n }\n }\n\n private getMongoCollection(slug: string): any {\n if (!this.db) {\n throw new Error('MongoDB not connected');\n }\n return this.db.collection(slug);\n }\n\n async find<T>(args: FindArgs): Promise<FindResult<T>> {\n const { collection: slug, where = {}, sort, limit = 10, page = 1, tenantID, select, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n let effectiveWhere = { ...where };\n if (this.tenantContext && config.tenantScoped) {\n const rlsQuery = applyRLS({ where: effectiveWhere }, slug, this.tenantContext, DEFAULT_RLS_CONFIG);\n effectiveWhere = rlsQuery.where || {};\n }\n\n // Build filter\n const filter = this.buildFilter(effectiveWhere, tenantID);\n \n // Default filter for non-draft requests: only show published\n if (!draft) {\n filter._status = 'published';\n }\n\n // Build sort\n const sortOption = this.parseSort(sort);\n const sortObj: Record<string, 1 | -1> = {\n [sortOption.field]: sortOption.direction === 'asc' ? 1 : -1,\n };\n\n // Execute query\n const skip = (page - 1) * limit;\n \n const [docs, totalDocs] = await Promise.all([\n col\n .find(filter)\n .sort(sortObj)\n .skip(skip)\n .limit(limit)\n .project(this.buildProjection(select))\n .toArray(),\n col.countDocuments(filter),\n ]);\n\n // Process results\n let processedDocs = docs.map((doc: any) => this.processResult(doc, config));\n\n if (this.tenantContext && !this.tenantContext.isSuperAdmin) {\n processedDocs = processedDocs.filter((doc: any) => canAccessDocument(doc, slug, this.tenantContext!, DEFAULT_RLS_CONFIG));\n }\n\n // If draft: true, we need to check if any docs have a separate draft version\n if (draft) {\n processedDocs = await Promise.all(processedDocs.map(async (doc: any) => {\n if (doc._has_draft) {\n const versions = await this.findVersions({\n collection: slug,\n documentId: doc.id,\n limit: 1,\n sort: '-createdAt'\n });\n if (versions.docs.length > 0 && versions.docs[0].status === 'draft') {\n return { ...doc, ...versions.docs[0].data, _has_draft: true, _status: doc._status };\n }\n }\n return doc;\n }));\n }\n\n return {\n docs: processedDocs as T[],\n ...this.calculatePagination(page, limit, totalDocs),\n };\n }\n\n async findByID<T>(args: FindByIDArgs): Promise<T | null> {\n const { collection: slug, id, tenantID, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n if (this.tenantContext && config.tenantScoped) {\n const tempDoc = { _id: id, tenantId: this.tenantContext.tenantId };\n if (!canAccessDocument(tempDoc, slug, this.tenantContext, DEFAULT_RLS_CONFIG)) {\n return null;\n }\n }\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n \n if (!draft) {\n filter._status = 'published';\n }\n\n const doc = await col.findOne(filter);\n if (!doc) return null;\n\n let processedDoc = this.processResult(doc, config);\n\n // If draft: true and doc has a separate draft, merge it\n if (draft && processedDoc._has_draft) {\n const versions = await this.findVersions({\n collection: slug,\n documentId: processedDoc.id,\n limit: 1,\n sort: '-createdAt'\n });\n if (versions.docs.length > 0 && versions.docs[0].status === 'draft') {\n processedDoc = { ...processedDoc, ...versions.docs[0].data, _has_draft: true, _status: processedDoc._status };\n }\n }\n\n return processedDoc as T;\n }\n\n async create<T>(args: CreateArgs): Promise<T> {\n const { collection: slug, data, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const doc: any = {\n ...this.prepareData(data, config),\n _id: this.generateId(),\n };\n\n if (tenantID) {\n doc.tenantId = tenantID;\n }\n\n await col.insertOne(doc);\n\n return this.processResult(doc, config) as T;\n }\n\n async update<T>(args: UpdateArgs): Promise<T> {\n const { collection: slug, id, data, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n const updateData = this.prepareData(data, config);\n\n const result = await col.findOneAndUpdate(\n filter,\n { $set: updateData },\n { returnDocument: 'after' }\n );\n\n if (!result) {\n throw new Error(`Document not found: ${slug}/${id}`);\n }\n\n return this.processResult(result, config) as T;\n }\n\n async delete<T>(args: DeleteArgs): Promise<T> {\n const { collection: slug, id, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n const doc = await col.findOneAndDelete(filter);\n if (!doc) {\n throw new Error(`Document not found: ${slug}/${id}`);\n }\n\n return this.processResult(doc, config) as T;\n }\n\n async count(args: { collection: string; where?: Record<string, any>; tenantID?: string }): Promise<number> {\n const { collection: slug, where = {}, tenantID } = args;\n const col = this.getMongoCollection(slug);\n const filter = this.buildFilter(where, tenantID);\n return col.countDocuments(filter);\n }\n\n async findOne(args: { collection: string; where: Record<string, any>; tenantID?: string; draft?: boolean }): Promise<any> {\n const { collection: slug, where = {}, tenantID, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n const filter = this.buildFilter(where, tenantID);\n\n if (!draft) {\n filter._status = 'published';\n }\n\n const doc = await col.findOne(filter);\n if (!doc) return null;\n\n let processedDoc = this.processResult(doc, config);\n\n // If draft: true and doc has a separate draft, merge it\n if (draft && processedDoc._has_draft) {\n const versions = await this.findVersions({\n collection: slug,\n documentId: processedDoc.id,\n limit: 1,\n sort: '-createdAt'\n });\n if (versions.docs.length > 0 && versions.docs[0].status === 'draft') {\n processedDoc = { ...processedDoc, ...versions.docs[0].data, _has_draft: true, _status: processedDoc._status };\n }\n }\n\n return processedDoc;\n }\n\n async findVersions(args: FindVersionsArgs): Promise<FindResult<VersionRecord>> {\n const { collection: slug, documentId, sort, limit = 10, page = 1, tenantID } = args;\n \n // Versions stored in a separate collection\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const filter: any = { document_id: documentId };\n if (tenantID) filter.tenant_id = tenantID;\n\n const skip = (page - 1) * limit;\n const sortOption = this.parseSort(sort);\n const sortObj: Record<string, 1 | -1> = {\n [sortOption.field]: sortOption.direction === 'asc' ? 1 : -1,\n };\n\n const [docs, totalDocs] = await Promise.all([\n versionCollection.find(filter).sort(sortObj).skip(skip).limit(limit).toArray(),\n versionCollection.countDocuments(filter),\n ]);\n\n return {\n docs: docs.map((doc: any) => this.processResult(doc, {} as CollectionConfig) as VersionRecord),\n ...this.calculatePagination(page, limit, totalDocs),\n };\n }\n\n async findVersionByID(args: { collection: string; versionId: string; tenantID?: string }): Promise<VersionRecord | null> {\n const { collection: slug, versionId, tenantID } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const filter: any = { _id: versionId };\n if (tenantID) filter.tenant_id = tenantID;\n \n const doc = await versionCollection.findOne(filter);\n return doc ? this.processResult(doc, {} as CollectionConfig) as VersionRecord : null;\n }\n\n async createVersion<T = Record<string, any>>(args: CreateVersionArgs<T>): Promise<VersionRecord<T>> {\n const { collection: slug, documentId, data, status, createdBy, changeDescription, tenantID } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n\n const versionDoc: any = {\n _id: this.generateId(),\n document_id: documentId,\n collection_slug: slug,\n tenant_id: tenantID,\n data,\n status,\n created_by: createdBy,\n change_description: changeDescription,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n await versionCollection.insertOne(versionDoc);\n \n // Pruning logic\n const config = this.getCollectionConfig(slug);\n if (config.versions?.maxPerDoc) {\n await this.deleteVersions({\n collection: slug,\n documentId: documentId,\n keepLatest: config.versions.maxPerDoc,\n tenantID: tenantID,\n });\n }\n\n return this.processResult(versionDoc, {} as CollectionConfig) as VersionRecord<T>;\n }\n\n async deleteVersions(args: { collection: string; documentId: string; keepLatest?: number; tenantID?: string }): Promise<void> {\n const { collection: slug, documentId, keepLatest, tenantID } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n \n if (keepLatest) {\n const filter: any = { document_id: documentId };\n if (tenantID) filter.tenant_id = tenantID;\n\n const toKeep = await versionCollection\n .find(filter)\n .sort({ createdAt: -1 })\n .limit(keepLatest)\n .project({ _id: 1 })\n .toArray();\n\n const keepIds = toKeep.map((doc: any) => doc._id);\n if (keepIds.length > 0) {\n await versionCollection.deleteMany({\n document_id: documentId,\n _id: { $nin: keepIds },\n ...(tenantID ? { tenant_id: tenantID } : {}),\n });\n }\n } else {\n const filter: any = { document_id: documentId };\n if (tenantID) filter.tenant_id = tenantID;\n await versionCollection.deleteMany(filter);\n }\n }\n\n async findDraft<T>(args: DraftFindArgs): Promise<DraftSnapshot<T> | null> {\n const draft = await this.getMongoCollection(this.draftsCollectionName).findOne({\n _id: this.getDraftId(args.collection, args.documentId, args.tenantID),\n });\n\n return draft ? this.docToDraft<T>(draft) : null;\n }\n\n async upsertDraft<T>(args: DraftUpsertArgs<T>): Promise<DraftSnapshot<T>> {\n const now = new Date().toISOString();\n const draftUpdatedAt = args.draftUpdatedAt || now;\n const _id = this.getDraftId(args.collection, args.documentId, args.tenantID);\n const existing = await this.getMongoCollection(this.draftsCollectionName).findOne({ _id });\n\n await this.getMongoCollection(this.draftsCollectionName).updateOne(\n { _id },\n {\n $set: {\n collectionSlug: args.collection,\n documentId: args.documentId,\n tenantId: args.tenantID,\n data: args.data,\n baseUpdatedAt: args.baseUpdatedAt ?? null,\n draftUpdatedAt,\n updatedAt: now,\n },\n $setOnInsert: {\n createdAt: existing?.createdAt || now,\n },\n },\n { upsert: true },\n );\n\n const saved = await this.getMongoCollection(this.draftsCollectionName).findOne({ _id });\n if (!saved) {\n throw new Error('Failed to persist draft snapshot');\n }\n return this.docToDraft<T>(saved);\n }\n\n async deleteDraft(args: DraftDeleteArgs): Promise<void> {\n await this.getMongoCollection(this.draftsCollectionName).deleteOne({\n _id: this.getDraftId(args.collection, args.documentId, args.tenantID),\n });\n }\n\n async migrate?(): Promise<void> {\n // Create indexes for all collections\n for (const config of this.collections.values()) {\n const col = this.getMongoCollection(config.slug);\n\n // Create default indexes\n await col.createIndex({ _id: 1 });\n \n if (config.tenantScoped) {\n await col.createIndex({ tenantId: 1 });\n }\n\n if (config.timestamps) {\n await col.createIndex({ createdAt: -1 });\n }\n\n // Create unique indexes\n for (const field of config.fields) {\n if (field.unique && field.name) {\n await col.createIndex({ [field.name]: 1 }, { unique: true });\n }\n if (field.indexed && field.name) {\n await col.createIndex({ [field.name]: 1 });\n }\n }\n }\n\n await this.getMongoCollection(this.draftsCollectionName).createIndex({ updatedAt: -1 });\n \n console.log(`[MongoDBAdapter] Migration completed`);\n }\n\n // ========================================================================\n // Helper Methods\n // ========================================================================\n\n private getCollectionConfig(slug: string): CollectionConfig {\n const config = this.collections.get(slug);\n if (!config) {\n throw new Error(`Collection \"${slug}\" not found`);\n }\n return config;\n }\n\n private buildFilter(where: Record<string, any> = {}, tenantID?: string): Record<string, any> {\n const filter: Record<string, any> = {};\n\n // Apply tenant filter\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n // Convert operators to MongoDB format\n for (const [key, value] of Object.entries(where)) {\n if (key === 'AND' && Array.isArray(value)) {\n const andConditions = value.map((v: any) => this.buildFilter(v));\n Object.assign(filter, ...andConditions);\n } else if (key === 'OR' && Array.isArray(value)) {\n filter.$or = value.map((v: any) => this.buildFilter(v));\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Operator-based conditions\n const mongoOperators: Record<string, any> = {};\n \n if (value.equals !== undefined) {\n filter[key === 'id' ? '_id' : key] = value.equals;\n continue;\n }\n if (value.not_equals !== undefined) {\n mongoOperators.$ne = value.not_equals;\n }\n if (value.in !== undefined) {\n mongoOperators.$in = value.in;\n }\n if (value.not_in !== undefined) {\n mongoOperators.$nin = value.not_in;\n }\n if (value.greater_than !== undefined) {\n mongoOperators.$gt = value.greater_than;\n }\n if (value.greater_than_equal !== undefined) {\n mongoOperators.$gte = value.greater_than_equal;\n }\n if (value.less_than !== undefined) {\n mongoOperators.$lt = value.less_than;\n }\n if (value.less_than_equal !== undefined) {\n mongoOperators.$lte = value.less_than_equal;\n }\n if (value.like !== undefined) {\n mongoOperators.$regex = new RegExp(value.like.replace(/%/g, '.*'), 'i');\n }\n if (value.not_like !== undefined) {\n mongoOperators.$not = new RegExp(value.not_like.replace(/%/g, '.*'), 'i');\n }\n if (value.contains !== undefined) {\n mongoOperators.$regex = new RegExp(`.*${value.contains}.*`, 'i');\n }\n if (value.exists !== undefined) {\n mongoOperators.$exists = value.exists;\n }\n\n if (Object.keys(mongoOperators).length > 0) {\n filter[key === 'id' ? '_id' : key] = mongoOperators;\n }\n } else {\n // Direct equality\n filter[key === 'id' ? '_id' : key] = value;\n }\n }\n\n return filter;\n }\n\n private getDraftId(collection: string, documentId: string, tenantID?: string): string {\n return `${collection}::${documentId}::${tenantID || 'global'}`;\n }\n\n private docToDraft<T>(doc: any): DraftSnapshot<T> {\n return {\n id: String(doc._id),\n collection: doc.collectionSlug,\n documentId: doc.documentId,\n tenantID: doc.tenantId ?? undefined,\n data: doc.data || {},\n baseUpdatedAt: doc.baseUpdatedAt ?? null,\n draftUpdatedAt: doc.draftUpdatedAt,\n createdAt: doc.createdAt,\n updatedAt: doc.updatedAt,\n };\n }\n\n private buildProjection(select?: string[]): Record<string, 1> | undefined {\n if (!select || select.length === 0) return undefined;\n \n const projection: Record<string, 1> = { _id: 1 };\n for (const field of select) {\n projection[field] = 1;\n }\n return projection;\n }\n\n private processResult(data: any, config: CollectionConfig): any {\n if (!data) return null;\n\n const result = { ...data };\n\n // Convert _id to id\n if (data._id) {\n result.id = data._id;\n delete result._id;\n }\n\n // Remove MongoDB internals\n delete result.__v;\n\n // Convert dates to ISO strings\n if (result.createdAt) {\n result.createdAt = new Date(result.createdAt).toISOString();\n }\n if (result.updatedAt) {\n result.updatedAt = new Date(result.updatedAt).toISOString();\n }\n\n return result;\n }\n\n private generateId(): string {\n const timestamp = Date.now().toString(16).padStart(12, '0');\n const random = randomBytes(6).toString('hex');\n return timestamp + random;\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\nexport function createMongoDBAdapter(options: {\n client?: any;\n database?: string;\n connectionString?: string;\n}): MongoDBAdapter {\n return new MongoDBAdapter(options);\n}\n"]}
|
|
@@ -265,6 +265,47 @@ var RedisAuthAdapter = class {
|
|
|
265
265
|
userAgent: hash.userAgent
|
|
266
266
|
};
|
|
267
267
|
}
|
|
268
|
+
tokenKey(tokenType, token) {
|
|
269
|
+
return `${this.prefix}tokens:${tokenType}:${token}`;
|
|
270
|
+
}
|
|
271
|
+
async createEmailVerificationToken(userId) {
|
|
272
|
+
const token = randomBytes(32).toString("hex");
|
|
273
|
+
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1e3);
|
|
274
|
+
const redis = await this.getRedis();
|
|
275
|
+
await redis.setex(this.tokenKey("email-verify", token), 86400, userId);
|
|
276
|
+
return { token, expiresAt };
|
|
277
|
+
}
|
|
278
|
+
async verifyEmailToken(token) {
|
|
279
|
+
const redis = await this.getRedis();
|
|
280
|
+
const userId = await redis.get(this.tokenKey("email-verify", token));
|
|
281
|
+
if (!userId) {
|
|
282
|
+
return { success: false, error: "Invalid or expired token" };
|
|
283
|
+
}
|
|
284
|
+
await redis.del(this.tokenKey("email-verify", token));
|
|
285
|
+
return { success: true, userId };
|
|
286
|
+
}
|
|
287
|
+
async createPasswordResetToken(email) {
|
|
288
|
+
const user = await this.findUserByEmail(email);
|
|
289
|
+
if (!user) {
|
|
290
|
+
return { token: "", expiresAt: /* @__PURE__ */ new Date(), error: "User not found" };
|
|
291
|
+
}
|
|
292
|
+
const token = randomBytes(32).toString("hex");
|
|
293
|
+
const expiresAt = new Date(Date.now() + 60 * 60 * 1e3);
|
|
294
|
+
const redis = await this.getRedis();
|
|
295
|
+
await redis.setex(this.tokenKey("password-reset", token), 3600, user.id);
|
|
296
|
+
return { token, expiresAt };
|
|
297
|
+
}
|
|
298
|
+
async resetPasswordWithToken(token, newPassword) {
|
|
299
|
+
const redis = await this.getRedis();
|
|
300
|
+
const userId = await redis.get(this.tokenKey("password-reset", token));
|
|
301
|
+
if (!userId) {
|
|
302
|
+
return { success: false, error: "Invalid or expired token" };
|
|
303
|
+
}
|
|
304
|
+
const passwordHash = await this.hashPassword(newPassword);
|
|
305
|
+
await this.updateUser(userId, { passwordHash });
|
|
306
|
+
await redis.del(this.tokenKey("password-reset", token));
|
|
307
|
+
return { success: true };
|
|
308
|
+
}
|
|
268
309
|
auditLogKey(id) {
|
|
269
310
|
return `${this.prefix}audit:logs:${id}`;
|
|
270
311
|
}
|
|
@@ -308,5 +349,5 @@ var RedisAuthAdapter = class {
|
|
|
308
349
|
};
|
|
309
350
|
|
|
310
351
|
export { RedisAuthAdapter };
|
|
311
|
-
//# sourceMappingURL=chunk-
|
|
312
|
-
//# sourceMappingURL=chunk-
|
|
352
|
+
//# sourceMappingURL=chunk-ES5HNFFT.js.map
|
|
353
|
+
//# sourceMappingURL=chunk-ES5HNFFT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/redis-adapter.ts"],"names":[],"mappings":"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","file":"chunk-ES5HNFFT.js","sourcesContent":["import type { Redis } from \"ioredis\";\nimport type { AuthAdapter, AuthUser, Session, UserRole } from \"./types.js\";\nimport bcrypt from \"bcryptjs\";\nimport { randomBytes } from \"crypto\";\n\nexport interface RedisAuthAdapterOptions {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n db?: number;\n keyPrefix?: string;\n tokenExpiration?: number;\n refreshTokenExpiration?: number;\n tls?: boolean;\n}\n\nconst DEFAULT_PREFIX = \"kyro:auth:\";\nconst DEFAULT_TOKEN_EXPIRATION = 86400;\nconst DEFAULT_REFRESH_EXPIRATION = 604800;\n\nexport class RedisAuthAdapter implements AuthAdapter {\n private _redis: Redis | null = null;\n private prefix: string;\n private tokenExpiration: number;\n private refreshExpiration: number;\n private options: RedisAuthAdapterOptions;\n\n constructor(options: RedisAuthAdapterOptions = {}) {\n this.options = options;\n this.prefix = options.keyPrefix || DEFAULT_PREFIX;\n this.tokenExpiration = options.tokenExpiration || DEFAULT_TOKEN_EXPIRATION;\n this.refreshExpiration =\n options.refreshTokenExpiration || DEFAULT_REFRESH_EXPIRATION;\n }\n\n private async getRedis(): Promise<Redis> {\n if (!this._redis) {\n const { Redis: RedisClass } = await import(\"ioredis\");\n const url =\n this.options.url ||\n `redis://${this.options.host || \"localhost\"}:${this.options.port || 6379}`;\n this._redis = new RedisClass(url, {\n password: this.options.password,\n db: this.options.db,\n lazyConnect: true,\n tls: this.options.tls ? {} : undefined,\n });\n }\n return this._redis;\n }\n\n async connect(): Promise<void> {\n await this.getRedis();\n }\n\n async disconnect(): Promise<void> {\n await (await this.getRedis()).quit();\n }\n\n private userKey(userId: string): string {\n return `${this.prefix}users:${userId}`;\n }\n\n private sessionKey(sessionId: string): string {\n return `${this.prefix}sessions:${sessionId}`;\n }\n\n private refreshKey(token: string): string {\n return `${this.prefix}refresh:${token}`;\n }\n\n private userByEmailKey(email: string): string {\n return `${this.prefix}users:email:${email.toLowerCase()}`;\n }\n\n private passwordHistoryKey(userId: string): string {\n return `${this.prefix}users:${userId}:password_history`;\n }\n\n async createUser(data: {\n email: string;\n password: string;\n role?: UserRole;\n tenantId?: string;\n }): Promise<AuthUser> {\n const userId = randomBytes(16).toString(\"hex\");\n const now = new Date().toISOString();\n const passwordHash = await this.hashPassword(data.password);\n\n const user: AuthUser = {\n id: userId,\n email: data.email.toLowerCase(),\n passwordHash,\n role: (data.role || \"customer\") as UserRole,\n tenantId: data.tenantId,\n createdAt: now,\n updatedAt: now,\n };\n\n const pipeline = (await this.getRedis()).pipeline();\n\n pipeline.hset(this.userKey(userId), this.userToHash(user));\n pipeline.set(this.userByEmailKey(data.email), userId);\n\n await pipeline.exec();\n\n return user;\n }\n\n async findUserByEmail(email: string): Promise<AuthUser | null> {\n const userId = await (\n await this.getRedis()\n ).get(this.userByEmailKey(email.toLowerCase()));\n if (!userId) return null;\n return this.findUserById(userId);\n }\n\n async findUserById(userId: string): Promise<AuthUser | null> {\n const data = await (await this.getRedis()).hgetall(this.userKey(userId));\n if (!data || Object.keys(data).length === 0) return null;\n return this.hashToUser(data);\n }\n\n async updateUser(\n userId: string,\n data: Partial<AuthUser>,\n ): Promise<AuthUser | null> {\n const existing = await this.findUserById(userId);\n if (!existing) return null;\n\n const updated: AuthUser = {\n ...existing,\n ...data,\n id: userId,\n updatedAt: new Date().toISOString(),\n };\n\n if (data.email && data.email !== existing.email) {\n const pipeline = (await this.getRedis()).pipeline();\n pipeline.del(this.userByEmailKey(existing.email));\n pipeline.set(this.userByEmailKey(data.email), userId);\n await pipeline.exec();\n }\n\n await (\n await this.getRedis()\n ).hset(this.userKey(userId), this.userToHash(updated));\n return updated;\n }\n\n async deleteUser(userId: string): Promise<boolean> {\n const user = await this.findUserById(userId);\n if (!user) return false;\n\n const pipeline = (await this.getRedis()).pipeline();\n pipeline.del(this.userKey(userId));\n pipeline.del(this.userByEmailKey(user.email));\n pipeline.del(this.passwordHistoryKey(userId));\n await pipeline.exec();\n\n return true;\n }\n\n async hashPassword(password: string): Promise<string> {\n return bcrypt.hash(password, 12);\n }\n\n async verifyPassword(\n email: string,\n password: string,\n ): Promise<AuthUser | null> {\n const userId = await (\n await this.getRedis()\n ).get(this.userByEmailKey(email));\n if (!userId) return null;\n const user = await this.findUserById(userId);\n if (!user || !user.passwordHash) return null;\n const valid = await bcrypt.compare(password, user.passwordHash);\n return valid ? user : null;\n }\n\n async createSession(\n userId: string,\n data: {\n ipAddress?: string;\n userAgent?: string;\n } = {},\n ): Promise<Session> {\n const sessionId = randomBytes(32).toString(\"hex\");\n const token = randomBytes(32).toString(\"base64url\");\n const refreshToken = randomBytes(32).toString(\"base64url\");\n const now = new Date();\n\n const session: Session = {\n id: sessionId,\n userId,\n token,\n refreshToken,\n expiresAt: new Date(\n now.getTime() + this.tokenExpiration * 1000,\n ).toISOString(),\n createdAt: now.toISOString(),\n ipAddress: data.ipAddress,\n userAgent: data.userAgent,\n };\n\n const pipeline = (await this.getRedis()).pipeline();\n\n pipeline.hset(this.sessionKey(sessionId), this.sessionToHash(session));\n pipeline.setex(\n this.refreshKey(refreshToken),\n this.refreshExpiration,\n sessionId,\n );\n\n await pipeline.exec();\n\n return session;\n }\n\n async findSessionByToken(token: string): Promise<Session | null> {\n const data = await (await this.getRedis()).hgetall(this.sessionKey(token));\n if (!data || Object.keys(data).length === 0) return null;\n return this.hashToSession(data);\n }\n\n async findSessionByRefreshToken(\n refreshToken: string,\n ): Promise<Session | null> {\n const sessionId = await (\n await this.getRedis()\n ).get(this.refreshKey(refreshToken));\n if (!sessionId) return null;\n const data = await (\n await this.getRedis()\n ).hgetall(this.sessionKey(sessionId));\n if (!data || Object.keys(data).length === 0) return null;\n return this.hashToSession(data);\n }\n\n async deleteSession(sessionId: string): Promise<boolean> {\n const session = await (\n await this.getRedis()\n ).hgetall(this.sessionKey(sessionId));\n if (!session || Object.keys(session).length === 0) return false;\n\n const pipeline = (await this.getRedis()).pipeline();\n pipeline.del(this.sessionKey(sessionId));\n if (session.refreshToken) {\n pipeline.del(this.refreshKey(session.refreshToken));\n }\n await pipeline.exec();\n\n return true;\n }\n\n async deleteUserSessions(userId: string): Promise<number> {\n const pattern = `${this.prefix}sessions:*`;\n let cursor = \"0\";\n let deleted = 0;\n\n do {\n const [nextCursor, keys] = await (\n await this.getRedis()\n ).scan(cursor, \"MATCH\", pattern, \"COUNT\", 100);\n cursor = nextCursor;\n\n for (const key of keys) {\n const sessionData = await (await this.getRedis()).hgetall(key);\n if (sessionData.userId === userId) {\n const sessionId = key.replace(`${this.prefix}sessions:`, \"\");\n await this.deleteSession(sessionId);\n deleted++;\n }\n }\n } while (cursor !== \"0\");\n\n return deleted;\n }\n\n async addPasswordToHistory(\n userId: string,\n passwordHash: string,\n ): Promise<void> {\n await (\n await this.getRedis()\n ).lpush(this.passwordHistoryKey(userId), passwordHash);\n await (await this.getRedis()).ltrim(this.passwordHistoryKey(userId), 0, 4);\n }\n\n async getPasswordHistory(\n userId: string,\n count: number = 5,\n ): Promise<string[]> {\n return (await this.getRedis()).lrange(\n this.passwordHistoryKey(userId),\n 0,\n count - 1,\n );\n }\n\n async isPasswordInHistory(\n password: string,\n userId: string,\n historyCount: number = 5,\n ): Promise<boolean> {\n const history = await this.getPasswordHistory(userId, historyCount);\n\n for (const hash of history) {\n if (await bcrypt.compare(password, hash)) {\n return true;\n }\n }\n\n return false;\n }\n\n private userToHash(user: AuthUser): Record<string, string> {\n const hash: Record<string, string> = {\n id: user.id,\n email: user.email,\n passwordHash: user.passwordHash || \"\",\n role: user.role,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt,\n };\n\n if (user.tenantId) hash.tenantId = user.tenantId;\n if (user.emailVerified !== undefined)\n hash.emailVerified = String(user.emailVerified);\n if (user.locked !== undefined) hash.locked = String(user.locked);\n if (user.lastLogin) hash.lastLogin = user.lastLogin;\n if (user.failedLoginAttempts !== undefined)\n hash.failedLoginAttempts = String(user.failedLoginAttempts);\n\n return hash;\n }\n\n private hashToUser(hash: Record<string, string>): AuthUser {\n return {\n id: hash.id,\n email: hash.email,\n passwordHash: hash.passwordHash,\n role: hash.role as UserRole,\n tenantId: hash.tenantId,\n createdAt: hash.createdAt,\n updatedAt: hash.updatedAt,\n emailVerified: hash.emailVerified === \"true\",\n locked: hash.locked === \"true\",\n lastLogin: hash.lastLogin,\n failedLoginAttempts: hash.failedLoginAttempts\n ? parseInt(hash.failedLoginAttempts, 10)\n : 0,\n };\n }\n\n private sessionToHash(session: Session): Record<string, string> {\n const hash: Record<string, string> = {\n id: session.id,\n userId: session.userId,\n token: session.token,\n expiresAt: session.expiresAt,\n createdAt: session.createdAt,\n };\n\n if (session.refreshToken) hash.refreshToken = session.refreshToken;\n if (session.ipAddress) hash.ipAddress = session.ipAddress;\n if (session.userAgent) hash.userAgent = session.userAgent;\n\n return hash;\n }\n\n private hashToSession(hash: Record<string, string>): Session {\n return {\n id: hash.id,\n userId: hash.userId,\n token: hash.token,\n refreshToken: hash.refreshToken,\n expiresAt: hash.expiresAt,\n createdAt: hash.createdAt,\n ipAddress: hash.ipAddress,\n userAgent: hash.userAgent,\n };\n }\n\n private tokenKey(tokenType: string, token: string): string {\n return `${this.prefix}tokens:${tokenType}:${token}`;\n }\n\n async createEmailVerificationToken(userId: string): Promise<{ token: string; expiresAt: Date }> {\n const token = randomBytes(32).toString(\"hex\");\n const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours\n const redis = await this.getRedis();\n await redis.setex(this.tokenKey(\"email-verify\", token), 86400, userId);\n return { token, expiresAt };\n }\n\n async verifyEmailToken(token: string): Promise<{ success: boolean; userId?: string; error?: string }> {\n const redis = await this.getRedis();\n const userId = await redis.get(this.tokenKey(\"email-verify\", token));\n if (!userId) {\n return { success: false, error: \"Invalid or expired token\" };\n }\n await redis.del(this.tokenKey(\"email-verify\", token));\n return { success: true, userId };\n }\n\n async createPasswordResetToken(email: string): Promise<{ token: string; expiresAt: Date; error?: string }> {\n const user = await this.findUserByEmail(email);\n if (!user) {\n return { token: \"\", expiresAt: new Date(), error: \"User not found\" };\n }\n const token = randomBytes(32).toString(\"hex\");\n const expiresAt = new Date(Date.now() + 60 * 60 * 1000); // 1 hour\n const redis = await this.getRedis();\n await redis.setex(this.tokenKey(\"password-reset\", token), 3600, user.id);\n return { token, expiresAt };\n }\n\n async resetPasswordWithToken(token: string, newPassword: string): Promise<{ success: boolean; error?: string }> {\n const redis = await this.getRedis();\n const userId = await redis.get(this.tokenKey(\"password-reset\", token));\n if (!userId) {\n return { success: false, error: \"Invalid or expired token\" };\n }\n const passwordHash = await this.hashPassword(newPassword);\n await this.updateUser(userId, { passwordHash });\n await redis.del(this.tokenKey(\"password-reset\", token));\n return { success: true };\n }\n\n private auditLogKey(id: string): string {\n return `${this.prefix}audit:logs:${id}`;\n }\n\n private auditLogIndexKey(): string {\n return `${this.prefix}audit:index`;\n }\n\n async findAuditLogs(filter: {\n userId?: string;\n action?: string | string[];\n resource?: string;\n success?: boolean;\n limit?: number;\n offset?: number;\n }): Promise<{ logs: any[]; total: number }> {\n const { limit = 50, offset = 0 } = filter;\n const indexKey = this.auditLogIndexKey();\n const allIds = await (await this.getRedis()).zrevrange(indexKey, 0, -1);\n const total = allIds.length;\n\n const pagedIds = allIds.slice(offset, offset + limit);\n const logs: any[] = [];\n\n for (const id of pagedIds) {\n const logData = await (await this.getRedis()).get(this.auditLogKey(id));\n if (logData) {\n const log = JSON.parse(logData);\n if (\n (!filter.userId || log.userId === filter.userId) &&\n (!filter.action ||\n (Array.isArray(filter.action)\n ? filter.action.includes(log.action)\n : log.action === filter.action)) &&\n (!filter.resource || log.resource === filter.resource) &&\n (filter.success === undefined || log.success === filter.success)\n ) {\n logs.push({ ...log, timestamp: new Date(log.timestamp) });\n }\n }\n }\n\n return { logs, total };\n }\n\n async createAuditLog(data: any): Promise<any> {\n const id = randomBytes(16).toString(\"hex\");\n const timestamp = new Date();\n const log = { ...data, id, timestamp };\n await (\n await this.getRedis()\n ).set(this.auditLogKey(id), JSON.stringify(log));\n await (await this.getRedis()).zadd(this.auditLogIndexKey(), Date.now(), id);\n const count = await (await this.getRedis()).zcard(this.auditLogIndexKey());\n if (count > 10000) {\n const oldIds = await (\n await this.getRedis()\n ).zrange(this.auditLogIndexKey(), 0, count - 10001);\n for (const oldId of oldIds) {\n await (await this.getRedis()).del(this.auditLogKey(oldId));\n await (await this.getRedis()).zrem(this.auditLogIndexKey(), oldId);\n }\n }\n return log;\n }\n}\n"]}
|
|
@@ -6,18 +6,32 @@ var API_HANDLER_ENTRYPOINT = path.resolve(
|
|
|
6
6
|
new URL(".", import.meta.url).pathname,
|
|
7
7
|
"api-handler.js"
|
|
8
8
|
);
|
|
9
|
+
var GRAPHQL_HANDLER_ENTRYPOINT = path.resolve(
|
|
10
|
+
new URL(".", import.meta.url).pathname,
|
|
11
|
+
"api-handler-graphql.js"
|
|
12
|
+
);
|
|
13
|
+
var TRPC_HANDLER_ENTRYPOINT = path.resolve(
|
|
14
|
+
new URL(".", import.meta.url).pathname,
|
|
15
|
+
"api-handler-trpc.js"
|
|
16
|
+
);
|
|
9
17
|
function kyro(options = {}) {
|
|
10
18
|
const {
|
|
11
19
|
configPath = "./kyro.config.ts",
|
|
12
20
|
apiPath = "/api",
|
|
13
21
|
adminPath = "/admin",
|
|
14
|
-
admin = true
|
|
22
|
+
admin = true,
|
|
23
|
+
enableGraphQL = false,
|
|
24
|
+
enableTRPC = false,
|
|
25
|
+
enableWebSocket = false
|
|
15
26
|
} = options;
|
|
16
27
|
return {
|
|
17
28
|
name: "@kyro-cms/core",
|
|
18
29
|
hooks: {
|
|
19
30
|
"astro:config:setup": async ({ config, updateConfig, injectRoute, logger }) => {
|
|
20
31
|
logger.info(`Setting up Kyro CMS (API: ${apiPath}, Admin: ${adminPath})`);
|
|
32
|
+
if (apiPath === adminPath) {
|
|
33
|
+
throw new Error(`Kyro CMS: apiPath and adminPath cannot be the same ("${apiPath}")`);
|
|
34
|
+
}
|
|
21
35
|
const resolvedConfigPath = path.resolve(config.root.pathname, configPath);
|
|
22
36
|
let finalConfigPath = resolvedConfigPath;
|
|
23
37
|
if (!fs.existsSync(resolvedConfigPath)) {
|
|
@@ -40,11 +54,28 @@ function kyro(options = {}) {
|
|
|
40
54
|
pattern: `${apiPath}/[...path]`,
|
|
41
55
|
entrypoint: API_HANDLER_ENTRYPOINT
|
|
42
56
|
});
|
|
57
|
+
if (enableGraphQL) {
|
|
58
|
+
injectRoute({
|
|
59
|
+
pattern: `${apiPath}/graphql`,
|
|
60
|
+
entrypoint: GRAPHQL_HANDLER_ENTRYPOINT
|
|
61
|
+
});
|
|
62
|
+
logger.info(`GraphQL endpoint enabled at ${apiPath}/graphql`);
|
|
63
|
+
}
|
|
64
|
+
if (enableTRPC) {
|
|
65
|
+
injectRoute({
|
|
66
|
+
pattern: `${apiPath}/trpc/[...path]`,
|
|
67
|
+
entrypoint: TRPC_HANDLER_ENTRYPOINT
|
|
68
|
+
});
|
|
69
|
+
logger.info(`tRPC endpoint enabled at ${apiPath}/trpc`);
|
|
70
|
+
}
|
|
71
|
+
if (enableWebSocket) {
|
|
72
|
+
logger.info(`WebSocket support will be initialized at runtime`);
|
|
73
|
+
}
|
|
43
74
|
}
|
|
44
75
|
}
|
|
45
76
|
};
|
|
46
77
|
}
|
|
47
78
|
|
|
48
79
|
export { kyro };
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
50
|
-
//# sourceMappingURL=chunk-
|
|
80
|
+
//# sourceMappingURL=chunk-FXYP2HA6.js.map
|
|
81
|
+
//# sourceMappingURL=chunk-FXYP2HA6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/integration.ts"],"names":[],"mappings":"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","file":"chunk-FXYP2HA6.js","sourcesContent":["import type { AstroIntegration } from \"astro\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nconst API_HANDLER_ENTRYPOINT = path.resolve(\n new URL(\".\", import.meta.url).pathname,\n \"api-handler.js\",\n);\nconst GRAPHQL_HANDLER_ENTRYPOINT = path.resolve(\n new URL(\".\", import.meta.url).pathname,\n \"api-handler-graphql.js\",\n);\nconst TRPC_HANDLER_ENTRYPOINT = path.resolve(\n new URL(\".\", import.meta.url).pathname,\n \"api-handler-trpc.js\",\n);\n\nexport interface KyroIntegrationOptions {\n configPath?: string;\n apiPath?: string;\n adminPath?: string;\n admin?: boolean;\n enableGraphQL?: boolean;\n enableTRPC?: boolean;\n enableWebSocket?: boolean;\n}\n\nexport default function kyro(options: KyroIntegrationOptions = {}): AstroIntegration {\n const {\n configPath = \"./kyro.config.ts\",\n apiPath = \"/api\",\n adminPath = \"/admin\",\n admin = true,\n enableGraphQL = false,\n enableTRPC = false,\n enableWebSocket = false,\n } = options;\n\n return {\n name: \"@kyro-cms/core\",\n hooks: {\n \"astro:config:setup\": async ({ config, updateConfig, injectRoute, logger }) => {\n logger.info(`Setting up Kyro CMS (API: ${apiPath}, Admin: ${adminPath})`);\n \n if (apiPath === adminPath) {\n throw new Error(`Kyro CMS: apiPath and adminPath cannot be the same (\"${apiPath}\")`);\n }\n\n const resolvedConfigPath = path.resolve(config.root.pathname, configPath);\n \n let finalConfigPath = resolvedConfigPath;\n if (!fs.existsSync(resolvedConfigPath)) {\n logger.warn(`Kyro config file not found at ${configPath}. The API will fail to boot if collections are needed.`);\n }\n \n updateConfig({\n vite: {\n resolve: {\n alias: {\n \"kyro:config\": finalConfigPath,\n },\n },\n define: {\n __KYRO_API_PATH__: JSON.stringify(apiPath),\n __KYRO_ADMIN_PATH__: JSON.stringify(adminPath),\n },\n },\n });\n \n injectRoute({\n pattern: `${apiPath}/[...path]`,\n entrypoint: API_HANDLER_ENTRYPOINT,\n });\n\n if (enableGraphQL) {\n injectRoute({\n pattern: `${apiPath}/graphql`,\n entrypoint: GRAPHQL_HANDLER_ENTRYPOINT,\n });\n logger.info(`GraphQL endpoint enabled at ${apiPath}/graphql`);\n }\n\n if (enableTRPC) {\n injectRoute({\n pattern: `${apiPath}/trpc/[...path]`,\n entrypoint: TRPC_HANDLER_ENTRYPOINT,\n });\n logger.info(`tRPC endpoint enabled at ${apiPath}/trpc`);\n }\n\n if (enableWebSocket) {\n logger.info(`WebSocket support will be initialized at runtime`);\n }\n },\n },\n };\n}\n"]}
|