{"version":3,"sources":["../src/store.ts","../src/setup.ts","../src/index.ts"],"sourcesContent":["import { S3mini } from 's3mini';\nimport { serializeStoreValue, deserializeStoreValue } from '@walkeros/core';\nimport type { Store } from '@walkeros/core';\nimport type { S3StoreSettings, Types } from './types';\n\nfunction isValidKey(key: string): boolean {\n  if (!key || key.startsWith('/') || key.startsWith('\\\\')) return false;\n  return !key.split(/[/\\\\]/).includes('..');\n}\n\nconst JSON_CONTENT_TYPE = 'application/json';\nconst DEFAULT_CONTENT_TYPE = 'application/octet-stream';\n\n// Minimal extension to content-type map for the file-mode asset-serving use\n// case (serving walker.js and friends back with a correct mime). Anything not\n// listed falls back to application/octet-stream.\nconst MIME_BY_EXT: Readonly<Record<string, string>> = {\n  js: 'application/javascript',\n  mjs: 'application/javascript',\n  json: 'application/json',\n  css: 'text/css',\n  html: 'text/html',\n  txt: 'text/plain',\n  svg: 'image/svg+xml',\n  png: 'image/png',\n  jpg: 'image/jpeg',\n  jpeg: 'image/jpeg',\n  gif: 'image/gif',\n  webp: 'image/webp',\n  ico: 'image/x-icon',\n  wasm: 'application/wasm',\n  map: 'application/json',\n};\n\nfunction mimeFromKey(key: string): string {\n  const dot = key.lastIndexOf('.');\n  if (dot < 0 || dot === key.length - 1) return DEFAULT_CONTENT_TYPE;\n  const ext = key.slice(dot + 1).toLowerCase();\n  return MIME_BY_EXT[ext] ?? DEFAULT_CONTENT_TYPE;\n}\n\nfunction normalizePrefix(prefix?: string): string {\n  if (!prefix) return '';\n  const trimmed = prefix.replace(/^\\/+|\\/+$/g, '');\n  return trimmed ? trimmed + '/' : '';\n}\n\nfunction buildEndpoint(endpoint: string, bucket: string): string {\n  const base = endpoint.replace(/\\/+$/, '');\n  return `${base}/${bucket}`;\n}\n\nfunction assertSettings(\n  settings: Partial<S3StoreSettings> | undefined,\n): asserts settings is S3StoreSettings {\n  if (\n    !settings ||\n    typeof settings.bucket !== 'string' ||\n    settings.bucket.length === 0\n  ) {\n    throw new Error(\n      'storeS3Init: settings.bucket is required (non-empty string)',\n    );\n  }\n  if (typeof settings.endpoint !== 'string' || settings.endpoint.length === 0) {\n    throw new Error(\n      'storeS3Init: settings.endpoint is required (non-empty string)',\n    );\n  }\n  if (\n    typeof settings.accessKeyId !== 'string' ||\n    settings.accessKeyId.length === 0\n  ) {\n    throw new Error(\n      'storeS3Init: settings.accessKeyId is required (non-empty string)',\n    );\n  }\n  if (\n    typeof settings.secretAccessKey !== 'string' ||\n    settings.secretAccessKey.length === 0\n  ) {\n    throw new Error(\n      'storeS3Init: settings.secretAccessKey is required (non-empty string)',\n    );\n  }\n}\n\nexport const storeS3Init: Store.Init<Types> = async (context) => {\n  assertSettings(context.config.settings);\n  const settings = context.config.settings;\n  const prefix = normalizePrefix(settings.prefix);\n  // One mode per instance, decided at init. file:true persists raw bytes\n  // byte-exact with a real mime; structured mode round-trips StoreValue\n  // through the shared core codec, stored as application/json.\n  const fileMode = context.config.file === true;\n\n  const client = new S3mini({\n    endpoint: buildEndpoint(settings.endpoint, settings.bucket),\n    accessKeyId: settings.accessKeyId,\n    secretAccessKey: settings.secretAccessKey,\n    region: settings.region || 'auto',\n  });\n\n  function resolveKey(key: string): string | undefined {\n    if (!isValidKey(key)) {\n      context.logger.warn('Invalid key rejected', { key });\n      return undefined;\n    }\n    return prefix + key;\n  }\n\n  // Hard-fail with an actionable message if the bucket is missing.\n  // Mirrors the BigQuery init-time hard-fail pattern.\n  const exists = await client.bucketExists();\n  if (!exists) {\n    const setupId = context.id ?? 's3';\n    const errorMsg =\n      `S3 bucket not found: ${settings.bucket} at ${settings.endpoint}. ` +\n      `Run \"walkeros setup store.${setupId}\" to create it.`;\n    context.logger.error(errorMsg, {\n      bucket: settings.bucket,\n      endpoint: settings.endpoint,\n    });\n    throw new Error(errorMsg);\n  }\n\n  return {\n    type: 's3',\n    config: {\n      settings,\n      env: context.config.env,\n      id: context.config.id,\n      logger: context.config.logger,\n    },\n\n    async get(key: string): Promise<Store.StoreValue | undefined> {\n      const s3Key = resolveKey(key);\n      if (!s3Key) return undefined;\n\n      let bytes: Buffer;\n      try {\n        const arrayBuffer = await client.getObjectArrayBuffer(s3Key);\n        if (!arrayBuffer) return undefined;\n        bytes = Buffer.from(arrayBuffer);\n      } catch {\n        return undefined;\n      }\n      // File mode hands the raw bytes back untouched (Buffer is a Uint8Array,\n      // a valid StoreValue leaf). Structured mode decodes the utf8-JSON payload.\n      // A corrupt or empty payload (e.g. a 0-byte object) degrades to a miss\n      // rather than throwing a raw SyntaxError.\n      if (fileMode) return bytes;\n      try {\n        return deserializeStoreValue(bytes);\n      } catch (err) {\n        context.logger.debug('structured decode failed, degrading to miss', {\n          key,\n          error: err instanceof Error ? err.message : String(err),\n        });\n        return undefined;\n      }\n    },\n\n    async set(key: string, value: Store.StoreValue): Promise<void> {\n      const s3Key = resolveKey(key);\n      if (!s3Key) return;\n\n      if (fileMode) {\n        // Byte-exact passthrough: accept Uint8Array (Buffer included) or string.\n        if (!(value instanceof Uint8Array) && typeof value !== 'string') {\n          throw new Error(\n            'storeS3Init.set: in file mode value must be Uint8Array or string; got ' +\n              typeof value,\n          );\n        }\n        await client.putObject(s3Key, value, mimeFromKey(key));\n        return;\n      }\n\n      // Structured mode: serialize to utf8-JSON bytes, stored as JSON.\n      await client.putObject(\n        s3Key,\n        serializeStoreValue(value),\n        JSON_CONTENT_TYPE,\n      );\n    },\n\n    async delete(key: string): Promise<void> {\n      const s3Key = resolveKey(key);\n      if (!s3Key) return;\n\n      try {\n        await client.deleteObject(s3Key);\n      } catch {\n        /* S3 delete is idempotent */\n      }\n    },\n  };\n};\n","import { S3mini } from 's3mini';\nimport type { LifecycleContext, SetupFn, Store } from '@walkeros/core';\nimport { resolveSetup } from '@walkeros/core';\nimport type { S3StoreSettings, S3StoreSetup, Types } from './types';\n\n/**\n * Default setup options. EU region by default per AGENT.md.\n */\nexport const DEFAULT_SETUP: Required<S3StoreSetup> = {\n  region: 'eu-central-1',\n};\n\nexport interface SetupResult {\n  bucketCreated: boolean;\n}\n\n/**\n * Public alias kept for callers that imported the prior shape.\n * Equivalent to the framework's `Store.Config<Types>`.\n */\nexport type S3StoreConfig = Store.Config<Types>;\n\n/**\n * Provision the S3 bucket described in the flow config. Idempotent. Triggered\n * only by the explicit `walkeros setup store.<id>` CLI command.\n *\n * Variant B: only the bucket is created. Encryption, public-access block,\n * versioning, lifecycle rules, and tags are not applied here because `s3mini`\n * does not expose the relevant API operations. Configure those once via the\n * AWS Console or `aws s3api`.\n */\nexport const setup: SetupFn<S3StoreConfig, Store.BaseEnv> = async (\n  context: LifecycleContext<S3StoreConfig, Store.BaseEnv>,\n) => {\n  const { config, logger } = context;\n\n  const options = resolveSetup(config.setup, DEFAULT_SETUP);\n  if (!options) {\n    logger.debug('setup: skipped (config.setup is false or unset)');\n    return;\n  }\n\n  assertS3Settings(config.settings);\n  const settings = config.settings;\n\n  // Region resolution per Open Question #4 (iii):\n  // - explicit setup.region wins\n  // - else fall back to settings.region when concrete (not 'auto')\n  // - else default eu-central-1\n  const explicitSetupRegion = readExplicitRegion(config.setup);\n  const region = resolveRegion(explicitSetupRegion, settings.region);\n  void options; // resolveSetup applies defaults; explicit branch handled separately\n\n  const client = new S3mini({\n    endpoint: buildEndpoint(settings.endpoint, settings.bucket),\n    accessKeyId: settings.accessKeyId,\n    secretAccessKey: settings.secretAccessKey,\n    region,\n  });\n\n  const exists = await client.bucketExists();\n  if (exists) {\n    logger.debug('setup: bucket exists', { bucket: settings.bucket });\n    return { bucketCreated: false };\n  }\n\n  try {\n    await client.createBucket();\n    logger.info('setup: bucket created', {\n      bucket: settings.bucket,\n      region,\n    });\n    return { bucketCreated: true };\n  } catch (err: unknown) {\n    if (isAlreadyOwnedByYou(err)) {\n      logger.debug('setup: bucket created concurrently (race)', {\n        bucket: settings.bucket,\n      });\n      return { bucketCreated: false };\n    }\n    if (isAlreadyExistsDifferentOwner(err)) {\n      throw new Error(\n        `S3 bucket name \"${settings.bucket}\" is already in use by another AWS account. ` +\n          `Choose a different bucket name in settings.bucket.`,\n      );\n    }\n    throw err;\n  }\n};\n\nfunction resolveRegion(\n  explicitSetupRegion: string | undefined,\n  settingsRegion: string | undefined,\n): string {\n  if (\n    typeof explicitSetupRegion === 'string' &&\n    explicitSetupRegion.length > 0\n  ) {\n    return explicitSetupRegion;\n  }\n  if (\n    typeof settingsRegion === 'string' &&\n    settingsRegion.length > 0 &&\n    settingsRegion !== 'auto'\n  ) {\n    return settingsRegion;\n  }\n  return DEFAULT_SETUP.region;\n}\n\nfunction readExplicitRegion(raw: S3StoreConfig['setup']): string | undefined {\n  if (!isRecord(raw)) return undefined;\n  const value = raw.region;\n  return typeof value === 'string' ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null;\n}\n\nfunction assertS3Settings(\n  settings: Partial<S3StoreSettings> | undefined,\n): asserts settings is S3StoreSettings {\n  if (\n    !settings ||\n    typeof settings.bucket !== 'string' ||\n    settings.bucket.length === 0\n  ) {\n    throw new Error('setup: settings.bucket is required (non-empty string)');\n  }\n  if (typeof settings.endpoint !== 'string' || settings.endpoint.length === 0) {\n    throw new Error('setup: settings.endpoint is required (non-empty string)');\n  }\n  if (\n    typeof settings.accessKeyId !== 'string' ||\n    settings.accessKeyId.length === 0\n  ) {\n    throw new Error(\n      'setup: settings.accessKeyId is required (non-empty string)',\n    );\n  }\n  if (\n    typeof settings.secretAccessKey !== 'string' ||\n    settings.secretAccessKey.length === 0\n  ) {\n    throw new Error(\n      'setup: settings.secretAccessKey is required (non-empty string)',\n    );\n  }\n}\n\nfunction buildEndpoint(endpoint: string, bucket: string): string {\n  const base = endpoint.replace(/\\/+$/, '');\n  return `${base}/${bucket}`;\n}\n\nfunction isAlreadyOwnedByYou(err: unknown): boolean {\n  return hasErrorCode(err, 'BucketAlreadyOwnedByYou');\n}\n\nfunction isAlreadyExistsDifferentOwner(err: unknown): boolean {\n  return hasErrorCode(err, 'BucketAlreadyExists');\n}\n\nfunction hasErrorCode(err: unknown, code: string): boolean {\n  if (typeof err !== 'object' || err === null) return false;\n  const obj: {\n    code?: unknown;\n    Code?: unknown;\n    name?: unknown;\n    serviceCode?: unknown;\n  } = err;\n  return (\n    obj.code === code ||\n    obj.Code === code ||\n    obj.name === code ||\n    obj.serviceCode === code\n  );\n}\n","import type { Store, SetupFn } from '@walkeros/core';\nimport { storeS3Init } from './store';\nimport { setup } from './setup';\nimport type { Types } from './types';\nimport type { S3StoreConfig } from './setup';\n\nexport { storeS3Init } from './store';\nexport { setup, DEFAULT_SETUP } from './setup';\nexport type { SetupResult, S3StoreConfig } from './setup';\nexport type {\n  S3StoreSettings,\n  S3StoreInitSettings,\n  S3StoreSetup,\n  Types,\n} from './types';\n\n/**\n * Default export shape for store packages. The CLI (`walkeros setup store.<id>`)\n * reads `default.setup` to find the lifecycle function; the collector reads\n * `default.init` (or the named export) to construct the runtime instance.\n *\n * Soft breaking change: callers using `import storeS3Init from '@walkeros/server-store-s3'`\n * (default import) must now call `.init` on the returned object. Named imports\n * (`import { storeS3Init }`) are unaffected.\n */\nexport interface StoreS3Module {\n  type: 's3';\n  init: Store.Init<Types>;\n  setup: SetupFn<S3StoreConfig, Store.BaseEnv>;\n}\n\nconst storeS3: StoreS3Module = {\n  type: 's3',\n  init: storeS3Init,\n  setup,\n};\n\nexport default storeS3;\n"],"mappings":"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","names":["S3mini","buildEndpoint"]}