Spaces:
Running
Running
File size: 4,493 Bytes
be9292f aa00da8 be9292f aa00da8 be9292f aa00da8 be9292f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | /**
* AWS Configuration for Cognito-based S3 access
*
* This module handles AWS credentials through Cognito Identity Provider.
* No AWS credentials are stored in code or exposed to the client.
*
* Environment Variables Required:
* - VITE_AWS_REGION: AWS region (e.g., "us-east-2")
* - VITE_AWS_COGNITO_IDENTITY_POOL_ID: Cognito Identity Pool ID (e.g., "us-east-2:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
* - VITE_S3_BUCKET: Default S3 bucket name (e.g., "ddy-first-bucket")
*/
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity";
import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
export const AWS_REGION = import.meta.env.VITE_AWS_REGION || "us-east-2";
// Cognito pool ID is safe to embed in client code (not a secret)
export const COGNITO_IDENTITY_POOL_ID = import.meta.env.VITE_AWS_COGNITO_IDENTITY_POOL_ID || "us-east-2:1387102d-5a87-4742-8a69-1baa70f37984";
export const DEFAULT_BUCKET = import.meta.env.VITE_S3_BUCKET || "ddy-first-bucket";
/**
* Initialize S3 client with Cognito credentials
* Uses unauthenticated Cognito Identity pool for public S3 access
*/
export function getS3Client() {
const credentialsProvider = fromCognitoIdentityPool({
client: new CognitoIdentityClient({ region: AWS_REGION }),
identityPoolId: COGNITO_IDENTITY_POOL_ID,
});
return new S3Client({
region: AWS_REGION,
credentials: credentialsProvider,
});
}
/**
* Get S3 object as text (for JSON tilesets, metadata, etc.)
*/
export async function getS3ObjectAsText(bucket, key) {
const s3Client = getS3Client();
if (!s3Client) {
throw new Error("S3 client not initialized");
}
try {
const command = new GetObjectCommand({
Bucket: bucket,
Key: key,
});
const response = await s3Client.send(command);
const text = await response.Body.transformToString();
return text;
} catch (error) {
console.error(`Failed to fetch S3 object s3://${bucket}/${key}:`, error);
throw error;
}
}
/**
* Get S3 object as JSON
*/
export async function getS3ObjectAsJson(bucket, key) {
const text = await getS3ObjectAsText(bucket, key);
return JSON.parse(text);
}
/**
* Build a direct S3 URL for tile assets
* Note: This URL requires proper CORS configuration on S3 bucket
* or the bucket must be public with proper authentication
*/
export function buildS3Url(bucket, key) {
return `https://${bucket}.s3.${AWS_REGION}.amazonaws.com/${key}`;
}
/**
* Rewrite URLs in a tileset JSON to use proper S3 paths
* Handles both relative and absolute URLs
*/
export function rewriteTilesetUrls(tilesetJson, bucket, basePath) {
const rewrite = (obj) => {
if (!obj || typeof obj !== "object") return;
if (Array.isArray(obj)) {
obj.forEach(rewrite);
return;
}
Object.keys(obj).forEach((key) => {
const value = obj[key];
// Rewrite uri/url fields to point to S3
if ((key === "uri" || key === "url") && typeof value === "string") {
// Skip external URLs
if (value.startsWith("http://") || value.startsWith("https://")) {
return;
}
// Skip data URLs
if (value.startsWith("data:")) {
return;
}
// Build S3 URL for relative paths
const relativePath = value.startsWith("/") ? value.slice(1) : value;
const s3Key = basePath
? `${basePath}/${relativePath}`.replace(/\/+/g, "/")
: relativePath;
obj[key] = buildS3Url(bucket, s3Key);
}
// Recursively rewrite nested objects
if (typeof value === "object") {
rewrite(value);
}
});
};
rewrite(tilesetJson);
return tilesetJson;
}
/**
* Load a tileset JSON file from S3 and rewrite its URLs
*/
export async function loadTilesetFromS3(bucket, tilesetPath, basePath) {
try {
const tilesetJson = await getS3ObjectAsJson(bucket, tilesetPath);
return rewriteTilesetUrls(tilesetJson, bucket, basePath);
} catch (error) {
console.error(`Failed to load tileset from S3:`, error);
throw error;
}
}
/**
* Get default S3 bucket name
*/
export function getDefaultBucket() {
return DEFAULT_BUCKET;
}
/**
* Get AWS region
*/
export function getAwsRegion() {
return AWS_REGION;
}
/**
* Validate AWS configuration
*/
export function validateAwsConfig() {
return !!(AWS_REGION && COGNITO_IDENTITY_POOL_ID && DEFAULT_BUCKET);
}
|