emulate 0.4.1 → 0.6.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.
Files changed (50) hide show
  1. package/README.md +198 -27
  2. package/dist/api.d.ts +2 -1
  3. package/dist/api.js +675 -103
  4. package/dist/api.js.map +1 -1
  5. package/dist/chunk-WVQMFHQM.js +83 -0
  6. package/dist/chunk-WVQMFHQM.js.map +1 -0
  7. package/dist/{dist-B674PYKV.js → dist-2ZZGNPJI.js} +22 -43
  8. package/dist/dist-2ZZGNPJI.js.map +1 -0
  9. package/dist/{dist-RDFBZ5O6.js → dist-CXRPM6BK.js} +211 -48
  10. package/dist/dist-CXRPM6BK.js.map +1 -0
  11. package/dist/{dist-VVXVP5EZ.js → dist-DSJSF3GY.js} +551 -91
  12. package/dist/dist-DSJSF3GY.js.map +1 -0
  13. package/dist/{dist-RMK3BS5M.js → dist-IFULY5LE.js} +196 -33
  14. package/dist/dist-IFULY5LE.js.map +1 -0
  15. package/dist/dist-IRUBHCZU.js +1898 -0
  16. package/dist/dist-IRUBHCZU.js.map +1 -0
  17. package/dist/{dist-YOVM5HEY.js → dist-NJJLJT2N.js} +520 -61
  18. package/dist/dist-NJJLJT2N.js.map +1 -0
  19. package/dist/dist-OGSAVJ25.js +4874 -0
  20. package/dist/dist-OGSAVJ25.js.map +1 -0
  21. package/dist/{dist-H6JYGQM4.js → dist-PO4CL5SJ.js} +271 -158
  22. package/dist/dist-PO4CL5SJ.js.map +1 -0
  23. package/dist/{dist-QMOJM6DV.js → dist-R3TNKUIE.js} +238 -55
  24. package/dist/dist-R3TNKUIE.js.map +1 -0
  25. package/dist/{dist-6JFNJPUU.js → dist-WACHAAVU.js} +171 -22
  26. package/dist/dist-WACHAAVU.js.map +1 -0
  27. package/dist/{dist-OTJZRQ3Q.js → dist-XWWZVLQQ.js} +216 -75
  28. package/dist/dist-XWWZVLQQ.js.map +1 -0
  29. package/dist/{dist-6EW7SSOZ.js → dist-ZY5SZSJ2.js} +397 -223
  30. package/dist/dist-ZY5SZSJ2.js.map +1 -0
  31. package/dist/fonts/favicon.ico +0 -0
  32. package/dist/helpers-LXLP3DFE-LBOTATT5.js +17 -0
  33. package/dist/helpers-LXLP3DFE-LBOTATT5.js.map +1 -0
  34. package/dist/index.js +812 -117
  35. package/dist/index.js.map +1 -1
  36. package/package.json +17 -15
  37. package/dist/chunk-TEPNEZ63.js +0 -2143
  38. package/dist/chunk-TEPNEZ63.js.map +0 -1
  39. package/dist/dist-6EW7SSOZ.js.map +0 -1
  40. package/dist/dist-6JFNJPUU.js.map +0 -1
  41. package/dist/dist-B674PYKV.js.map +0 -1
  42. package/dist/dist-G7WQPZ3Y.js +0 -1287
  43. package/dist/dist-G7WQPZ3Y.js.map +0 -1
  44. package/dist/dist-H6JYGQM4.js.map +0 -1
  45. package/dist/dist-OTJZRQ3Q.js.map +0 -1
  46. package/dist/dist-QMOJM6DV.js.map +0 -1
  47. package/dist/dist-RDFBZ5O6.js.map +0 -1
  48. package/dist/dist-RMK3BS5M.js.map +0 -1
  49. package/dist/dist-VVXVP5EZ.js.map +0 -1
  50. package/dist/dist-YOVM5HEY.js.map +0 -1
@@ -240,7 +240,7 @@ function dataApiRoutes(ctx) {
240
240
  if (!cluster) {
241
241
  return mongoError(c, "ClusterNotFound", `Cluster '${body.dataSource}' not found`, 404);
242
242
  }
243
- let docs = ms().documents.all().filter(
243
+ const docs = ms().documents.all().filter(
244
244
  (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection
245
245
  );
246
246
  const pipeline = body.pipeline ?? [];
@@ -268,13 +268,9 @@ function dataApiRoutes(ctx) {
268
268
  });
269
269
  }
270
270
  function ensureCollectionExists(ms, clusterId, database, collection) {
271
- const existing = ms().collections.all().find(
272
- (col) => col.cluster_id === clusterId && col.database === database && col.name === collection
273
- );
271
+ const existing = ms().collections.all().find((col) => col.cluster_id === clusterId && col.database === database && col.name === collection);
274
272
  if (!existing) {
275
- const dbExists = ms().databases.all().find(
276
- (db) => db.cluster_id === clusterId && db.name === database
277
- );
273
+ const dbExists = ms().databases.all().find((db) => db.cluster_id === clusterId && db.name === database);
278
274
  if (!dbExists) {
279
275
  ms().databases.insert({ cluster_id: clusterId, name: database });
280
276
  }
@@ -407,7 +403,8 @@ function applyUpdate(data, update) {
407
403
  } else {
408
404
  let current = result;
409
405
  for (let i = 0; i < parts.length - 1; i++) {
410
- if (current[parts[i]] === null || current[parts[i]] === void 0 || typeof current[parts[i]] !== "object") break;
406
+ if (current[parts[i]] === null || current[parts[i]] === void 0 || typeof current[parts[i]] !== "object")
407
+ break;
411
408
  current = current[parts[i]];
412
409
  }
413
410
  delete current[parts[parts.length - 1]];
@@ -437,7 +434,11 @@ function applyUpdate(data, update) {
437
434
  for (const [key, value] of Object.entries(pullFields)) {
438
435
  const current = getNestedValue(result, key);
439
436
  if (Array.isArray(current)) {
440
- setNestedValue(result, key, current.filter((item) => item !== value));
437
+ setNestedValue(
438
+ result,
439
+ key,
440
+ current.filter((item) => item !== value)
441
+ );
441
442
  }
442
443
  }
443
444
  }
@@ -581,9 +582,7 @@ function adminRoutes(ctx) {
581
582
  app.get("/api/atlas/v2/groups/:groupId/clusters/:clusterName", (c) => {
582
583
  const groupId = c.req.param("groupId");
583
584
  const clusterName = c.req.param("clusterName");
584
- const cluster = ms().clusters.all().find(
585
- (cl) => cl.group_id === groupId && cl.name === clusterName
586
- );
585
+ const cluster = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === clusterName);
587
586
  if (!cluster) {
588
587
  return mongoError(c, "CLUSTER_NOT_FOUND", `Cluster '${clusterName}' not found.`, 404);
589
588
  }
@@ -599,9 +598,7 @@ function adminRoutes(ctx) {
599
598
  if (!body.name?.trim()) {
600
599
  return mongoError(c, "INVALID_PARAMETER", "name is required");
601
600
  }
602
- const existing = ms().clusters.all().find(
603
- (cl) => cl.group_id === groupId && cl.name === body.name
604
- );
601
+ const existing = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === body.name);
605
602
  if (existing) {
606
603
  return mongoError(c, "DUPLICATE_CLUSTER_NAME", `Cluster '${body.name}' already exists.`, 409);
607
604
  }
@@ -631,9 +628,7 @@ function adminRoutes(ctx) {
631
628
  app.patch("/api/atlas/v2/groups/:groupId/clusters/:clusterName", async (c) => {
632
629
  const groupId = c.req.param("groupId");
633
630
  const clusterName = c.req.param("clusterName");
634
- const cluster = ms().clusters.all().find(
635
- (cl) => cl.group_id === groupId && cl.name === clusterName
636
- );
631
+ const cluster = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === clusterName);
637
632
  if (!cluster) {
638
633
  return mongoError(c, "CLUSTER_NOT_FOUND", `Cluster '${clusterName}' not found.`, 404);
639
634
  }
@@ -655,9 +650,7 @@ function adminRoutes(ctx) {
655
650
  app.delete("/api/atlas/v2/groups/:groupId/clusters/:clusterName", (c) => {
656
651
  const groupId = c.req.param("groupId");
657
652
  const clusterName = c.req.param("clusterName");
658
- const cluster = ms().clusters.all().find(
659
- (cl) => cl.group_id === groupId && cl.name === clusterName
660
- );
653
+ const cluster = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === clusterName);
661
654
  if (!cluster) {
662
655
  return mongoError(c, "CLUSTER_NOT_FOUND", `Cluster '${clusterName}' not found.`, 404);
663
656
  }
@@ -718,9 +711,7 @@ function adminRoutes(ctx) {
718
711
  app.get("/api/atlas/v2/groups/:groupId/clusters/:clusterName/databases", (c) => {
719
712
  const groupId = c.req.param("groupId");
720
713
  const clusterName = c.req.param("clusterName");
721
- const cluster = ms().clusters.all().find(
722
- (cl) => cl.group_id === groupId && cl.name === clusterName
723
- );
714
+ const cluster = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === clusterName);
724
715
  if (!cluster) {
725
716
  return mongoError(c, "CLUSTER_NOT_FOUND", `Cluster '${clusterName}' not found.`, 404);
726
717
  }
@@ -734,15 +725,11 @@ function adminRoutes(ctx) {
734
725
  const groupId = c.req.param("groupId");
735
726
  const clusterName = c.req.param("clusterName");
736
727
  const databaseName = c.req.param("databaseName");
737
- const cluster = ms().clusters.all().find(
738
- (cl) => cl.group_id === groupId && cl.name === clusterName
739
- );
728
+ const cluster = ms().clusters.all().find((cl) => cl.group_id === groupId && cl.name === clusterName);
740
729
  if (!cluster) {
741
730
  return mongoError(c, "CLUSTER_NOT_FOUND", `Cluster '${clusterName}' not found.`, 404);
742
731
  }
743
- const collections = ms().collections.all().filter(
744
- (col) => col.cluster_id === cluster.cluster_id && col.database === databaseName
745
- );
732
+ const collections = ms().collections.all().filter((col) => col.cluster_id === cluster.cluster_id && col.database === databaseName);
746
733
  return mongoOk(c, {
747
734
  results: collections.map((col) => ({ collectionName: col.name, databaseName })),
748
735
  totalCount: collections.length
@@ -863,9 +850,7 @@ function seedFromConfig(store, _baseUrl, config) {
863
850
  for (const cl of config.clusters) {
864
851
  const groupId = projectIdMap.get(cl.project);
865
852
  if (!groupId) continue;
866
- const existing = ms.clusters.all().find(
867
- (ec) => ec.group_id === groupId && ec.name === cl.name
868
- );
853
+ const existing = ms.clusters.all().find((ec) => ec.group_id === groupId && ec.name === cl.name);
869
854
  if (existing) {
870
855
  clusterIdMap.set(cl.name, existing.cluster_id);
871
856
  continue;
@@ -905,9 +890,7 @@ function seedFromConfig(store, _baseUrl, config) {
905
890
  for (const u of config.database_users) {
906
891
  const groupId = projectIdMap.get(u.project);
907
892
  if (!groupId) continue;
908
- const existing = ms.users.all().find(
909
- (eu) => eu.group_id === groupId && eu.username === u.username
910
- );
893
+ const existing = ms.users.all().find((eu) => eu.group_id === groupId && eu.username === u.username);
911
894
  if (existing) continue;
912
895
  ms.users.insert({
913
896
  user_id: generateUserId(),
@@ -921,17 +904,13 @@ function seedFromConfig(store, _baseUrl, config) {
921
904
  for (const db of config.databases) {
922
905
  const clusterId = clusterIdMap.get(db.cluster);
923
906
  if (!clusterId) continue;
924
- const existingDb = ms.databases.all().find(
925
- (edb) => edb.cluster_id === clusterId && edb.name === db.name
926
- );
907
+ const existingDb = ms.databases.all().find((edb) => edb.cluster_id === clusterId && edb.name === db.name);
927
908
  if (!existingDb) {
928
909
  ms.databases.insert({ cluster_id: clusterId, name: db.name });
929
910
  }
930
911
  if (db.collections) {
931
912
  for (const colName of db.collections) {
932
- const existingCol = ms.collections.all().find(
933
- (ec) => ec.cluster_id === clusterId && ec.database === db.name && ec.name === colName
934
- );
913
+ const existingCol = ms.collections.all().find((ec) => ec.cluster_id === clusterId && ec.database === db.name && ec.name === colName);
935
914
  if (!existingCol) {
936
915
  ms.collections.insert({ cluster_id: clusterId, database: db.name, name: colName });
937
916
  }
@@ -958,4 +937,4 @@ export {
958
937
  mongoatlasPlugin,
959
938
  seedFromConfig
960
939
  };
961
- //# sourceMappingURL=dist-B674PYKV.js.map
940
+ //# sourceMappingURL=dist-2ZZGNPJI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../@emulators/mongoatlas/src/store.ts","../../@emulators/mongoatlas/src/helpers.ts","../../@emulators/mongoatlas/src/routes/data-api.ts","../../@emulators/mongoatlas/src/routes/admin.ts","../../@emulators/mongoatlas/src/index.ts"],"sourcesContent":["import { type Store, type Collection } from \"@emulators/core\";\nimport type {\n MongoAtlasCluster,\n MongoAtlasDatabase,\n MongoAtlasCollection,\n MongoAtlasDocument,\n MongoAtlasProject,\n MongoAtlasUser,\n} from \"./entities.js\";\n\nexport interface MongoAtlasStore {\n clusters: Collection<MongoAtlasCluster>;\n databases: Collection<MongoAtlasDatabase>;\n collections: Collection<MongoAtlasCollection>;\n documents: Collection<MongoAtlasDocument>;\n projects: Collection<MongoAtlasProject>;\n users: Collection<MongoAtlasUser>;\n}\n\nexport function getMongoAtlasStore(store: Store): MongoAtlasStore {\n return {\n clusters: store.collection<MongoAtlasCluster>(\"mongoatlas.clusters\", [\"cluster_id\", \"name\"]),\n databases: store.collection<MongoAtlasDatabase>(\"mongoatlas.databases\", [\"cluster_id\", \"name\"]),\n collections: store.collection<MongoAtlasCollection>(\"mongoatlas.collections\", [\"cluster_id\", \"database\", \"name\"]),\n documents: store.collection<MongoAtlasDocument>(\"mongoatlas.documents\", [\"cluster_id\", \"doc_id\"]),\n projects: store.collection<MongoAtlasProject>(\"mongoatlas.projects\", [\"group_id\"]),\n users: store.collection<MongoAtlasUser>(\"mongoatlas.users\", [\"user_id\", \"username\"]),\n };\n}\n","import { randomBytes } from \"crypto\";\nimport type { Context } from \"@emulators/core\";\n\nexport function generateObjectId(): string {\n const timestamp = Math.floor(Date.now() / 1000)\n .toString(16)\n .padStart(8, \"0\");\n const random = randomBytes(8).toString(\"hex\").slice(0, 16);\n return (timestamp + random).slice(0, 24);\n}\n\nexport function generateClusterId(): string {\n return randomBytes(12).toString(\"hex\");\n}\n\nexport function generateGroupId(): string {\n return randomBytes(12).toString(\"hex\");\n}\n\nexport function generateUserId(): string {\n return randomBytes(12).toString(\"hex\");\n}\n\nexport function mongoOk<T extends Record<string, unknown>>(c: Context, data: T, status = 200) {\n return c.json(data, status as 200);\n}\n\nexport function mongoError(c: Context, errorCode: string, detail: string, status = 400) {\n return c.json({ error: status, errorCode, detail }, status as 400);\n}\n","import type { RouteContext } from \"@emulators/core\";\nimport { getMongoAtlasStore } from \"../store.js\";\nimport { generateObjectId, mongoOk, mongoError } from \"../helpers.js\";\n\n/**\n * MongoDB Atlas Data API endpoints.\n * These emulate the Atlas Data API v1 for CRUD operations on documents.\n * See: https://www.mongodb.com/docs/atlas/api/data-api-resources/\n */\nexport function dataApiRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ms = () => getMongoAtlasStore(store);\n\n // Find a single document\n app.post(\"/app/data-api/v1/action/findOne\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n projection?: Record<string, unknown>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, and collection are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n const matched = matchFilter(docs, body.filter) ?? docs;\n const doc = matched[0] ?? null;\n const projected = doc ? applyProjection(doc.data, body.projection) : null;\n\n return mongoOk(c, { document: projected });\n });\n\n // Find multiple documents\n app.post(\"/app/data-api/v1/action/find\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n projection?: Record<string, unknown>;\n sort?: Record<string, number>;\n limit?: number;\n skip?: number;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, and collection are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n let docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n docs = matchFilter(docs, body.filter) ?? docs;\n\n if (body.sort) {\n docs = sortBySpec(docs, body.sort, (d) => d.data);\n }\n\n if (body.skip) {\n docs = docs.slice(body.skip);\n }\n\n if (body.limit) {\n docs = docs.slice(0, body.limit);\n }\n\n const documents = docs.map((d) => applyProjection(d.data, body.projection));\n return mongoOk(c, { documents });\n });\n\n // Insert a single document\n app.post(\"/app/data-api/v1/action/insertOne\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n document?: Record<string, unknown>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection || !body.document) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, collection, and document are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n ensureCollectionExists(ms, cluster.cluster_id, body.database, body.collection);\n\n const docId = (body.document._id as string) ?? generateObjectId();\n const data = { ...body.document, _id: docId };\n\n ms().documents.insert({\n cluster_id: cluster.cluster_id,\n database: body.database,\n collection: body.collection,\n doc_id: docId,\n data,\n });\n\n return mongoOk(c, { insertedId: docId }, 201);\n });\n\n // Insert multiple documents\n app.post(\"/app/data-api/v1/action/insertMany\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n documents?: Array<Record<string, unknown>>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection || !body.documents) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, collection, and documents are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n ensureCollectionExists(ms, cluster.cluster_id, body.database, body.collection);\n\n const insertedIds: string[] = [];\n for (const doc of body.documents) {\n const docId = (doc._id as string) ?? generateObjectId();\n const data = { ...doc, _id: docId };\n\n ms().documents.insert({\n cluster_id: cluster.cluster_id,\n database: body.database,\n collection: body.collection,\n doc_id: docId,\n data,\n });\n insertedIds.push(docId);\n }\n\n return mongoOk(c, { insertedIds }, 201);\n });\n\n // Update a single document\n app.post(\"/app/data-api/v1/action/updateOne\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n update?: Record<string, unknown>;\n upsert?: boolean;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection || !body.update) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, collection, and update are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n const matched = matchFilter(docs, body.filter) ?? docs;\n const doc = matched[0];\n\n if (doc) {\n const updatedData = applyUpdate(doc.data, body.update);\n ms().documents.update(doc.id, { data: updatedData });\n return mongoOk(c, { matchedCount: 1, modifiedCount: 1 });\n }\n\n if (body.upsert) {\n ensureCollectionExists(ms, cluster.cluster_id, body.database, body.collection);\n const docId = generateObjectId();\n const baseDoc = extractEqualityFields(body.filter ?? {});\n const data = applyUpdate({ _id: docId, ...baseDoc }, body.update);\n ms().documents.insert({\n cluster_id: cluster.cluster_id,\n database: body.database,\n collection: body.collection,\n doc_id: docId,\n data,\n });\n return mongoOk(c, { matchedCount: 0, modifiedCount: 0, upsertedId: docId });\n }\n\n return mongoOk(c, { matchedCount: 0, modifiedCount: 0 });\n });\n\n // Update multiple documents\n app.post(\"/app/data-api/v1/action/updateMany\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n update?: Record<string, unknown>;\n upsert?: boolean;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection || !body.update) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, collection, and update are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n const matched = matchFilter(docs, body.filter) ?? docs;\n let modifiedCount = 0;\n\n for (const doc of matched) {\n const updatedData = applyUpdate(doc.data, body.update);\n ms().documents.update(doc.id, { data: updatedData });\n modifiedCount++;\n }\n\n if (matched.length === 0 && body.upsert) {\n ensureCollectionExists(ms, cluster.cluster_id, body.database, body.collection);\n const docId = generateObjectId();\n const baseDoc = extractEqualityFields(body.filter ?? {});\n const data = applyUpdate({ _id: docId, ...baseDoc }, body.update);\n ms().documents.insert({\n cluster_id: cluster.cluster_id,\n database: body.database,\n collection: body.collection,\n doc_id: docId,\n data,\n });\n return mongoOk(c, { matchedCount: 0, modifiedCount: 0, upsertedId: docId });\n }\n\n return mongoOk(c, { matchedCount: matched.length, modifiedCount });\n });\n\n // Delete a single document\n app.post(\"/app/data-api/v1/action/deleteOne\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, and collection are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n const matched = matchFilter(docs, body.filter) ?? docs;\n const doc = matched[0];\n\n if (doc) {\n ms().documents.delete(doc.id);\n return mongoOk(c, { deletedCount: 1 });\n }\n\n return mongoOk(c, { deletedCount: 0 });\n });\n\n // Delete multiple documents\n app.post(\"/app/data-api/v1/action/deleteMany\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n filter?: Record<string, unknown>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, and collection are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n const matched = matchFilter(docs, body.filter) ?? docs;\n let deletedCount = 0;\n\n for (const doc of matched) {\n ms().documents.delete(doc.id);\n deletedCount++;\n }\n\n return mongoOk(c, { deletedCount });\n });\n\n // Aggregate (simplified)\n app.post(\"/app/data-api/v1/action/aggregate\", async (c) => {\n const body = await c.req.json<{\n dataSource?: string;\n database?: string;\n collection?: string;\n pipeline?: Array<Record<string, unknown>>;\n }>();\n\n if (!body.dataSource || !body.database || !body.collection) {\n return mongoError(c, \"InvalidParameter\", \"dataSource, database, and collection are required\");\n }\n\n const cluster = ms().clusters.findOneBy(\"name\", body.dataSource);\n if (!cluster) {\n return mongoError(c, \"ClusterNotFound\", `Cluster '${body.dataSource}' not found`, 404);\n }\n\n const docs = ms()\n .documents.all()\n .filter(\n (d) => d.cluster_id === cluster.cluster_id && d.database === body.database && d.collection === body.collection,\n );\n\n // Process simplified pipeline stages\n const pipeline = body.pipeline ?? [];\n let results: Record<string, unknown>[] = docs.map((d) => d.data);\n\n for (const stage of pipeline) {\n if (\"$match\" in stage) {\n const filter = stage.$match as Record<string, unknown>;\n results = results.filter((d) => matchesFilter(d, filter));\n } else if (\"$limit\" in stage) {\n results = results.slice(0, stage.$limit as number);\n } else if (\"$skip\" in stage) {\n results = results.slice(stage.$skip as number);\n } else if (\"$sort\" in stage) {\n const sortSpec = stage.$sort as Record<string, number>;\n results = sortBySpec(results, sortSpec, (d) => d);\n } else if (\"$project\" in stage) {\n const projection = stage.$project as Record<string, unknown>;\n results = results.map((d) => applyProjection(d, projection));\n } else if (\"$count\" in stage) {\n const fieldName = stage.$count as string;\n results = [{ [fieldName]: results.length }];\n }\n }\n\n return mongoOk(c, { documents: results });\n });\n}\n\ntype MongoAtlasDocEntity = { data: Record<string, unknown>; id: number };\n\nfunction ensureCollectionExists(\n ms: () => ReturnType<typeof getMongoAtlasStore>,\n clusterId: string,\n database: string,\n collection: string,\n): void {\n const existing = ms()\n .collections.all()\n .find((col) => col.cluster_id === clusterId && col.database === database && col.name === collection);\n if (!existing) {\n // Auto-create database entry if needed\n const dbExists = ms()\n .databases.all()\n .find((db) => db.cluster_id === clusterId && db.name === database);\n if (!dbExists) {\n ms().databases.insert({ cluster_id: clusterId, name: database });\n }\n ms().collections.insert({ cluster_id: clusterId, database, name: collection });\n }\n}\n\nfunction matchesFilter(data: Record<string, unknown>, filter: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (key === \"$and\") {\n const conditions = value as Record<string, unknown>[];\n if (!conditions.every((cond) => matchesFilter(data, cond))) return false;\n continue;\n }\n if (key === \"$or\") {\n const conditions = value as Record<string, unknown>[];\n if (!conditions.some((cond) => matchesFilter(data, cond))) return false;\n continue;\n }\n if (key === \"$nor\") {\n const conditions = value as Record<string, unknown>[];\n if (conditions.some((cond) => matchesFilter(data, cond))) return false;\n continue;\n }\n\n const docValue = getNestedValue(data, key);\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const ops = value as Record<string, unknown>;\n for (const [op, opVal] of Object.entries(ops)) {\n switch (op) {\n case \"$eq\":\n if (docValue !== opVal) return false;\n break;\n case \"$ne\":\n if (docValue === opVal) return false;\n break;\n case \"$gt\":\n if (typeof docValue !== \"number\" || typeof opVal !== \"number\" || docValue <= opVal) return false;\n break;\n case \"$gte\":\n if (typeof docValue !== \"number\" || typeof opVal !== \"number\" || docValue < opVal) return false;\n break;\n case \"$lt\":\n if (typeof docValue !== \"number\" || typeof opVal !== \"number\" || docValue >= opVal) return false;\n break;\n case \"$lte\":\n if (typeof docValue !== \"number\" || typeof opVal !== \"number\" || docValue > opVal) return false;\n break;\n case \"$in\":\n if (!Array.isArray(opVal) || !opVal.includes(docValue)) return false;\n break;\n case \"$nin\":\n if (!Array.isArray(opVal) || opVal.includes(docValue)) return false;\n break;\n case \"$exists\":\n if (opVal && docValue === undefined) return false;\n if (!opVal && docValue !== undefined) return false;\n break;\n case \"$regex\": {\n const pattern = opVal as string;\n const flags = (ops.$options as string) ?? \"\";\n try {\n if (pattern.length > 1000) return false;\n const re = new RegExp(pattern, flags);\n if (typeof docValue !== \"string\" || !re.test(docValue)) return false;\n } catch {\n return false;\n }\n break;\n }\n }\n }\n } else {\n if (docValue !== value) return false;\n }\n }\n return true;\n}\n\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split(\".\");\n if (hasDangerousKey(parts)) return undefined;\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\nfunction matchFilter<T extends MongoAtlasDocEntity>(docs: T[], filter?: Record<string, unknown>): T[] | null {\n if (!filter || Object.keys(filter).length === 0) return null;\n return docs.filter((d) => matchesFilter(d.data, filter));\n}\n\nfunction applyProjection(data: Record<string, unknown>, projection?: Record<string, unknown>): Record<string, unknown> {\n if (!projection || Object.keys(projection).length === 0) return data;\n\n const hasInclusions = Object.values(projection).some((v) => v === 1 || v === true);\n\n if (hasInclusions) {\n const result: Record<string, unknown> = {};\n if (projection._id !== 0 && projection._id !== false) {\n result._id = data._id;\n }\n for (const [key, val] of Object.entries(projection)) {\n if (key === \"_id\") continue;\n if (val === 1 || val === true) {\n result[key] = data[key];\n }\n }\n return result;\n }\n\n const result = { ...data };\n for (const [key, val] of Object.entries(projection)) {\n if (val === 0 || val === false) {\n delete result[key];\n }\n }\n return result;\n}\n\nfunction applyUpdate(data: Record<string, unknown>, update: Record<string, unknown>): Record<string, unknown> {\n const result = { ...data };\n\n if (\"$set\" in update) {\n const setFields = update.$set as Record<string, unknown>;\n for (const [key, value] of Object.entries(setFields)) {\n setNestedValue(result, key, value);\n }\n }\n\n if (\"$unset\" in update) {\n const unsetFields = update.$unset as Record<string, unknown>;\n for (const key of Object.keys(unsetFields)) {\n const parts = key.split(\".\");\n if (hasDangerousKey(parts)) continue;\n if (parts.length === 1) {\n delete result[key];\n } else {\n let current: Record<string, unknown> = result;\n for (let i = 0; i < parts.length - 1; i++) {\n if (current[parts[i]] === null || current[parts[i]] === undefined || typeof current[parts[i]] !== \"object\")\n break;\n current = current[parts[i]] as Record<string, unknown>;\n }\n delete current[parts[parts.length - 1]];\n }\n }\n }\n\n if (\"$inc\" in update) {\n const incFields = update.$inc as Record<string, number>;\n for (const [key, value] of Object.entries(incFields)) {\n const current = (getNestedValue(result, key) as number) ?? 0;\n setNestedValue(result, key, current + value);\n }\n }\n\n if (\"$push\" in update) {\n const pushFields = update.$push as Record<string, unknown>;\n for (const [key, value] of Object.entries(pushFields)) {\n const current = getNestedValue(result, key);\n if (!Array.isArray(current)) {\n setNestedValue(result, key, [value]);\n } else {\n setNestedValue(result, key, [...current, value]);\n }\n }\n }\n\n if (\"$pull\" in update) {\n const pullFields = update.$pull as Record<string, unknown>;\n for (const [key, value] of Object.entries(pullFields)) {\n const current = getNestedValue(result, key);\n if (Array.isArray(current)) {\n setNestedValue(\n result,\n key,\n current.filter((item) => item !== value),\n );\n }\n }\n }\n\n if (\"$rename\" in update) {\n const renameFields = update.$rename as Record<string, string>;\n for (const [oldKey, newKey] of Object.entries(renameFields)) {\n const oldParts = oldKey.split(\".\");\n const newParts = newKey.split(\".\");\n if (hasDangerousKey(oldParts) || hasDangerousKey(newParts)) continue;\n const value = getNestedValue(result, oldKey);\n if (value !== undefined) {\n setNestedValue(result, newKey, value);\n if (oldParts.length === 1) {\n delete result[oldKey];\n } else {\n let current: Record<string, unknown> = result;\n for (let i = 0; i < oldParts.length - 1; i++) {\n if (typeof current[oldParts[i]] !== \"object\" || current[oldParts[i]] === null) break;\n current = current[oldParts[i]] as Record<string, unknown>;\n }\n delete current[oldParts[oldParts.length - 1]];\n }\n }\n }\n }\n\n // If no operators found, treat the entire update as a replacement (minus _id)\n const hasOperators = Object.keys(update).some((k) => k.startsWith(\"$\"));\n if (!hasOperators) {\n const id = result._id;\n for (const key of Object.keys(result)) {\n delete result[key];\n }\n result._id = id;\n Object.assign(result, update);\n }\n\n return result;\n}\n\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction hasDangerousKey(parts: string[]): boolean {\n return parts.some((p) => DANGEROUS_KEYS.has(p));\n}\n\nfunction setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split(\".\");\n if (hasDangerousKey(parts)) return;\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!(parts[i] in current) || typeof current[parts[i]] !== \"object\") {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = value;\n}\n\nfunction sortBySpec<T>(\n docs: T[],\n sortSpec: Record<string, number>,\n accessor: (doc: T) => Record<string, unknown>,\n): T[] {\n return [...docs].sort((a, b) => {\n for (const [key, direction] of Object.entries(sortSpec)) {\n const aVal = getNestedValue(accessor(a), key);\n const bVal = getNestedValue(accessor(b), key);\n if (aVal === bVal) continue;\n if (aVal === undefined) return direction;\n if (bVal === undefined) return -direction;\n if ((aVal as number) < (bVal as number)) return -direction;\n if ((aVal as number) > (bVal as number)) return direction;\n }\n return 0;\n });\n}\n\n/**\n * Extract simple equality fields from a filter for use as a base document during upsert.\n * Strips out query operators (keys starting with $) and fields with operator-object values.\n */\nfunction extractEqualityFields(filter: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(filter)) {\n if (key.startsWith(\"$\")) continue;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const ops = value as Record<string, unknown>;\n if (Object.keys(ops).some((k) => k.startsWith(\"$\"))) continue;\n }\n result[key] = value;\n }\n return result;\n}\n","import type { RouteContext } from \"@emulators/core\";\nimport { getMongoAtlasStore } from \"../store.js\";\nimport { generateClusterId, generateGroupId, generateUserId, mongoOk, mongoError } from \"../helpers.js\";\n\n/**\n * MongoDB Atlas Admin API endpoints.\n * These emulate the Atlas Administration API v2 for managing projects, clusters, and users.\n * See: https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/\n */\nexport function adminRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const ms = () => getMongoAtlasStore(store);\n\n // --- Projects ---\n\n // List projects\n app.get(\"/api/atlas/v2/groups\", (c) => {\n const projects = ms().projects.all();\n return mongoOk(c, {\n results: projects.map(formatProject),\n totalCount: projects.length,\n });\n });\n\n // Get project by ID\n app.get(\"/api/atlas/v2/groups/:groupId\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const project = ms().projects.findOneBy(\"group_id\", groupId);\n if (!project) {\n return mongoError(c, \"GROUP_NOT_FOUND\", `Group '${groupId}' not found.`, 404);\n }\n return mongoOk(c, formatProject(project));\n });\n\n // Create project\n app.post(\"/api/atlas/v2/groups\", async (c) => {\n const body = await c.req.json<{ name?: string; orgId?: string }>();\n if (!body.name?.trim()) {\n return mongoError(c, \"INVALID_PARAMETER\", \"name is required\");\n }\n\n const existing = ms()\n .projects.all()\n .find((p) => p.name === body.name);\n if (existing) {\n return mongoError(c, \"DUPLICATE_GROUP_NAME\", `Group name '${body.name}' already exists.`, 409);\n }\n\n const groupId = generateGroupId();\n const project = ms().projects.insert({\n group_id: groupId,\n name: body.name,\n org_id: body.orgId ?? \"default_org\",\n cluster_count: 0,\n });\n\n return mongoOk(c, formatProject(project), 201);\n });\n\n // Delete project\n app.delete(\"/api/atlas/v2/groups/:groupId\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const project = ms().projects.findOneBy(\"group_id\", groupId);\n if (!project) {\n return mongoError(c, \"GROUP_NOT_FOUND\", `Group '${groupId}' not found.`, 404);\n }\n\n // Cascade delete clusters in this project\n const clusters = ms()\n .clusters.all()\n .filter((cl) => cl.group_id === groupId);\n for (const cluster of clusters) {\n deleteClusterData(ms, cluster.cluster_id);\n ms().clusters.delete(cluster.id);\n }\n\n ms().projects.delete(project.id);\n return c.body(null, 204);\n });\n\n // --- Clusters ---\n\n // List clusters\n app.get(\"/api/atlas/v2/groups/:groupId/clusters\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const project = ms().projects.findOneBy(\"group_id\", groupId);\n if (!project) {\n return mongoError(c, \"GROUP_NOT_FOUND\", `Group '${groupId}' not found.`, 404);\n }\n\n const clusters = ms()\n .clusters.all()\n .filter((cl) => cl.group_id === groupId);\n return mongoOk(c, {\n results: clusters.map(formatCluster),\n totalCount: clusters.length,\n });\n });\n\n // Get cluster\n app.get(\"/api/atlas/v2/groups/:groupId/clusters/:clusterName\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const clusterName = c.req.param(\"clusterName\");\n const cluster = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === clusterName);\n\n if (!cluster) {\n return mongoError(c, \"CLUSTER_NOT_FOUND\", `Cluster '${clusterName}' not found.`, 404);\n }\n\n return mongoOk(c, formatCluster(cluster));\n });\n\n // Create cluster\n app.post(\"/api/atlas/v2/groups/:groupId/clusters\", async (c) => {\n const groupId = c.req.param(\"groupId\");\n const project = ms().projects.findOneBy(\"group_id\", groupId);\n if (!project) {\n return mongoError(c, \"GROUP_NOT_FOUND\", `Group '${groupId}' not found.`, 404);\n }\n\n const body = await c.req.json<{\n name?: string;\n clusterType?: \"REPLICASET\" | \"SHARDED\";\n providerSettings?: {\n providerName?: string;\n instanceSizeName?: string;\n regionName?: string;\n };\n diskSizeGB?: number;\n mongoDBMajorVersion?: string;\n }>();\n\n if (!body.name?.trim()) {\n return mongoError(c, \"INVALID_PARAMETER\", \"name is required\");\n }\n\n const existing = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === body.name);\n if (existing) {\n return mongoError(c, \"DUPLICATE_CLUSTER_NAME\", `Cluster '${body.name}' already exists.`, 409);\n }\n\n const clusterId = generateClusterId();\n const cluster = ms().clusters.insert({\n cluster_id: clusterId,\n name: body.name,\n group_id: groupId,\n state: \"IDLE\",\n mongo_uri: `mongodb+srv://${body.name}.emulate.mongodb.net`,\n connection_strings: {\n standard: `mongodb://${body.name}.emulate.mongodb.net:27017`,\n standard_srv: `mongodb+srv://${body.name}.emulate.mongodb.net`,\n },\n provider_settings: {\n provider_name: body.providerSettings?.providerName ?? \"AWS\",\n instance_size_name: body.providerSettings?.instanceSizeName ?? \"M10\",\n region_name: body.providerSettings?.regionName ?? \"US_EAST_1\",\n },\n cluster_type: body.clusterType ?? \"REPLICASET\",\n disk_size_gb: body.diskSizeGB ?? 10,\n mongodb_version: body.mongoDBMajorVersion ?? \"8.0\",\n });\n\n ms().projects.update(project.id, { cluster_count: project.cluster_count + 1 });\n\n return mongoOk(c, formatCluster(cluster), 201);\n });\n\n // Update cluster\n app.patch(\"/api/atlas/v2/groups/:groupId/clusters/:clusterName\", async (c) => {\n const groupId = c.req.param(\"groupId\");\n const clusterName = c.req.param(\"clusterName\");\n const cluster = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === clusterName);\n\n if (!cluster) {\n return mongoError(c, \"CLUSTER_NOT_FOUND\", `Cluster '${clusterName}' not found.`, 404);\n }\n\n const body = await c.req.json<{\n providerSettings?: {\n instanceSizeName?: string;\n regionName?: string;\n };\n diskSizeGB?: number;\n }>();\n\n const updates: Partial<typeof cluster> = {};\n if (body.providerSettings) {\n updates.provider_settings = {\n provider_name: cluster.provider_settings.provider_name,\n instance_size_name: body.providerSettings.instanceSizeName ?? cluster.provider_settings.instance_size_name,\n region_name: body.providerSettings.regionName ?? cluster.provider_settings.region_name,\n };\n }\n if (body.diskSizeGB !== undefined) {\n updates.disk_size_gb = body.diskSizeGB;\n }\n\n const updated = ms().clusters.update(cluster.id, updates);\n return mongoOk(c, formatCluster(updated!));\n });\n\n // Delete cluster\n app.delete(\"/api/atlas/v2/groups/:groupId/clusters/:clusterName\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const clusterName = c.req.param(\"clusterName\");\n const cluster = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === clusterName);\n\n if (!cluster) {\n return mongoError(c, \"CLUSTER_NOT_FOUND\", `Cluster '${clusterName}' not found.`, 404);\n }\n\n deleteClusterData(ms, cluster.cluster_id);\n ms().clusters.delete(cluster.id);\n\n const project = ms().projects.findOneBy(\"group_id\", groupId);\n if (project) {\n ms().projects.update(project.id, { cluster_count: Math.max(0, project.cluster_count - 1) });\n }\n\n return c.body(null, 204);\n });\n\n // --- Database Users ---\n\n // List database users\n app.get(\"/api/atlas/v2/groups/:groupId/databaseUsers\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const users = ms()\n .users.all()\n .filter((u) => u.group_id === groupId);\n return mongoOk(c, {\n results: users.map(formatUser),\n totalCount: users.length,\n });\n });\n\n // Get database user\n app.get(\"/api/atlas/v2/groups/:groupId/databaseUsers/admin/:username\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const username = c.req.param(\"username\");\n const user = ms()\n .users.all()\n .find((u) => u.group_id === groupId && u.username === username);\n\n if (!user) {\n return mongoError(c, \"USER_NOT_FOUND\", `Database user '${username}' not found.`, 404);\n }\n\n return mongoOk(c, formatUser(user));\n });\n\n // Create database user\n app.post(\"/api/atlas/v2/groups/:groupId/databaseUsers\", async (c) => {\n const groupId = c.req.param(\"groupId\");\n const body = await c.req.json<{\n username?: string;\n password?: string;\n databaseName?: string;\n roles?: Array<{ databaseName: string; roleName: string }>;\n }>();\n\n if (!body.username?.trim()) {\n return mongoError(c, \"INVALID_PARAMETER\", \"username is required\");\n }\n\n const existing = ms()\n .users.all()\n .find((u) => u.group_id === groupId && u.username === body.username);\n if (existing) {\n return mongoError(c, \"DUPLICATE_USER\", `User '${body.username}' already exists.`, 409);\n }\n\n const userId = generateUserId();\n const user = ms().users.insert({\n user_id: userId,\n username: body.username,\n group_id: groupId,\n roles: (body.roles ?? []).map((r) => ({ database_name: r.databaseName, role_name: r.roleName })),\n });\n\n return mongoOk(c, formatUser(user), 201);\n });\n\n // Delete database user\n app.delete(\"/api/atlas/v2/groups/:groupId/databaseUsers/admin/:username\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const username = c.req.param(\"username\");\n const user = ms()\n .users.all()\n .find((u) => u.group_id === groupId && u.username === username);\n\n if (!user) {\n return mongoError(c, \"USER_NOT_FOUND\", `Database user '${username}' not found.`, 404);\n }\n\n ms().users.delete(user.id);\n return c.body(null, 204);\n });\n\n // --- Databases & Collections (Data Explorer) ---\n\n // List databases in a cluster\n app.get(\"/api/atlas/v2/groups/:groupId/clusters/:clusterName/databases\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const clusterName = c.req.param(\"clusterName\");\n const cluster = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === clusterName);\n\n if (!cluster) {\n return mongoError(c, \"CLUSTER_NOT_FOUND\", `Cluster '${clusterName}' not found.`, 404);\n }\n\n const databases = ms()\n .databases.all()\n .filter((db) => db.cluster_id === cluster.cluster_id);\n return mongoOk(c, {\n results: databases.map((db) => ({ databaseName: db.name })),\n totalCount: databases.length,\n });\n });\n\n // List collections in a database\n app.get(\"/api/atlas/v2/groups/:groupId/clusters/:clusterName/databases/:databaseName/collections\", (c) => {\n const groupId = c.req.param(\"groupId\");\n const clusterName = c.req.param(\"clusterName\");\n const databaseName = c.req.param(\"databaseName\");\n const cluster = ms()\n .clusters.all()\n .find((cl) => cl.group_id === groupId && cl.name === clusterName);\n\n if (!cluster) {\n return mongoError(c, \"CLUSTER_NOT_FOUND\", `Cluster '${clusterName}' not found.`, 404);\n }\n\n const collections = ms()\n .collections.all()\n .filter((col) => col.cluster_id === cluster.cluster_id && col.database === databaseName);\n return mongoOk(c, {\n results: collections.map((col) => ({ collectionName: col.name, databaseName })),\n totalCount: collections.length,\n });\n });\n}\n\nfunction deleteClusterData(ms: () => ReturnType<typeof getMongoAtlasStore>, clusterId: string): void {\n const docs = ms()\n .documents.all()\n .filter((d) => d.cluster_id === clusterId);\n for (const doc of docs) ms().documents.delete(doc.id);\n\n const cols = ms()\n .collections.all()\n .filter((col) => col.cluster_id === clusterId);\n for (const col of cols) ms().collections.delete(col.id);\n\n const dbs = ms()\n .databases.all()\n .filter((db) => db.cluster_id === clusterId);\n for (const db of dbs) ms().databases.delete(db.id);\n}\n\nfunction formatProject(p: {\n group_id: string;\n name: string;\n org_id: string;\n cluster_count: number;\n created_at: string;\n}) {\n return {\n id: p.group_id,\n name: p.name,\n orgId: p.org_id,\n clusterCount: p.cluster_count,\n created: p.created_at,\n };\n}\n\nfunction formatCluster(cl: {\n cluster_id: string;\n name: string;\n group_id: string;\n state: string;\n mongo_uri: string;\n connection_strings: { standard: string; standard_srv: string };\n provider_settings: { provider_name: string; instance_size_name: string; region_name: string };\n cluster_type: string;\n disk_size_gb: number;\n mongodb_version: string;\n created_at: string;\n}) {\n return {\n id: cl.cluster_id,\n name: cl.name,\n groupId: cl.group_id,\n stateName: cl.state,\n mongoURI: cl.mongo_uri,\n connectionStrings: {\n standard: cl.connection_strings.standard,\n standardSrv: cl.connection_strings.standard_srv,\n },\n providerSettings: {\n providerName: cl.provider_settings.provider_name,\n instanceSizeName: cl.provider_settings.instance_size_name,\n regionName: cl.provider_settings.region_name,\n },\n clusterType: cl.cluster_type,\n diskSizeGB: cl.disk_size_gb,\n mongoDBVersion: cl.mongodb_version,\n created: cl.created_at,\n };\n}\n\nfunction formatUser(u: {\n user_id: string;\n username: string;\n group_id: string;\n roles: Array<{ database_name: string; role_name: string }>;\n}) {\n return {\n username: u.username,\n groupId: u.group_id,\n databaseName: \"admin\",\n roles: u.roles.map((r) => ({ databaseName: r.database_name, roleName: r.role_name })),\n };\n}\n","import type { Hono } from \"@emulators/core\";\nimport type { ServicePlugin, Store, WebhookDispatcher, TokenMap, AppEnv, RouteContext } from \"@emulators/core\";\nimport { getMongoAtlasStore } from \"./store.js\";\nimport { generateClusterId, generateGroupId, generateUserId } from \"./helpers.js\";\nimport { dataApiRoutes } from \"./routes/data-api.js\";\nimport { adminRoutes } from \"./routes/admin.js\";\n\nexport { getMongoAtlasStore, type MongoAtlasStore } from \"./store.js\";\nexport * from \"./entities.js\";\n\nexport interface MongoAtlasSeedConfig {\n port?: number;\n projects?: Array<{\n name: string;\n org_id?: string;\n }>;\n clusters?: Array<{\n name: string;\n project: string;\n provider?: string;\n instance_size?: string;\n region?: string;\n disk_size_gb?: number;\n mongodb_version?: string;\n }>;\n database_users?: Array<{\n username: string;\n project: string;\n roles?: Array<{ database_name: string; role_name: string }>;\n }>;\n databases?: Array<{\n cluster: string;\n name: string;\n collections?: string[];\n }>;\n}\n\nfunction seedDefaults(store: Store, _baseUrl: string): void {\n const ms = getMongoAtlasStore(store);\n\n const groupId = generateGroupId();\n ms.projects.insert({\n group_id: groupId,\n name: \"Project0\",\n org_id: \"default_org\",\n cluster_count: 1,\n });\n\n const clusterId = generateClusterId();\n ms.clusters.insert({\n cluster_id: clusterId,\n name: \"Cluster0\",\n group_id: groupId,\n state: \"IDLE\",\n mongo_uri: \"mongodb+srv://Cluster0.emulate.mongodb.net\",\n connection_strings: {\n standard: \"mongodb://Cluster0.emulate.mongodb.net:27017\",\n standard_srv: \"mongodb+srv://Cluster0.emulate.mongodb.net\",\n },\n provider_settings: {\n provider_name: \"AWS\",\n instance_size_name: \"M10\",\n region_name: \"US_EAST_1\",\n },\n cluster_type: \"REPLICASET\",\n disk_size_gb: 10,\n mongodb_version: \"8.0\",\n });\n\n ms.users.insert({\n user_id: generateUserId(),\n username: \"admin\",\n group_id: groupId,\n roles: [{ database_name: \"admin\", role_name: \"atlasAdmin\" }],\n });\n\n ms.databases.insert({ cluster_id: clusterId, name: \"test\" });\n ms.collections.insert({ cluster_id: clusterId, database: \"test\", name: \"items\" });\n}\n\nexport function seedFromConfig(store: Store, _baseUrl: string, config: MongoAtlasSeedConfig): void {\n const ms = getMongoAtlasStore(store);\n\n const projectIdMap = new Map<string, string>();\n\n if (config.projects) {\n for (const p of config.projects) {\n const existing = ms.projects.all().find((ep) => ep.name === p.name);\n if (existing) {\n projectIdMap.set(p.name, existing.group_id);\n continue;\n }\n\n const groupId = generateGroupId();\n ms.projects.insert({\n group_id: groupId,\n name: p.name,\n org_id: p.org_id ?? \"default_org\",\n cluster_count: 0,\n });\n projectIdMap.set(p.name, groupId);\n }\n }\n\n // Map default project\n const defaultProject = ms.projects.all()[0];\n if (defaultProject) {\n projectIdMap.set(defaultProject.name, defaultProject.group_id);\n }\n\n const clusterIdMap = new Map<string, string>();\n\n if (config.clusters) {\n for (const cl of config.clusters) {\n const groupId = projectIdMap.get(cl.project);\n if (!groupId) continue;\n\n const existing = ms.clusters.all().find((ec) => ec.group_id === groupId && ec.name === cl.name);\n if (existing) {\n clusterIdMap.set(cl.name, existing.cluster_id);\n continue;\n }\n\n const clusterId = generateClusterId();\n ms.clusters.insert({\n cluster_id: clusterId,\n name: cl.name,\n group_id: groupId,\n state: \"IDLE\",\n mongo_uri: `mongodb+srv://${cl.name}.emulate.mongodb.net`,\n connection_strings: {\n standard: `mongodb://${cl.name}.emulate.mongodb.net:27017`,\n standard_srv: `mongodb+srv://${cl.name}.emulate.mongodb.net`,\n },\n provider_settings: {\n provider_name: cl.provider ?? \"AWS\",\n instance_size_name: cl.instance_size ?? \"M10\",\n region_name: cl.region ?? \"US_EAST_1\",\n },\n cluster_type: \"REPLICASET\",\n disk_size_gb: cl.disk_size_gb ?? 10,\n mongodb_version: cl.mongodb_version ?? \"8.0\",\n });\n clusterIdMap.set(cl.name, clusterId);\n\n const project = ms.projects.findOneBy(\"group_id\", groupId);\n if (project) {\n ms.projects.update(project.id, { cluster_count: project.cluster_count + 1 });\n }\n }\n }\n\n // Map default cluster\n const defaultCluster = ms.clusters.all()[0];\n if (defaultCluster) {\n clusterIdMap.set(defaultCluster.name, defaultCluster.cluster_id);\n }\n\n if (config.database_users) {\n for (const u of config.database_users) {\n const groupId = projectIdMap.get(u.project);\n if (!groupId) continue;\n\n const existing = ms.users.all().find((eu) => eu.group_id === groupId && eu.username === u.username);\n if (existing) continue;\n\n ms.users.insert({\n user_id: generateUserId(),\n username: u.username,\n group_id: groupId,\n roles: u.roles ?? [{ database_name: \"admin\", role_name: \"readWriteAnyDatabase\" }],\n });\n }\n }\n\n if (config.databases) {\n for (const db of config.databases) {\n const clusterId = clusterIdMap.get(db.cluster);\n if (!clusterId) continue;\n\n const existingDb = ms.databases.all().find((edb) => edb.cluster_id === clusterId && edb.name === db.name);\n if (!existingDb) {\n ms.databases.insert({ cluster_id: clusterId, name: db.name });\n }\n\n if (db.collections) {\n for (const colName of db.collections) {\n const existingCol = ms.collections\n .all()\n .find((ec) => ec.cluster_id === clusterId && ec.database === db.name && ec.name === colName);\n if (!existingCol) {\n ms.collections.insert({ cluster_id: clusterId, database: db.name, name: colName });\n }\n }\n }\n }\n }\n}\n\nexport const mongoatlasPlugin: ServicePlugin = {\n name: \"mongoatlas\",\n register(app: Hono<AppEnv>, store: Store, webhooks: WebhookDispatcher, baseUrl: string, tokenMap?: TokenMap): void {\n const ctx: RouteContext = { app, store, webhooks, baseUrl, tokenMap };\n adminRoutes(ctx);\n dataApiRoutes(ctx);\n },\n seed(store: Store, baseUrl: string): void {\n seedDefaults(store, baseUrl);\n },\n};\n\nexport default mongoatlasPlugin;\n"],"mappings":"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","names":["result"]}