Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt

Use this file to discover all available pages before exploring further.

OCI’s S3 Compatibility API accepts AWS Signature V4 against https://<namespace>.compat.objectstorage.<region>.oci.customer-oci.com. MIRAGE derives this endpoint from your namespace + region automatically. Credentials (bucket, namespace, region, customer secret key pair) are created the same way in both runtimes, see OCI Credentials.

Node (server-side)

pnpm add @struktoai/mirage-node
import { MountMode, OCIResource, Workspace } from '@struktoai/mirage-node'

const oci = new OCIResource({
  bucket: process.env.OCI_BUCKET!,
  namespace: process.env.OCI_NAMESPACE!,
  region: process.env.OCI_REGION!,
  accessKeyId: process.env.OCI_ACCESS_KEY_ID!,
  secretAccessKey: process.env.OCI_SECRET_ACCESS_KEY!,
})

const ws = new Workspace({ '/bucket/': oci }, { mode: MountMode.READ })
const res = await ws.execute('ls /bucket/')
console.log(res.stdoutText)

Browser (presigned URLs)

pnpm add @struktoai/mirage-browser
The browser OCIResource is secret-free, your backend signs each operation using your OCI customer secret keys and returns a URL. OCI’s S3-compat endpoint accepts AWS Signature V4, so @aws-sdk/s3-request-presigner works, pointed at the OCI endpoint.

1. Server: sign URLs with the OCI endpoint

import {
  CopyObjectCommand,
  DeleteObjectCommand,
  GetObjectCommand,
  HeadObjectCommand,
  ListObjectsV2Command,
  PutObjectCommand,
  S3Client,
} from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const NAMESPACE = process.env.OCI_NAMESPACE!
const REGION = process.env.OCI_REGION!

const client = new S3Client({
  region: REGION,
  endpoint: `https://${NAMESPACE}.compat.objectstorage.${REGION}.oci.customer-oci.com`,
  forcePathStyle: true,
  credentials: {
    accessKeyId: process.env.OCI_ACCESS_KEY_ID!,
    secretAccessKey: process.env.OCI_SECRET_ACCESS_KEY!,
  },
})
const BUCKET = process.env.OCI_BUCKET!

app.post('/presign/oci', async (req, res) => {
  const { path, op, opts } = req.body
  const key = path.replace(/^\/+/, '')
  const ttl = typeof opts?.ttlSec === 'number' ? opts.ttlSec : 300
  let cmd
  switch (op) {
    case 'GET':    cmd = new GetObjectCommand({ Bucket: BUCKET, Key: key }); break
    case 'PUT':    cmd = new PutObjectCommand({ Bucket: BUCKET, Key: key, ContentType: opts?.contentType }); break
    case 'HEAD':   cmd = new HeadObjectCommand({ Bucket: BUCKET, Key: key }); break
    case 'DELETE': cmd = new DeleteObjectCommand({ Bucket: BUCKET, Key: key }); break
    case 'LIST':   cmd = new ListObjectsV2Command({
      Bucket: BUCKET,
      Prefix: opts?.listPrefix,
      Delimiter: opts?.listDelimiter,
      ContinuationToken: opts?.listContinuationToken,
    }); break
    case 'COPY':   cmd = new CopyObjectCommand({
      Bucket: BUCKET,
      Key: key,
      CopySource: `${BUCKET}/${opts?.copySource}`,
    }); break
  }
  res.json({ url: await getSignedUrl(client, cmd, { expiresIn: ttl }) })
})
OCI requires path-style URLs (forcePathStyle: true), virtual-hosted style is not supported on the S3 Compatibility API.

2. Browser: wire it up

import { MountMode, OCIResource, Workspace } from '@struktoai/mirage-browser'

const oci = new OCIResource({
  bucket: 'my-oci-bucket',
  namespace: 'idsiqbdbcr4i',
  region: 'us-ashburn-1',
  presignedUrlProvider: async (path, op, opts) => {
    const r = await fetch('/presign/oci', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ path, op, opts }),
    })
    const { url } = await r.json()
    return url
  },
})

const ws = new Workspace({ '/bucket/': oci }, { mode: MountMode.READ })

3. CORS

OCI’s S3-compatibility endpoint ships with permissive default CORS rules that echo back whatever Origin the browser sends, so local dev typically “just works” without any bucket configuration. For production origins you can tighten the policy through the OCI Console (Bucket → Pre-Authenticated Requests / CORS) or via the native OCI CLI:
oci os bucket update --bucket-name $OCI_BUCKET \
  --namespace $OCI_NAMESPACE \
  --cors-rules '[{"allowedOrigins":["https://app.example.com"],"allowedMethods":["GET","PUT","HEAD","DELETE","POST"],"allowedHeaders":["*"],"exposedHeaders":["ETag","Content-Length","Content-Type","Last-Modified"],"maxAgeInSeconds":3000}]'
OCI’s CORS is not configurable via the S3-compat PutBucketCors call, the schema differs. Use the native OCI Console or CLI.
See Python OCI Setup for the equivalent Python wiring.