@emulators/aws 0.3.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts","../src/helpers.ts","../src/routes/s3.ts","../src/routes/sqs.ts","../src/routes/iam.ts","../src/routes/inspector.ts","../src/index.ts"],"sourcesContent":["import { Store, type Collection } from \"@emulators/core\";\nimport type { S3Bucket, S3Object, SqsQueue, SqsMessage, IamUser, IamRole } from \"./entities.js\";\n\nexport interface AwsStore {\n s3Buckets: Collection<S3Bucket>;\n s3Objects: Collection<S3Object>;\n sqsQueues: Collection<SqsQueue>;\n sqsMessages: Collection<SqsMessage>;\n iamUsers: Collection<IamUser>;\n iamRoles: Collection<IamRole>;\n}\n\nexport function getAwsStore(store: Store): AwsStore {\n return {\n s3Buckets: store.collection<S3Bucket>(\"aws.s3_buckets\", [\"bucket_name\"]),\n s3Objects: store.collection<S3Object>(\"aws.s3_objects\", [\"key\", \"bucket_name\"]),\n sqsQueues: store.collection<SqsQueue>(\"aws.sqs_queues\", [\"queue_name\", \"queue_url\"]),\n sqsMessages: store.collection<SqsMessage>(\"aws.sqs_messages\", [\"message_id\", \"queue_name\"]),\n iamUsers: store.collection<IamUser>(\"aws.iam_users\", [\"user_name\", \"user_id\"]),\n iamRoles: store.collection<IamRole>(\"aws.iam_roles\", [\"role_name\", \"role_id\"]),\n };\n}\n","import { randomBytes, createHash } from \"crypto\";\nimport type { Context } from \"hono\";\n\nconst ACCOUNT_ID = \"123456789012\";\nconst DEFAULT_REGION = \"us-east-1\";\n\nexport function generateAwsId(prefix: string): string {\n return prefix + randomBytes(8).toString(\"hex\").toUpperCase();\n}\n\nexport function generateMessageId(): string {\n return [\n randomBytes(4).toString(\"hex\"),\n randomBytes(2).toString(\"hex\"),\n randomBytes(2).toString(\"hex\"),\n randomBytes(2).toString(\"hex\"),\n randomBytes(6).toString(\"hex\"),\n ].join(\"-\");\n}\n\nexport function generateReceiptHandle(): string {\n return randomBytes(48).toString(\"base64url\");\n}\n\nexport function md5(content: string): string {\n return createHash(\"md5\").update(content).digest(\"hex\");\n}\n\nexport function getAccountId(): string {\n return ACCOUNT_ID;\n}\n\nexport function getDefaultRegion(): string {\n return DEFAULT_REGION;\n}\n\nexport function awsXmlResponse(c: Context, xml: string, status = 200) {\n return c.text(xml, status, { \"Content-Type\": \"application/xml\" });\n}\n\nexport function awsErrorXml(c: Context, code: string, message: string, status = 400) {\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ErrorResponse>\n <Error>\n <Code>${escapeXml(code)}</Code>\n <Message>${escapeXml(message)}</Message>\n </Error>\n <RequestId>${generateMessageId()}</RequestId>\n</ErrorResponse>`;\n return c.text(xml, status, { \"Content-Type\": \"application/xml\" });\n}\n\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nexport function parseQueryString(body: string): Record<string, string> {\n const params = new URLSearchParams(body);\n const result: Record<string, string> = {};\n for (const [key, value] of params) {\n result[key] = value;\n }\n return result;\n}\n","import type { RouteContext } from \"@emulators/core\";\nimport { getAwsStore } from \"../store.js\";\nimport { awsXmlResponse, awsErrorXml, md5, generateMessageId, escapeXml } from \"../helpers.js\";\n\nexport function s3Routes(ctx: RouteContext): void {\n const { app, store, baseUrl } = ctx;\n const aws = () => getAwsStore(store);\n\n // ListBuckets - GET /s3/\n app.get(\"/s3/\", (c) => {\n const buckets = aws().s3Buckets.all();\n const bucketXml = buckets\n .map(\n (b) => ` <Bucket>\n <Name>${escapeXml(b.bucket_name)}</Name>\n <CreationDate>${b.creation_date}</CreationDate>\n </Bucket>`,\n )\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListAllMyBucketsResult>\n <Owner>\n <ID>owner-id</ID>\n <DisplayName>emulate</DisplayName>\n </Owner>\n <Buckets>\n${bucketXml}\n </Buckets>\n</ListAllMyBucketsResult>`;\n return awsXmlResponse(c, xml);\n });\n\n // CreateBucket - PUT /s3/:bucket\n app.put(\"/s3/:bucket\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const existing = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (existing) {\n return awsErrorXml(c, \"BucketAlreadyOwnedByYou\", \"Your previous request to create the named bucket succeeded and you already own it.\", 409);\n }\n\n aws().s3Buckets.insert({\n bucket_name: bucketName,\n region: \"us-east-1\",\n creation_date: new Date().toISOString(),\n acl: \"private\",\n versioning_enabled: false,\n });\n\n return c.text(\"\", 200, { Location: `/${bucketName}` });\n });\n\n // DeleteBucket - DELETE /s3/:bucket\n app.delete(\"/s3/:bucket\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const bucket = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (!bucket) {\n return awsErrorXml(c, \"NoSuchBucket\", \"The specified bucket does not exist.\", 404);\n }\n\n const objects = aws().s3Objects.findBy(\"bucket_name\", bucketName);\n if (objects.length > 0) {\n return awsErrorXml(c, \"BucketNotEmpty\", \"The bucket you tried to delete is not empty.\", 409);\n }\n\n aws().s3Buckets.delete(bucket.id);\n return c.body(null, 204);\n });\n\n // HeadBucket - HEAD /s3/:bucket\n app.on(\"HEAD\", \"/s3/:bucket\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const bucket = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (!bucket) {\n return c.text(\"\", 404);\n }\n return c.text(\"\", 200, { \"x-amz-bucket-region\": bucket.region });\n });\n\n // ListObjects (v2) - GET /s3/:bucket\n app.get(\"/s3/:bucket\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const bucket = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (!bucket) {\n return awsErrorXml(c, \"NoSuchBucket\", \"The specified bucket does not exist.\", 404);\n }\n\n const prefix = c.req.query(\"prefix\") ?? \"\";\n const delimiter = c.req.query(\"delimiter\") ?? \"\";\n const maxKeys = Math.min(parseInt(c.req.query(\"max-keys\") ?? \"1000\", 10), 1000);\n\n let objects = aws().s3Objects.findBy(\"bucket_name\", bucketName);\n if (prefix) {\n objects = objects.filter((o) => o.key.startsWith(prefix));\n }\n\n const commonPrefixes: string[] = [];\n let contents = objects;\n if (delimiter) {\n const prefixSet = new Set<string>();\n contents = [];\n for (const obj of objects) {\n const remaining = obj.key.slice(prefix.length);\n const delimIndex = remaining.indexOf(delimiter);\n if (delimIndex >= 0) {\n prefixSet.add(prefix + remaining.slice(0, delimIndex + delimiter.length));\n } else {\n contents.push(obj);\n }\n }\n commonPrefixes.push(...Array.from(prefixSet).sort());\n }\n\n const truncated = contents.length > maxKeys;\n const page = contents.slice(0, maxKeys);\n\n const contentsXml = page\n .map(\n (o) => ` <Contents>\n <Key>${escapeXml(o.key)}</Key>\n <LastModified>${o.last_modified}</LastModified>\n <ETag>\"${o.etag}\"</ETag>\n <Size>${o.content_length}</Size>\n <StorageClass>STANDARD</StorageClass>\n </Contents>`,\n )\n .join(\"\\n\");\n\n const prefixesXml = commonPrefixes\n .map((p) => ` <CommonPrefixes><Prefix>${escapeXml(p)}</Prefix></CommonPrefixes>`)\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListBucketResult>\n <Name>${escapeXml(bucketName)}</Name>\n <Prefix>${escapeXml(prefix)}</Prefix>\n <MaxKeys>${maxKeys}</MaxKeys>\n <IsTruncated>${truncated}</IsTruncated>\n <KeyCount>${page.length}</KeyCount>\n${contentsXml}\n${prefixesXml}\n</ListBucketResult>`;\n return awsXmlResponse(c, xml);\n });\n\n // PutObject - PUT /s3/:bucket/:key{.+}\n // Also handles CopyObject when x-amz-copy-source header is present\n app.put(\"/s3/:bucket/:key{.+}\", async (c) => {\n const bucketName = c.req.param(\"bucket\");\n const key = c.req.param(\"key\");\n\n const bucket = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (!bucket) {\n return awsErrorXml(c, \"NoSuchBucket\", \"The specified bucket does not exist.\", 404);\n }\n\n // Handle CopyObject via x-amz-copy-source header\n const copySource = c.req.header(\"x-amz-copy-source\");\n if (copySource) {\n // copySource format: /bucket/key or bucket/key\n const normalized = copySource.startsWith(\"/\") ? copySource.slice(1) : copySource;\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex < 0) {\n return awsErrorXml(c, \"InvalidArgument\", \"Invalid copy source.\", 400);\n }\n const srcBucket = normalized.slice(0, slashIndex);\n const srcKey = normalized.slice(slashIndex + 1);\n\n const srcObj = aws()\n .s3Objects.findBy(\"bucket_name\", srcBucket)\n .find((o) => o.key === srcKey);\n if (!srcObj) {\n return awsErrorXml(c, \"NoSuchKey\", \"The specified source key does not exist.\", 404);\n }\n\n const etag = srcObj.etag;\n const now = new Date().toISOString();\n\n const existing = aws()\n .s3Objects.findBy(\"bucket_name\", bucketName)\n .find((o) => o.key === key);\n\n if (existing) {\n aws().s3Objects.update(existing.id, {\n body: srcObj.body,\n content_type: srcObj.content_type,\n content_length: srcObj.content_length,\n etag,\n last_modified: now,\n metadata: { ...srcObj.metadata },\n });\n } else {\n aws().s3Objects.insert({\n bucket_name: bucketName,\n key,\n body: srcObj.body,\n content_type: srcObj.content_type,\n content_length: srcObj.content_length,\n etag,\n last_modified: now,\n metadata: { ...srcObj.metadata },\n });\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CopyObjectResult>\n <ETag>\"${etag}\"</ETag>\n <LastModified>${now}</LastModified>\n</CopyObjectResult>`;\n return awsXmlResponse(c, xml);\n }\n\n const body = await c.req.text();\n const contentType = c.req.header(\"Content-Type\") ?? \"application/octet-stream\";\n const etag = md5(body);\n\n // Extract user metadata (x-amz-meta-*)\n const metadata: Record<string, string> = {};\n for (const [headerName, headerValue] of Object.entries(c.req.header())) {\n if (typeof headerValue === \"string\" && headerName.toLowerCase().startsWith(\"x-amz-meta-\")) {\n metadata[headerName.slice(\"x-amz-meta-\".length)] = headerValue;\n }\n }\n\n const existing = aws()\n .s3Objects.findBy(\"bucket_name\", bucketName)\n .find((o) => o.key === key);\n\n if (existing) {\n aws().s3Objects.update(existing.id, {\n body,\n content_type: contentType,\n content_length: new TextEncoder().encode(body).byteLength,\n etag,\n last_modified: new Date().toISOString(),\n metadata,\n });\n } else {\n aws().s3Objects.insert({\n bucket_name: bucketName,\n key,\n body,\n content_type: contentType,\n content_length: new TextEncoder().encode(body).byteLength,\n etag,\n last_modified: new Date().toISOString(),\n metadata,\n });\n }\n\n return c.text(\"\", 200, { ETag: `\"${etag}\"` });\n });\n\n // GetObject - GET /s3/:bucket/:key{.+}\n app.get(\"/s3/:bucket/:key{.+}\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const key = c.req.param(\"key\");\n\n const bucket = aws().s3Buckets.findOneBy(\"bucket_name\", bucketName);\n if (!bucket) {\n return awsErrorXml(c, \"NoSuchBucket\", \"The specified bucket does not exist.\", 404);\n }\n\n const obj = aws()\n .s3Objects.findBy(\"bucket_name\", bucketName)\n .find((o) => o.key === key);\n\n if (!obj) {\n return awsErrorXml(c, \"NoSuchKey\", \"The specified key does not exist.\", 404);\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": obj.content_type,\n \"Content-Length\": String(obj.content_length),\n ETag: `\"${obj.etag}\"`,\n \"Last-Modified\": obj.last_modified,\n };\n for (const [k, v] of Object.entries(obj.metadata)) {\n headers[`x-amz-meta-${k}`] = v;\n }\n\n return c.text(obj.body, 200, headers);\n });\n\n // HeadObject - HEAD /s3/:bucket/:key{.+}\n app.on(\"HEAD\", \"/s3/:bucket/:key{.+}\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const key = c.req.param(\"key\");\n\n const obj = aws()\n .s3Objects.findBy(\"bucket_name\", bucketName)\n .find((o) => o.key === key);\n\n if (!obj) {\n return c.text(\"\", 404);\n }\n\n return c.text(\"\", 200, {\n \"Content-Type\": obj.content_type,\n \"Content-Length\": String(obj.content_length),\n ETag: `\"${obj.etag}\"`,\n \"Last-Modified\": obj.last_modified,\n });\n });\n\n // DeleteObject - DELETE /s3/:bucket/:key{.+}\n app.delete(\"/s3/:bucket/:key{.+}\", (c) => {\n const bucketName = c.req.param(\"bucket\");\n const key = c.req.param(\"key\");\n\n const obj = aws()\n .s3Objects.findBy(\"bucket_name\", bucketName)\n .find((o) => o.key === key);\n\n if (obj) {\n aws().s3Objects.delete(obj.id);\n }\n\n // S3 returns 204 even if the key doesn't exist\n return c.body(null, 204);\n });\n\n}\n\n","import type { RouteContext } from \"@emulators/core\";\nimport type { Context } from \"hono\";\nimport { getAwsStore } from \"../store.js\";\nimport { awsXmlResponse, awsErrorXml, generateMessageId, generateReceiptHandle, md5, getAccountId, parseQueryString, escapeXml } from \"../helpers.js\";\n\nexport function sqsRoutes(ctx: RouteContext): void {\n const { app, store, baseUrl } = ctx;\n const aws = () => getAwsStore(store);\n const accountId = getAccountId();\n\n // All SQS actions go through POST with Action parameter\n app.post(\"/sqs/\", async (c) => {\n const body = await c.req.text();\n const params = parseQueryString(body);\n const action = params[\"Action\"] ?? c.req.query(\"Action\") ?? \"\";\n\n switch (action) {\n case \"CreateQueue\":\n return createQueue(c, params);\n case \"DeleteQueue\":\n return deleteQueue(c, params);\n case \"ListQueues\":\n return listQueues(c, params);\n case \"GetQueueUrl\":\n return getQueueUrl(c, params);\n case \"GetQueueAttributes\":\n return getQueueAttributes(c, params);\n case \"SendMessage\":\n return sendMessage(c, params);\n case \"ReceiveMessage\":\n return receiveMessage(c, params);\n case \"DeleteMessage\":\n return deleteMessage(c, params);\n case \"PurgeQueue\":\n return purgeQueue(c, params);\n default:\n return awsErrorXml(c, \"InvalidAction\", `The action ${action} is not valid for this endpoint.`, 400);\n }\n });\n\n function createQueue(c: Context, params: Record<string, string>) {\n const queueName = params[\"QueueName\"] ?? \"\";\n if (!queueName) {\n return awsErrorXml(c, \"MissingParameter\", \"The request must contain the parameter QueueName.\", 400);\n }\n\n const existing = aws().sqsQueues.findOneBy(\"queue_name\", queueName);\n if (existing) {\n // SQS returns success with existing queue URL if attributes match\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreateQueueResponse>\n <CreateQueueResult>\n <QueueUrl>${escapeXml(existing.queue_url)}</QueueUrl>\n </CreateQueueResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</CreateQueueResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n const fifo = queueName.endsWith(\".fifo\");\n const queueUrl = `${baseUrl}/sqs/${accountId}/${queueName}`;\n const arn = `arn:aws:sqs:us-east-1:${accountId}:${queueName}`;\n\n // Parse numbered Attribute.N.Name / Attribute.N.Value pairs\n const attrs: Record<string, string> = {};\n for (let i = 1; params[`Attribute.${i}.Name`]; i++) {\n attrs[params[`Attribute.${i}.Name`]] = params[`Attribute.${i}.Value`] ?? \"\";\n }\n\n aws().sqsQueues.insert({\n queue_name: queueName,\n queue_url: queueUrl,\n arn,\n visibility_timeout: parseInt(attrs[\"VisibilityTimeout\"] ?? \"30\", 10),\n delay_seconds: parseInt(attrs[\"DelaySeconds\"] ?? \"0\", 10),\n max_message_size: parseInt(attrs[\"MaximumMessageSize\"] ?? \"262144\", 10),\n message_retention_period: parseInt(attrs[\"MessageRetentionPeriod\"] ?? \"345600\", 10),\n receive_message_wait_time: parseInt(attrs[\"ReceiveMessageWaitTimeSeconds\"] ?? \"0\", 10),\n fifo,\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreateQueueResponse>\n <CreateQueueResult>\n <QueueUrl>${escapeXml(queueUrl)}</QueueUrl>\n </CreateQueueResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</CreateQueueResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function deleteQueue(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n // Delete all messages in the queue\n const messages = aws().sqsMessages.findBy(\"queue_name\", queue.queue_name);\n for (const msg of messages) {\n aws().sqsMessages.delete(msg.id);\n }\n aws().sqsQueues.delete(queue.id);\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<DeleteQueueResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</DeleteQueueResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function listQueues(c: Context, params: Record<string, string>) {\n const prefix = params[\"QueueNamePrefix\"] ?? \"\";\n let queues = aws().sqsQueues.all();\n if (prefix) {\n queues = queues.filter((q) => q.queue_name.startsWith(prefix));\n }\n\n const queueUrlsXml = queues.map((q) => ` <QueueUrl>${escapeXml(q.queue_url)}</QueueUrl>`).join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListQueuesResponse>\n <ListQueuesResult>\n${queueUrlsXml}\n </ListQueuesResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</ListQueuesResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function getQueueUrl(c: Context, params: Record<string, string>) {\n const queueName = params[\"QueueName\"] ?? \"\";\n const queue = aws().sqsQueues.findOneBy(\"queue_name\", queueName);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetQueueUrlResponse>\n <GetQueueUrlResult>\n <QueueUrl>${escapeXml(queue.queue_url)}</QueueUrl>\n </GetQueueUrlResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</GetQueueUrlResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function getQueueAttributes(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n const messages = aws().sqsMessages.findBy(\"queue_name\", queue.queue_name);\n const now = Date.now();\n const visibleCount = messages.filter((m) => m.visible_after <= now).length;\n const inFlightCount = messages.filter((m) => m.visible_after > now).length;\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetQueueAttributesResponse>\n <GetQueueAttributesResult>\n <Attribute><Name>QueueArn</Name><Value>${queue.arn}</Value></Attribute>\n <Attribute><Name>ApproximateNumberOfMessages</Name><Value>${visibleCount}</Value></Attribute>\n <Attribute><Name>ApproximateNumberOfMessagesNotVisible</Name><Value>${inFlightCount}</Value></Attribute>\n <Attribute><Name>VisibilityTimeout</Name><Value>${queue.visibility_timeout}</Value></Attribute>\n <Attribute><Name>MaximumMessageSize</Name><Value>${queue.max_message_size}</Value></Attribute>\n <Attribute><Name>MessageRetentionPeriod</Name><Value>${queue.message_retention_period}</Value></Attribute>\n <Attribute><Name>DelaySeconds</Name><Value>${queue.delay_seconds}</Value></Attribute>\n <Attribute><Name>ReceiveMessageWaitTimeSeconds</Name><Value>${queue.receive_message_wait_time}</Value></Attribute>\n <Attribute><Name>FifoQueue</Name><Value>${queue.fifo}</Value></Attribute>\n </GetQueueAttributesResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</GetQueueAttributesResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function sendMessage(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const messageBody = params[\"MessageBody\"] ?? \"\";\n\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n if (!messageBody) {\n return awsErrorXml(c, \"MissingParameter\", \"The request must contain the parameter MessageBody.\", 400);\n }\n\n const bodyBytes = new TextEncoder().encode(messageBody).byteLength;\n if (bodyBytes > queue.max_message_size) {\n return awsErrorXml(c, \"InvalidParameterValue\", `One or more parameters are invalid. Reason: Message must be shorter than ${queue.max_message_size} bytes.`, 400);\n }\n\n const messageId = generateMessageId();\n const bodyMd5 = md5(messageBody);\n const now = Date.now();\n\n // Parse message attributes\n const messageAttributes: Record<string, { DataType: string; StringValue?: string; BinaryValue?: string }> = {};\n let attrIndex = 1;\n while (params[`MessageAttribute.${attrIndex}.Name`]) {\n const name = params[`MessageAttribute.${attrIndex}.Name`];\n const dataType = params[`MessageAttribute.${attrIndex}.Value.DataType`] ?? \"String\";\n const stringValue = params[`MessageAttribute.${attrIndex}.Value.StringValue`];\n messageAttributes[name] = { DataType: dataType, StringValue: stringValue };\n attrIndex++;\n }\n\n aws().sqsMessages.insert({\n queue_name: queue.queue_name,\n message_id: messageId,\n receipt_handle: generateReceiptHandle(),\n body: messageBody,\n md5_of_body: bodyMd5,\n attributes: {\n SentTimestamp: String(now),\n ApproximateReceiveCount: \"0\",\n ApproximateFirstReceiveTimestamp: \"\",\n SenderId: getAccountId(),\n },\n message_attributes: messageAttributes,\n visible_after: now + queue.delay_seconds * 1000,\n sent_timestamp: now,\n receive_count: 0,\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SendMessageResponse>\n <SendMessageResult>\n <MessageId>${messageId}</MessageId>\n <MD5OfMessageBody>${bodyMd5}</MD5OfMessageBody>\n </SendMessageResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</SendMessageResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function receiveMessage(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const maxMessages = Math.min(parseInt(params[\"MaxNumberOfMessages\"] ?? \"1\", 10), 10);\n const visibilityTimeout = parseInt(params[\"VisibilityTimeout\"] ?? \"\", 10);\n\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n const now = Date.now();\n const timeout = isNaN(visibilityTimeout) ? queue.visibility_timeout : visibilityTimeout;\n const allMessages = aws().sqsMessages.findBy(\"queue_name\", queue.queue_name);\n const visible = allMessages.filter((m) => m.visible_after <= now);\n const batch = visible.slice(0, maxMessages);\n\n for (const msg of batch) {\n const newReceiptHandle = generateReceiptHandle();\n aws().sqsMessages.update(msg.id, {\n receipt_handle: newReceiptHandle,\n visible_after: now + timeout * 1000,\n receive_count: msg.receive_count + 1,\n });\n msg.receipt_handle = newReceiptHandle;\n msg.receive_count += 1;\n }\n\n const messagesXml = batch\n .map(\n (m) => ` <Message>\n <MessageId>${m.message_id}</MessageId>\n <ReceiptHandle>${m.receipt_handle}</ReceiptHandle>\n <MD5OfBody>${m.md5_of_body}</MD5OfBody>\n <Body>${escapeXml(m.body)}</Body>\n <Attribute><Name>SentTimestamp</Name><Value>${m.sent_timestamp}</Value></Attribute>\n <Attribute><Name>ApproximateReceiveCount</Name><Value>${m.receive_count}</Value></Attribute>\n <Attribute><Name>ApproximateFirstReceiveTimestamp</Name><Value>${m.sent_timestamp}</Value></Attribute>\n </Message>`,\n )\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ReceiveMessageResponse>\n <ReceiveMessageResult>\n${messagesXml}\n </ReceiveMessageResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</ReceiveMessageResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function deleteMessage(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const receiptHandle = params[\"ReceiptHandle\"] ?? \"\";\n\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n const messages = aws().sqsMessages.findBy(\"queue_name\", queue.queue_name);\n const msg = messages.find((m) => m.receipt_handle === receiptHandle);\n if (msg) {\n aws().sqsMessages.delete(msg.id);\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<DeleteMessageResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</DeleteMessageResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function purgeQueue(c: Context, params: Record<string, string>) {\n const queueUrl = params[\"QueueUrl\"] ?? \"\";\n const queue = aws().sqsQueues.findOneBy(\"queue_url\", queueUrl);\n if (!queue) {\n return awsErrorXml(c, \"AWS.SimpleQueueService.NonExistentQueue\", \"The specified queue does not exist.\", 400);\n }\n\n const messages = aws().sqsMessages.findBy(\"queue_name\", queue.queue_name);\n for (const msg of messages) {\n aws().sqsMessages.delete(msg.id);\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<PurgeQueueResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</PurgeQueueResponse>`;\n return awsXmlResponse(c, xml);\n }\n}\n\n","import type { RouteContext } from \"@emulators/core\";\nimport type { Context } from \"hono\";\nimport { getAwsStore } from \"../store.js\";\nimport { awsXmlResponse, awsErrorXml, generateAwsId, generateMessageId, getAccountId, parseQueryString, escapeXml } from \"../helpers.js\";\nimport { randomBytes } from \"crypto\";\n\nexport function iamRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const aws = () => getAwsStore(store);\n const accountId = getAccountId();\n\n // IAM actions via POST with Action parameter\n app.post(\"/iam/\", async (c) => {\n const body = await c.req.text();\n const params = parseQueryString(body);\n const action = params[\"Action\"] ?? c.req.query(\"Action\") ?? \"\";\n\n switch (action) {\n case \"CreateUser\":\n return createUser(c, params);\n case \"GetUser\":\n return getUser(c, params);\n case \"DeleteUser\":\n return deleteUser(c, params);\n case \"ListUsers\":\n return listUsers(c);\n case \"CreateAccessKey\":\n return createAccessKey(c, params);\n case \"ListAccessKeys\":\n return listAccessKeys(c, params);\n case \"DeleteAccessKey\":\n return deleteAccessKey(c, params);\n case \"CreateRole\":\n return createRole(c, params);\n case \"GetRole\":\n return getRole(c, params);\n case \"DeleteRole\":\n return deleteRole(c, params);\n case \"ListRoles\":\n return listRoles(c);\n default:\n return awsErrorXml(c, \"InvalidAction\", `The action ${action} is not valid for this endpoint.`, 400);\n }\n });\n\n // STS endpoints\n app.post(\"/sts/\", async (c) => {\n const body = await c.req.text();\n const params = parseQueryString(body);\n const action = params[\"Action\"] ?? c.req.query(\"Action\") ?? \"\";\n\n switch (action) {\n case \"GetCallerIdentity\":\n return getCallerIdentity(c);\n case \"AssumeRole\":\n return assumeRole(c, params);\n default:\n return awsErrorXml(c, \"InvalidAction\", `The action ${action} is not valid for this endpoint.`, 400);\n }\n });\n\n function createUser(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n if (!userName) {\n return awsErrorXml(c, \"ValidationError\", \"The request must contain the parameter UserName.\", 400);\n }\n\n const existing = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (existing) {\n return awsErrorXml(c, \"EntityAlreadyExists\", `User with name ${escapeXml(userName)} already exists.`, 409);\n }\n\n const userId = generateAwsId(\"AIDA\");\n const path = params[\"Path\"] ?? \"/\";\n const arn = `arn:aws:iam::${accountId}:user${path}${userName}`;\n\n aws().iamUsers.insert({\n user_name: userName,\n user_id: userId,\n arn,\n path,\n access_keys: [],\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreateUserResponse>\n <CreateUserResult>\n <User>\n <Path>${escapeXml(path)}</Path>\n <UserName>${escapeXml(userName)}</UserName>\n <UserId>${userId}</UserId>\n <Arn>${escapeXml(arn)}</Arn>\n <CreateDate>${new Date().toISOString()}</CreateDate>\n </User>\n </CreateUserResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</CreateUserResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function getUser(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (!user) {\n return awsErrorXml(c, \"NoSuchEntity\", `The user with name ${escapeXml(userName)} cannot be found.`, 404);\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetUserResponse>\n <GetUserResult>\n <User>\n <Path>${escapeXml(user.path)}</Path>\n <UserName>${escapeXml(user.user_name)}</UserName>\n <UserId>${user.user_id}</UserId>\n <Arn>${escapeXml(user.arn)}</Arn>\n <CreateDate>${user.created_at}</CreateDate>\n </User>\n </GetUserResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</GetUserResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function deleteUser(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (!user) {\n return awsErrorXml(c, \"NoSuchEntity\", `The user with name ${escapeXml(userName)} cannot be found.`, 404);\n }\n\n aws().iamUsers.delete(user.id);\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<DeleteUserResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</DeleteUserResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function listUsers(c: Context) {\n const users = aws().iamUsers.all();\n const usersXml = users\n .map(\n (u) => ` <member>\n <Path>${escapeXml(u.path)}</Path>\n <UserName>${escapeXml(u.user_name)}</UserName>\n <UserId>${u.user_id}</UserId>\n <Arn>${escapeXml(u.arn)}</Arn>\n <CreateDate>${u.created_at}</CreateDate>\n </member>`,\n )\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListUsersResponse>\n <ListUsersResult>\n <IsTruncated>false</IsTruncated>\n <Users>\n${usersXml}\n </Users>\n </ListUsersResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</ListUsersResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function createAccessKey(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (!user) {\n return awsErrorXml(c, \"NoSuchEntity\", `The user with name ${escapeXml(userName)} cannot be found.`, 404);\n }\n\n const accessKeyId = \"AKIA\" + randomBytes(8).toString(\"hex\").toUpperCase();\n const secretAccessKey = randomBytes(30).toString(\"base64\");\n\n const keys = [...user.access_keys, { access_key_id: accessKeyId, secret_access_key: secretAccessKey, status: \"Active\" as const }];\n aws().iamUsers.update(user.id, { access_keys: keys });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreateAccessKeyResponse>\n <CreateAccessKeyResult>\n <AccessKey>\n <UserName>${escapeXml(userName)}</UserName>\n <AccessKeyId>${accessKeyId}</AccessKeyId>\n <Status>Active</Status>\n <SecretAccessKey>${secretAccessKey}</SecretAccessKey>\n <CreateDate>${new Date().toISOString()}</CreateDate>\n </AccessKey>\n </CreateAccessKeyResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</CreateAccessKeyResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function listAccessKeys(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (!user) {\n return awsErrorXml(c, \"NoSuchEntity\", `The user with name ${escapeXml(userName)} cannot be found.`, 404);\n }\n\n const keysXml = user.access_keys\n .map(\n (k) => ` <member>\n <UserName>${escapeXml(userName)}</UserName>\n <AccessKeyId>${k.access_key_id}</AccessKeyId>\n <Status>${k.status}</Status>\n </member>`,\n )\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListAccessKeysResponse>\n <ListAccessKeysResult>\n <IsTruncated>false</IsTruncated>\n <AccessKeyMetadata>\n${keysXml}\n </AccessKeyMetadata>\n </ListAccessKeysResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</ListAccessKeysResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function deleteAccessKey(c: Context, params: Record<string, string>) {\n const userName = params[\"UserName\"] ?? \"\";\n const accessKeyId = params[\"AccessKeyId\"] ?? \"\";\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n if (!user) {\n return awsErrorXml(c, \"NoSuchEntity\", `The user with name ${escapeXml(userName)} cannot be found.`, 404);\n }\n\n const keys = user.access_keys.filter((k) => k.access_key_id !== accessKeyId);\n aws().iamUsers.update(user.id, { access_keys: keys });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<DeleteAccessKeyResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</DeleteAccessKeyResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function createRole(c: Context, params: Record<string, string>) {\n const roleName = params[\"RoleName\"] ?? \"\";\n if (!roleName) {\n return awsErrorXml(c, \"ValidationError\", \"The request must contain the parameter RoleName.\", 400);\n }\n\n const existing = aws().iamRoles.findOneBy(\"role_name\", roleName);\n if (existing) {\n return awsErrorXml(c, \"EntityAlreadyExists\", `Role with name ${escapeXml(roleName)} already exists.`, 409);\n }\n\n const roleId = generateAwsId(\"AROA\");\n const path = params[\"Path\"] ?? \"/\";\n const arn = `arn:aws:iam::${accountId}:role${path}${roleName}`;\n const assumeRolePolicy = params[\"AssumeRolePolicyDocument\"] ?? \"{}\";\n const description = params[\"Description\"] ?? \"\";\n\n aws().iamRoles.insert({\n role_name: roleName,\n role_id: roleId,\n arn,\n path,\n assume_role_policy_document: assumeRolePolicy,\n description,\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CreateRoleResponse>\n <CreateRoleResult>\n <Role>\n <Path>${escapeXml(path)}</Path>\n <RoleName>${escapeXml(roleName)}</RoleName>\n <RoleId>${roleId}</RoleId>\n <Arn>${escapeXml(arn)}</Arn>\n <CreateDate>${new Date().toISOString()}</CreateDate>\n <AssumeRolePolicyDocument>${encodeURIComponent(assumeRolePolicy)}</AssumeRolePolicyDocument>\n <Description>${escapeXml(description)}</Description>\n </Role>\n </CreateRoleResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</CreateRoleResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function getRole(c: Context, params: Record<string, string>) {\n const roleName = params[\"RoleName\"] ?? \"\";\n const role = aws().iamRoles.findOneBy(\"role_name\", roleName);\n if (!role) {\n return awsErrorXml(c, \"NoSuchEntity\", `The role with name ${escapeXml(roleName)} cannot be found.`, 404);\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetRoleResponse>\n <GetRoleResult>\n <Role>\n <Path>${escapeXml(role.path)}</Path>\n <RoleName>${escapeXml(role.role_name)}</RoleName>\n <RoleId>${role.role_id}</RoleId>\n <Arn>${escapeXml(role.arn)}</Arn>\n <CreateDate>${role.created_at}</CreateDate>\n <AssumeRolePolicyDocument>${encodeURIComponent(role.assume_role_policy_document)}</AssumeRolePolicyDocument>\n <Description>${escapeXml(role.description)}</Description>\n </Role>\n </GetRoleResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</GetRoleResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function deleteRole(c: Context, params: Record<string, string>) {\n const roleName = params[\"RoleName\"] ?? \"\";\n const role = aws().iamRoles.findOneBy(\"role_name\", roleName);\n if (!role) {\n return awsErrorXml(c, \"NoSuchEntity\", `The role with name ${escapeXml(roleName)} cannot be found.`, 404);\n }\n\n aws().iamRoles.delete(role.id);\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<DeleteRoleResponse>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</DeleteRoleResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function listRoles(c: Context) {\n const roles = aws().iamRoles.all();\n const rolesXml = roles\n .map(\n (r) => ` <member>\n <Path>${escapeXml(r.path)}</Path>\n <RoleName>${escapeXml(r.role_name)}</RoleName>\n <RoleId>${r.role_id}</RoleId>\n <Arn>${escapeXml(r.arn)}</Arn>\n <CreateDate>${r.created_at}</CreateDate>\n <Description>${escapeXml(r.description)}</Description>\n </member>`,\n )\n .join(\"\\n\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListRolesResponse>\n <ListRolesResult>\n <IsTruncated>false</IsTruncated>\n <Roles>\n${rolesXml}\n </Roles>\n </ListRolesResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</ListRolesResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function getCallerIdentity(c: Context) {\n const authUser = c.get(\"authUser\") as { login?: string } | undefined;\n const userName = authUser?.login ?? \"admin\";\n const arn = `arn:aws:iam::${accountId}:user/${userName}`;\n\n // Return stable UserId from the IAM store when available\n const user = aws().iamUsers.findOneBy(\"user_name\", userName);\n const userId = user?.user_id ?? generateAwsId(\"AIDA\");\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<GetCallerIdentityResponse>\n <GetCallerIdentityResult>\n <Arn>${escapeXml(arn)}</Arn>\n <UserId>${userId}</UserId>\n <Account>${accountId}</Account>\n </GetCallerIdentityResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</GetCallerIdentityResponse>`;\n return awsXmlResponse(c, xml);\n }\n\n function assumeRole(c: Context, params: Record<string, string>) {\n const roleArn = params[\"RoleArn\"] ?? \"\";\n const sessionName = params[\"RoleSessionName\"] ?? \"session\";\n\n // Find the role by ARN\n const role = aws().iamRoles.all().find((r) => r.arn === roleArn);\n if (!role) {\n return awsErrorXml(c, \"NoSuchEntity\", `The role specified cannot be found.`, 404);\n }\n\n const accessKeyId = \"ASIA\" + randomBytes(8).toString(\"hex\").toUpperCase();\n const secretAccessKey = randomBytes(30).toString(\"base64\");\n const sessionToken = randomBytes(64).toString(\"base64\");\n const expiration = new Date(Date.now() + 3600 * 1000).toISOString();\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<AssumeRoleResponse>\n <AssumeRoleResult>\n <Credentials>\n <AccessKeyId>${accessKeyId}</AccessKeyId>\n <SecretAccessKey>${secretAccessKey}</SecretAccessKey>\n <SessionToken>${sessionToken}</SessionToken>\n <Expiration>${expiration}</Expiration>\n </Credentials>\n <AssumedRoleUser>\n <Arn>${roleArn}/${sessionName}</Arn>\n <AssumedRoleId>${role.role_id}:${sessionName}</AssumedRoleId>\n </AssumedRoleUser>\n </AssumeRoleResult>\n <ResponseMetadata><RequestId>${generateMessageId()}</RequestId></ResponseMetadata>\n</AssumeRoleResponse>`;\n return awsXmlResponse(c, xml);\n }\n}\n","import type { RouteContext } from \"@emulators/core\";\nimport { getAwsStore } from \"../store.js\";\nimport { escapeXml } from \"../helpers.js\";\n\nexport function inspectorRoutes(ctx: RouteContext): void {\n const { app, store } = ctx;\n const aws = () => getAwsStore(store);\n\n app.get(\"/\", (c) => {\n const tab = c.req.query(\"tab\") ?? \"s3\";\n const s3Store = aws();\n\n const buckets = s3Store.s3Buckets.all();\n const queues = s3Store.sqsQueues.all();\n const users = s3Store.iamUsers.all();\n const roles = s3Store.iamRoles.all();\n\n let contentHtml = \"\";\n\n if (tab === \"s3\") {\n const rows = buckets\n .map((b) => {\n const objects = s3Store.s3Objects.findBy(\"bucket_name\", b.bucket_name);\n return `<tr>\n <td>${escapeXml(b.bucket_name)}</td>\n <td>${objects.length}</td>\n <td>${escapeXml(b.region)}</td>\n <td>${escapeXml(b.creation_date)}</td>\n </tr>`;\n })\n .join(\"\\n\");\n\n contentHtml = `\n <h2>S3 Buckets (${buckets.length})</h2>\n <table>\n <thead><tr><th>Bucket</th><th>Objects</th><th>Region</th><th>Created</th></tr></thead>\n <tbody>${rows || \"<tr><td colspan=\\\"4\\\">No buckets</td></tr>\"}</tbody>\n </table>`;\n\n // Show objects for each bucket\n for (const bucket of buckets) {\n const objects = s3Store.s3Objects.findBy(\"bucket_name\", bucket.bucket_name);\n if (objects.length > 0) {\n const objRows = objects\n .map(\n (o) => `<tr>\n <td>${escapeXml(o.key)}</td>\n <td>${o.content_length}</td>\n <td>${escapeXml(o.content_type)}</td>\n <td>${escapeXml(o.last_modified)}</td>\n </tr>`,\n )\n .join(\"\\n\");\n contentHtml += `\n <h3>${escapeXml(bucket.bucket_name)} objects</h3>\n <table>\n <thead><tr><th>Key</th><th>Size</th><th>Type</th><th>Last Modified</th></tr></thead>\n <tbody>${objRows}</tbody>\n </table>`;\n }\n }\n } else if (tab === \"sqs\") {\n const rows = queues\n .map((q) => {\n const messages = s3Store.sqsMessages.findBy(\"queue_name\", q.queue_name);\n return `<tr>\n <td>${escapeXml(q.queue_name)}</td>\n <td>${messages.length}</td>\n <td>${q.fifo ? \"Yes\" : \"No\"}</td>\n <td>${q.visibility_timeout}s</td>\n </tr>`;\n })\n .join(\"\\n\");\n\n contentHtml = `\n <h2>SQS Queues (${queues.length})</h2>\n <table>\n <thead><tr><th>Queue</th><th>Messages</th><th>FIFO</th><th>Visibility Timeout</th></tr></thead>\n <tbody>${rows || \"<tr><td colspan=\\\"4\\\">No queues</td></tr>\"}</tbody>\n </table>`;\n } else if (tab === \"iam\") {\n const userRows = users\n .map(\n (u) => `<tr>\n <td>${escapeXml(u.user_name)}</td>\n <td>${escapeXml(u.user_id)}</td>\n <td>${u.access_keys.length}</td>\n <td>${escapeXml(u.arn)}</td>\n </tr>`,\n )\n .join(\"\\n\");\n\n const roleRows = roles\n .map(\n (r) => `<tr>\n <td>${escapeXml(r.role_name)}</td>\n <td>${escapeXml(r.role_id)}</td>\n <td>${escapeXml(r.description)}</td>\n <td>${escapeXml(r.arn)}</td>\n </tr>`,\n )\n .join(\"\\n\");\n\n contentHtml = `\n <h2>IAM Users (${users.length})</h2>\n <table>\n <thead><tr><th>User</th><th>User ID</th><th>Access Keys</th><th>ARN</th></tr></thead>\n <tbody>${userRows || \"<tr><td colspan=\\\"4\\\">No users</td></tr>\"}</tbody>\n </table>\n <h2>IAM Roles (${roles.length})</h2>\n <table>\n <thead><tr><th>Role</th><th>Role ID</th><th>Description</th><th>ARN</th></tr></thead>\n <tbody>${roleRows || \"<tr><td colspan=\\\"4\\\">No roles</td></tr>\"}</tbody>\n </table>`;\n }\n\n const html = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <title>AWS Emulator - Inspector</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }\n .header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }\n .header h1 { margin: 0; font-size: 24px; }\n .badge { background: #ff9900; color: #fff; padding: 2px 8px; border-radius: 4px; font-size: 12px; }\n .tabs { display: flex; gap: 4px; margin-bottom: 20px; }\n .tabs a { padding: 8px 16px; border-radius: 6px 6px 0 0; text-decoration: none; color: #333; background: #e0e0e0; }\n .tabs a.active { background: #fff; font-weight: 600; }\n .content { background: #fff; border-radius: 8px; padding: 20px; }\n table { width: 100%; border-collapse: collapse; margin-bottom: 16px; }\n th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid #eee; }\n th { background: #f9f9f9; font-weight: 600; }\n h2 { margin-top: 0; }\n h3 { margin-top: 16px; color: #555; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>AWS Emulator</h1>\n <span class=\"badge\">Inspector</span>\n </div>\n <div class=\"tabs\">\n <a href=\"/?tab=s3\" class=\"${tab === \"s3\" ? \"active\" : \"\"}\">S3</a>\n <a href=\"/?tab=sqs\" class=\"${tab === \"sqs\" ? \"active\" : \"\"}\">SQS</a>\n <a href=\"/?tab=iam\" class=\"${tab === \"iam\" ? \"active\" : \"\"}\">IAM</a>\n </div>\n <div class=\"content\">\n ${contentHtml}\n </div>\n</body>\n</html>`;\n\n return c.html(html);\n });\n}\n","import type { Hono } from \"hono\";\nimport type { ServicePlugin, Store, WebhookDispatcher, TokenMap, AppEnv, RouteContext } from \"@emulators/core\";\nimport { getAwsStore } from \"./store.js\";\nimport { getAccountId, getDefaultRegion, generateAwsId } from \"./helpers.js\";\nimport { s3Routes } from \"./routes/s3.js\";\nimport { sqsRoutes } from \"./routes/sqs.js\";\nimport { iamRoutes } from \"./routes/iam.js\";\nimport { inspectorRoutes } from \"./routes/inspector.js\";\n\nexport { getAwsStore, type AwsStore } from \"./store.js\";\nexport * from \"./entities.js\";\n\nexport interface AwsSeedConfig {\n port?: number;\n region?: string;\n account_id?: string;\n s3?: {\n buckets?: Array<{\n name: string;\n region?: string;\n }>;\n };\n sqs?: {\n queues?: Array<{\n name: string;\n fifo?: boolean;\n visibility_timeout?: number;\n }>;\n };\n iam?: {\n users?: Array<{\n user_name: string;\n path?: string;\n create_access_key?: boolean;\n }>;\n roles?: Array<{\n role_name: string;\n path?: string;\n description?: string;\n assume_role_policy?: string;\n }>;\n };\n}\n\nfunction seedDefaults(store: Store, baseUrl: string): void {\n const aws = getAwsStore(store);\n const accountId = getAccountId();\n const region = getDefaultRegion();\n\n // Create a default S3 bucket\n aws.s3Buckets.insert({\n bucket_name: \"emulate-default\",\n region,\n creation_date: new Date().toISOString(),\n acl: \"private\",\n versioning_enabled: false,\n });\n\n // Create a default SQS queue\n const queueName = \"emulate-default-queue\";\n aws.sqsQueues.insert({\n queue_name: queueName,\n queue_url: `${baseUrl}/sqs/${accountId}/${queueName}`,\n arn: `arn:aws:sqs:${region}:${accountId}:${queueName}`,\n visibility_timeout: 30,\n delay_seconds: 0,\n max_message_size: 262144,\n message_retention_period: 345600,\n receive_message_wait_time: 0,\n fifo: false,\n });\n\n // Create a default IAM user\n const userId = generateAwsId(\"AIDA\");\n aws.iamUsers.insert({\n user_name: \"admin\",\n user_id: userId,\n arn: `arn:aws:iam::${accountId}:user/admin`,\n path: \"/\",\n access_keys: [\n {\n access_key_id: \"AKIAIOSFODNN7EXAMPLE\",\n secret_access_key: \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",\n status: \"Active\",\n },\n ],\n });\n}\n\nexport function seedFromConfig(store: Store, baseUrl: string, config: AwsSeedConfig): void {\n const aws = getAwsStore(store);\n const accountId = getAccountId();\n const region = config.region ?? getDefaultRegion();\n\n if (config.s3?.buckets) {\n for (const b of config.s3.buckets) {\n const existing = aws.s3Buckets.findOneBy(\"bucket_name\", b.name);\n if (existing) continue;\n\n aws.s3Buckets.insert({\n bucket_name: b.name,\n region: b.region ?? region,\n creation_date: new Date().toISOString(),\n acl: \"private\",\n versioning_enabled: false,\n });\n }\n }\n\n if (config.sqs?.queues) {\n for (const q of config.sqs.queues) {\n const existing = aws.sqsQueues.findOneBy(\"queue_name\", q.name);\n if (existing) continue;\n\n const fifo = q.fifo ?? q.name.endsWith(\".fifo\");\n aws.sqsQueues.insert({\n queue_name: q.name,\n queue_url: `${baseUrl}/sqs/${accountId}/${q.name}`,\n arn: `arn:aws:sqs:${region}:${accountId}:${q.name}`,\n visibility_timeout: q.visibility_timeout ?? 30,\n delay_seconds: 0,\n max_message_size: 262144,\n message_retention_period: 345600,\n receive_message_wait_time: 0,\n fifo,\n });\n }\n }\n\n if (config.iam?.users) {\n for (const u of config.iam.users) {\n const existing = aws.iamUsers.findOneBy(\"user_name\", u.user_name);\n if (existing) continue;\n\n const userId = generateAwsId(\"AIDA\");\n const path = u.path ?? \"/\";\n const accessKeys = u.create_access_key\n ? [\n {\n access_key_id: \"AKIA\" + generateAwsId(\"\").slice(0, 16),\n secret_access_key: generateAwsId(\"\") + generateAwsId(\"\"),\n status: \"Active\" as const,\n },\n ]\n : [];\n\n aws.iamUsers.insert({\n user_name: u.user_name,\n user_id: userId,\n arn: `arn:aws:iam::${accountId}:user${path}${u.user_name}`,\n path,\n access_keys: accessKeys,\n });\n }\n }\n\n if (config.iam?.roles) {\n for (const r of config.iam.roles) {\n const existing = aws.iamRoles.findOneBy(\"role_name\", r.role_name);\n if (existing) continue;\n\n const roleId = generateAwsId(\"AROA\");\n const path = r.path ?? \"/\";\n\n aws.iamRoles.insert({\n role_name: r.role_name,\n role_id: roleId,\n arn: `arn:aws:iam::${accountId}:role${path}${r.role_name}`,\n path,\n assume_role_policy_document: r.assume_role_policy ?? \"{}\",\n description: r.description ?? \"\",\n });\n }\n }\n}\n\nexport const awsPlugin: ServicePlugin = {\n name: \"aws\",\n register(app: Hono<AppEnv>, store: Store, webhooks: WebhookDispatcher, baseUrl: string, tokenMap?: TokenMap): void {\n const ctx: RouteContext = { app, store, webhooks, baseUrl, tokenMap };\n s3Routes(ctx);\n sqsRoutes(ctx);\n iamRoutes(ctx);\n inspectorRoutes(ctx);\n },\n seed(store: Store, baseUrl: string): void {\n seedDefaults(store, baseUrl);\n },\n};\n\nexport default awsPlugin;\n"],"mappings":"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","names":["etag","existing","xml","randomBytes"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@emulators/aws",
3
+ "version": "0.3.0",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "homepage": "https://emulate.dev",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/vercel-labs/emulate.git",
18
+ "directory": "packages/@emulators/aws"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/vercel-labs/emulate/issues"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "dependencies": {
30
+ "hono": "^4",
31
+ "@emulators/core": "0.3.0"
32
+ },
33
+ "devDependencies": {
34
+ "tsup": "^8",
35
+ "typescript": "^5.7",
36
+ "vitest": "^4.1.0"
37
+ },
38
+ "scripts": {
39
+ "build": "tsup --clean",
40
+ "dev": "tsup --watch",
41
+ "test": "vitest run",
42
+ "clean": "rm -rf dist .turbo"
43
+ }
44
+ }