Skip to main content
Glama
provision-aws.ts3.66 kB
#!/usr/bin/env tsx import { writeFileSync, existsSync, appendFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3'; import { DynamoDBClient, CreateTableCommand, ResourceInUseException } from '@aws-sdk/client-dynamodb'; import { AWS_REGION } from '@/src/utils/aws-config'; function randSuffix() { return Math.floor(Math.random() * 1e9).toString(36); } const timestamp = new Date().toISOString().replace(/[-:TZ\.]/g, '').slice(0,14); async function ensureBucket(s3: S3Client, name: string){ try{ const input: any = { Bucket: name }; if (AWS_REGION !== 'us-east-1') { input.CreateBucketConfiguration = { LocationConstraint: AWS_REGION }; } await s3.send(new CreateBucketCommand(input)); return { created: true, name }; }catch(e:any){ const msg = String(e?.name||e?.message||e); if(msg.includes('BucketAlreadyOwnedByYou')) return { created:false, name }; if(msg.includes('BucketAlreadyExists')){ return { created:false, name: name+'-'+randSuffix() }; } throw e; } } async function ensureTable(ddb: DynamoDBClient, params: any){ try{ await ddb.send(new CreateTableCommand(params)); return { created:true, name: params.TableName }; } catch(e){ if(e instanceof ResourceInUseException){ return { created:false, name: params.TableName }; } throw e; } } (async()=>{ const s3 = new S3Client({ region: AWS_REGION }); const ddb = new DynamoDBClient({ region: AWS_REGION }); const suffix = `${timestamp}-${randSuffix()}`; let exportsBucket = `axion-exports-usw2-${suffix}`; let tilesBucket = `axion-tiles-usw2-${suffix}`; let boundariesBucket = `axion-boundaries-usw2-${suffix}`; const e = await ensureBucket(s3, exportsBucket); exportsBucket = e.name; const t = await ensureBucket(s3, tilesBucket); tilesBucket = t.name; const b = await ensureBucket(s3, boundariesBucket); boundariesBucket = b.name; // DynamoDB tables await ensureTable(ddb, { TableName: 'axion-sessions', AttributeDefinitions: [{AttributeName:'session_id',AttributeType:'S'}], KeySchema: [{AttributeName:'session_id',KeyType:'HASH'}], BillingMode: 'PAY_PER_REQUEST' }); await ensureTable(ddb, { TableName: 'axion-tasks', AttributeDefinitions: [{AttributeName:'task_id',AttributeType:'S'}], KeySchema: [{AttributeName:'task_id',KeyType:'HASH'}], BillingMode: 'PAY_PER_REQUEST' }); await ensureTable(ddb, { TableName: 'axion-boundaries', AttributeDefinitions: [ {AttributeName:'name',AttributeType:'S'}, {AttributeName:'level',AttributeType:'S'} ], KeySchema: [ {AttributeName:'name',KeyType:'HASH'}, {AttributeName:'level',KeyType:'RANGE'} ], BillingMode: 'PAY_PER_REQUEST' }); await ensureTable(ddb, { TableName: 'axion-cache', AttributeDefinitions: [{AttributeName:'cache_key',AttributeType:'S'}], KeySchema: [{AttributeName:'cache_key',KeyType:'HASH'}], BillingMode: 'PAY_PER_REQUEST' }); // Write .env.local const envPath = resolve(process.cwd(), '.env.local'); const lines = [ `AWS_REGION=${AWS_REGION}`, `AXION_S3_EXPORTS_BUCKET=${exportsBucket}`, `AXION_STAC_ENDPOINT=https://earth-search.aws.element84.com/v1` ].join('\n') + '\n'; if(!existsSync(envPath)) writeFileSync(envPath, lines); else appendFileSync(envPath, lines); // Output summary const summary = { region: AWS_REGION, exportsBucket, tilesBucket, boundariesBucket, tables: ['axion-sessions','axion-tasks','axion-boundaries','axion-cache'] }; console.log(JSON.stringify({ success:true, summary }, null, 2)); })();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dhenenjay/axion-planetary-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server