mirror of
https://github.com/alexandernicholson/s3panoramic.git
synced 2026-03-31 09:07:11 +09:00
feature: update to deno 2 and initializeClient requirement
This commit is contained in:
parent
e99a065f77
commit
aff7414f57
@@ -1,5 +1,5 @@
|
|||||||
# Use the official Deno image
|
# Use the official Deno image
|
||||||
FROM denoland/deno:1.46.3
|
FROM denoland/deno:2.0.6
|
||||||
|
|
||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ListObjectsOptions, ListObjectsResult, StorageObject } from "../types/m
|
|||||||
import { S3, type ListObjectsV2Request } from "https://deno.land/x/aws_api@v0.8.1/services/s3/mod.ts";
|
import { S3, type ListObjectsV2Request } from "https://deno.land/x/aws_api@v0.8.1/services/s3/mod.ts";
|
||||||
import { ApiFactory } from "https://deno.land/x/aws_api@v0.8.1/client/mod.ts";
|
import { ApiFactory } from "https://deno.land/x/aws_api@v0.8.1/client/mod.ts";
|
||||||
import { getSignedUrl } from "https://deno.land/x/aws_s3_presign@2.2.1/mod.ts";
|
import { getSignedUrl } from "https://deno.land/x/aws_s3_presign@2.2.1/mod.ts";
|
||||||
|
import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.48/deno-dom-wasm.ts";
|
||||||
|
|
||||||
interface Credentials {
|
interface Credentials {
|
||||||
awsAccessKeyId: string;
|
awsAccessKeyId: string;
|
||||||
@@ -11,10 +12,14 @@ interface Credentials {
|
|||||||
|
|
||||||
export class StorageService {
|
export class StorageService {
|
||||||
private client: S3;
|
private client: S3;
|
||||||
private credentials: Credentials;
|
private credentials!: Credentials;
|
||||||
|
|
||||||
constructor(private bucket: string, private region: string) {
|
constructor(private bucket: string, private region: string) {
|
||||||
this.credentials = this.resolveCredentials();
|
this.initializeClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initializeClient() {
|
||||||
|
this.credentials = await this.resolveCredentials();
|
||||||
const factory = new ApiFactory({
|
const factory = new ApiFactory({
|
||||||
region: this.region,
|
region: this.region,
|
||||||
credentials: this.credentials,
|
credentials: this.credentials,
|
||||||
@@ -23,6 +28,13 @@ export class StorageService {
|
|||||||
this.client = new S3(factory);
|
this.client = new S3(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure any method that uses this.client waits for initialization
|
||||||
|
private async ensureInitialized() {
|
||||||
|
if (!this.client) {
|
||||||
|
await this.initializeClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async fetchInstanceProfileCredentials(): Promise<[Credentials | null, string | null]> {
|
private async fetchInstanceProfileCredentials(): Promise<[Credentials | null, string | null]> {
|
||||||
try {
|
try {
|
||||||
const metadataUrl = "http://169.254.169.254/latest/meta-data/iam/security-credentials/";
|
const metadataUrl = "http://169.254.169.254/latest/meta-data/iam/security-credentials/";
|
||||||
@@ -98,6 +110,7 @@ export class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getSignedUrl(key: string, expiresIn = 3600): Promise<string> {
|
async getSignedUrl(key: string, expiresIn = 3600): Promise<string> {
|
||||||
|
await this.ensureInitialized();
|
||||||
return await getSignedUrl({
|
return await getSignedUrl({
|
||||||
accessKeyId: this.credentials.awsAccessKeyId,
|
accessKeyId: this.credentials.awsAccessKeyId,
|
||||||
secretAccessKey: this.credentials.awsSecretKey,
|
secretAccessKey: this.credentials.awsSecretKey,
|
||||||
@@ -109,6 +122,7 @@ export class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async listObjects(options: ListObjectsOptions): Promise<ListObjectsResult> {
|
async listObjects(options: ListObjectsOptions): Promise<ListObjectsResult> {
|
||||||
|
await this.ensureInitialized();
|
||||||
try {
|
try {
|
||||||
const params: ListObjectsV2Request = {
|
const params: ListObjectsV2Request = {
|
||||||
Bucket: this.bucket,
|
Bucket: this.bucket,
|
||||||
@@ -160,10 +174,14 @@ export class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class WebIdentityCredentials {
|
class WebIdentityCredentials {
|
||||||
|
private parser: DOMParser;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private roleArn: string,
|
private roleArn: string,
|
||||||
private token: string,
|
private token: string,
|
||||||
) {}
|
) {
|
||||||
|
this.parser = new DOMParser();
|
||||||
|
}
|
||||||
|
|
||||||
async getCredentials(): Promise<{ accessKeyId: string; secretAccessKey: string; sessionToken: string }> {
|
async getCredentials(): Promise<{ accessKeyId: string; secretAccessKey: string; sessionToken: string }> {
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
@@ -183,15 +201,20 @@ class WebIdentityCredentials {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const xml = await response.text();
|
const xml = await response.text();
|
||||||
const result = new DOMParser().parseFromString(xml, "text/xml");
|
const result = this.parser.parseFromString(xml, "text/xml");
|
||||||
|
if (!result) throw new Error("Failed to parse XML response");
|
||||||
|
|
||||||
const credentials = result.querySelector("Credentials");
|
const credentials = result.querySelector("Credentials");
|
||||||
if (!credentials) throw new Error("No credentials in response");
|
if (!credentials) throw new Error("No credentials in response");
|
||||||
|
|
||||||
return {
|
const accessKeyId = credentials.querySelector("AccessKeyId")?.textContent;
|
||||||
accessKeyId: credentials.querySelector("AccessKeyId")?.textContent ?? "",
|
const secretAccessKey = credentials.querySelector("SecretAccessKey")?.textContent;
|
||||||
secretAccessKey: credentials.querySelector("SecretAccessKey")?.textContent ?? "",
|
const sessionToken = credentials.querySelector("SessionToken")?.textContent;
|
||||||
sessionToken: credentials.querySelector("SessionToken")?.textContent ?? "",
|
|
||||||
};
|
if (!accessKeyId || !secretAccessKey || !sessionToken) {
|
||||||
|
throw new Error("Missing required credential fields in response");
|
||||||
|
}
|
||||||
|
|
||||||
|
return { accessKeyId, secretAccessKey, sessionToken };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user