Skip to content

Commit

Permalink
feat(cloud-sdk): add url api to cloud sdk (#1732)
Browse files Browse the repository at this point in the history
* feat(cloud-sdk): add filename url api to cloud.storage.bucket

* update cloud sdk version in runtime

* chore: fix deprecated marker
  • Loading branch information
maslow authored Dec 12, 2023
1 parent ae9ff33 commit 2b87cb7
Show file tree
Hide file tree
Showing 5 changed files with 8,657 additions and 3,277 deletions.
4 changes: 2 additions & 2 deletions packages/cloud-sdk/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/cloud-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lafjs/cloud",
"version": "1.0.0-beta.13-storage-pr",
"version": "1.0.0-beta.13-storage-pr2",
"description": "The cloud sdk for laf cloud function",
"main": "dist/index.js",
"scripts": {
Expand Down
82 changes: 61 additions & 21 deletions packages/cloud-sdk/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export interface SdkStreamMixin {
transformToString: (encoding?: string) => Promise<string>
transformToWebStream: () => ReadableStream
}
/**

/**
* `ICloudStorage` is an interface for cloud storage services.
Expand All @@ -36,7 +35,29 @@ export class CloudStorage {
return process.env.APPID
}

protected getExternalClient() {
public get externalEndpoint() {
assert(
process.env.OSS_EXTERNAL_ENDPOINT,
'OSS_EXTERNAL_ENDPOINT is required'
)
return process.env.OSS_EXTERNAL_ENDPOINT
}

public get internalEndpoint() {
assert(
process.env.OSS_INTERNAL_ENDPOINT,
'OSS_INTERNAL_ENDPOINT is required'
)
return process.env.OSS_INTERNAL_ENDPOINT
}

/**
* Get external S3 client of `@aws-sdk/client-s3`.
* You can use this client to access the bucket through the external endpoint.
* @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
* @returns
*/
public getExternalS3Client() {
if (!this._externalS3Client) {
assert(
process.env.OSS_EXTERNAL_ENDPOINT,
Expand All @@ -60,7 +81,12 @@ export class CloudStorage {
return this._externalS3Client
}

protected getInternalClient() {
/**
* Get internal S3 client of `@aws-sdk/client-s3`.
* You can use this client to access the bucket through the internal endpoint.
* @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
*/
public getInternalS3Client() {
if (!this._internalS3Client) {
assert(
process.env.OSS_INTERNAL_ENDPOINT,
Expand All @@ -84,19 +110,9 @@ export class CloudStorage {
return this._internalS3Client
}

/**
* Get S3 client of `@aws-sdk/client-s3`, by default it returns the internal access client.
* @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
*/
public getS3Client(options: { external?: boolean } = { external: false }) {
return options.external
? this.getExternalClient()
: this.getInternalClient()
}

/**
* Get bucket by short name
* @param bucketShortName it is the short name of the bucket, e.g. `images`, NOT `{appid}-images`
* @param bucketShortName it is the short name of the bucket, e.g. `images`, NOT `{appid}-images`.
* @returns
*/
bucket(bucketShortName: string): CloudStorageBucket {
Expand All @@ -107,7 +123,7 @@ export class CloudStorage {
}

export class CloudStorageBucket {
readonly storage: CloudStorage
protected readonly storage: CloudStorage
readonly name: string

constructor(storage: CloudStorage, name: string) {
Expand All @@ -130,7 +146,7 @@ export class CloudStorageBucket {
options?: Omit<GetObjectCommandInput, 'Bucket' | 'Key'>
): Promise<NodeJsRuntimeStreamingBlobPayloadOutputTypes> {
assert(filename, 'filename is required')
const internal = this.storage.getS3Client()
const internal = this.storage.getInternalS3Client()

const args: GetObjectCommandInput = {
Bucket: this.name,
Expand All @@ -156,7 +172,7 @@ export class CloudStorageBucket {
) {
assert(filename, 'key is required')
assert(body, 'body is required')
const external = this.storage.getS3Client()
const external = this.storage.getInternalS3Client()

const args: PutObjectCommandInput = {
Bucket: this.name,
Expand All @@ -180,7 +196,7 @@ export class CloudStorageBucket {
options?: Omit<DeleteObjectCommandInput, 'Bucket' | 'Key'>
) {
assert(filename, 'filename is required')
const external = this.storage.getS3Client()
const external = this.storage.getInternalS3Client()

const args: DeleteObjectCommandInput = {
Bucket: this.name,
Expand All @@ -202,7 +218,7 @@ export class CloudStorageBucket {
prefix?: string,
options?: Omit<ListObjectsCommandInput, 'Bucket' | 'Prefix'>
) {
const internal = this.storage.getS3Client()
const internal = this.storage.getInternalS3Client()

const args: ListObjectsCommandInput = {
Bucket: this.name,
Expand All @@ -213,6 +229,30 @@ export class CloudStorageBucket {
return res
}

/**
* Get external url of the file.
* You can ONLY use this url to access file from `readonly` bucket or `public` bucket.
* Use `getDownloadUrl()` to get a signed url for `private` bucket.
* @param filename filename is the key of the object, it can contain subdirectories, e.g. `a/b/c.txt`
* @returns
*/
public externalUrl(filename: string) {
assert(filename, 'filename is required')
return `${this.storage.externalEndpoint}/${this.name}/${filename}`
}

/**
* Get internal url of the file.
* You can ONLY use this url to access file from `readonly` bucket or `public` bucket.
* Use `getDownloadUrl()` to get a signed url for `private` bucket.
* @param filename filename is the key of the object, it can contain subdirectories, e.g. `a/b/c.txt`
* @returns
*/
public internalUrl(filename: string) {
assert(filename, 'filename is required')
return `${this.storage.internalEndpoint}/${this.name}/${filename}`
}

/**
* Get upload url, you can use this url to upload file directly to bucket
* @param filename filename is the key of the object, it can contain subdirectories, e.g. `a/b/c.txt`
Expand All @@ -226,7 +266,7 @@ export class CloudStorageBucket {
options?: Omit<PutObjectCommandInput, 'Bucket' | 'Key'>
) {
assert(filename, 'filename is required')
const external = this.storage.getS3Client({ external: true })
const external = this.storage.getExternalS3Client()

const args = new PutObjectCommand({
Bucket: this.name,
Expand All @@ -251,7 +291,7 @@ export class CloudStorageBucket {
options?: Omit<GetObjectCommandInput, 'Bucket' | 'Key'>
) {
assert(filename, 'filename is required')
const external = this.storage.getS3Client({ external: true })
const external = this.storage.getExternalS3Client()

const args = new GetObjectCommand({
Bucket: this.name,
Expand Down
Loading

0 comments on commit 2b87cb7

Please sign in to comment.