Enable TS noImplicitAny in web (#31636)

GitOrigin-RevId: 18881694770f2476c475f8fef4c6a2678a2a12fe
This commit is contained in:
Anna Claire Fields
2026-03-27 09:05:30 +00:00
committed by Copybot
parent b3489a6792
commit 6113c6c291
58 changed files with 1423 additions and 281 deletions
@@ -21,7 +21,7 @@ const hkdf = promisify(Crypto.hkdf)
const AES256_KEY_LENGTH = 32
/**
* @typedef {Object} Settings
* @typedef {Object} EncryptionSettings
* @property {boolean} automaticallyRotateDEKEncryption
* @property {string} dataEncryptionKeyBucketName
* @property {boolean} ignoreErrorsFromDEKReEncryption
@@ -29,6 +29,26 @@ const AES256_KEY_LENGTH = 32
* @property {() => Promise<Array<RootKeyEncryptionKey>>} getRootKeyEncryptionKeys
*/
/**
* @typedef {Object} S3PersistorSettings
* @property {Object<string, import('@aws-sdk/client-s3').StorageClass>} [storageClass]
* @property {string} [key]
* @property {string} [secret]
* @property {string} [region]
* @property {string} [endpoint]
* @property {boolean} [pathStyle]
* @property {number} [maxRetries]
* @property {Object} [httpOptions]
* @property {string} [ca]
* @property {number} [signedUrlExpiryInMs]
* @property {number} [partSize]
* @property {Object<string, {auth_key: string, auth_secret: string}>} [bucketCreds]
*/
/**
* @typedef {S3PersistorSettings & EncryptionSettings} Settings
*/
/**
* @typedef {import('./types').ListDirectoryResult} ListDirectoryResult
*/
@@ -105,10 +125,6 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
})
}
async ensureKeyEncryptionKeysLoaded() {
await this.#availableKeyEncryptionKeysPromise
}
/**
* @param {string} bucketName
* @param {string} path
@@ -289,6 +305,13 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
}
}
/**
* @param {string} bucketName
* @param {string} path
* @param {NodeJS.ReadableStream} sourceStream
* @param {import('./S3Persistor.js').StreamOptions} opts
* @return {Promise<void>}
*/
async sendStream(bucketName, path, sourceStream, opts = {}) {
const ssecOptions =
opts.ssecOptions ||
@@ -299,6 +322,13 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
})
}
/**
* @param {string} bucketName
* @param {string} path
* @param {Object} opts
* @param {SSECOptions} [opts.ssecOptions]
* @return {Promise<NodeJS.ReadableStream>}
*/
async getObjectStream(bucketName, path, opts = {}) {
const ssecOptions =
opts.ssecOptions ||
@@ -309,6 +339,13 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
})
}
/**
* @param {string} bucketName
* @param {string} path
* @param {Object} opts
* @param {SSECOptions} [opts.ssecOptions]
* @return {Promise<number>}
*/
async getObjectSize(bucketName, path, opts = {}) {
const ssecOptions =
opts.ssecOptions ||
@@ -316,6 +353,13 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
return await super.getObjectSize(bucketName, path, { ...opts, ssecOptions })
}
/**
* @param {string} bucketName
* @param {string} path
* @param {Object} opts
* @param {SSECOptions} [opts.ssecOptions]
* @return {Promise<string | undefined>}
*/
async getObjectStorageClass(bucketName, path, opts = {}) {
const ssecOptions =
opts.ssecOptions ||
@@ -326,11 +370,23 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
})
}
/**
* @param {string} bucketName
* @param {string} path
* @param {string} [continuationToken]
* @return {Promise<number>}
*/
async directorySize(bucketName, path, continuationToken) {
// Note: Listing a bucket does not require SSE-C credentials.
return await super.directorySize(bucketName, path, continuationToken)
}
/**
* @param {string} bucketName
* @param {string} path
* @param {string} [continuationToken]
* @return {Promise<void>}
*/
async deleteDirectory(bucketName, path, continuationToken) {
// Let [Settings.pathToProjectFolder] validate the project path before deleting things.
const { projectFolder, dekPath } = this.#buildProjectPaths(bucketName, path)
@@ -344,12 +400,27 @@ class PerProjectEncryptedS3Persistor extends S3Persistor {
}
}
/**
* @param {string} bucketName
* @param {string} path
* @param {Object} opts
* @return {Promise<string>}
*/
async getObjectMd5Hash(bucketName, path, opts = {}) {
// The ETag in object metadata is not the MD5 content hash, skip the HEAD request.
opts = { ...opts, etagIsNotMD5: true }
return await super.getObjectMd5Hash(bucketName, path, opts)
}
/**
* @param {string} bucketName
* @param {string} sourcePath
* @param {string} destinationPath
* @param {Object} opts
* @param {SSECOptions} [opts.ssecOptions]
* @param {SSECOptions} [opts.ssecSrcOptions]
* @return {Promise<void>}
*/
async copyObject(bucketName, sourcePath, destinationPath, opts = {}) {
const ssecOptions =
opts.ssecOptions ||
+61 -13
View File
@@ -77,14 +77,53 @@ class SSECOptions {
}
}
/**
* @typedef {import('@aws-sdk/client-s3').StorageClass} StorageClass
* @typedef {import('@aws-sdk/client-s3').PutObjectCommandInput} PutObjectCommandInput
* @typedef {import('@aws-sdk/client-s3').HeadObjectCommandOutput} HeadObjectCommandOutput
* @typedef {import('@aws-sdk/client-s3').GetObjectCommandOutput} GetObjectCommandOutput
* @typedef {import('@aws-sdk/client-s3').S3ClientConfig} S3ClientConfig
*/
/**
* @typedef {Object} StreamOptions
* @property {string} [contentType]
* @property {string} [contentEncoding]
* @property {number} [contentLength]
* @property {'*'} [ifNoneMatch]
* @property {SSECOptions} [ssecOptions]
*/
/**
* @typedef {Object} S3PersistorSettings
* @property {Object<string, StorageClass>} [storageClass]
* @property {string} [key]
* @property {string} [secret]
* @property {string} [region]
* @property {string} [endpoint]
* @property {boolean} [pathStyle]
* @property {number} [maxRetries]
* @property {Object} [httpOptions]
* @property {string} [ca]
* @property {number} [signedUrlExpiryInMs]
* @property {number} [partSize]
* @property {Object<string, {auth_key: string, auth_secret: string}>} [bucketCreds]
*/
class S3Persistor extends AbstractPersistor {
/** @type {Map<string, S3Client>} */
#clients = new Map()
/** @type {S3PersistorSettings} */
settings
/**
* @param {S3PersistorSettings} [settings]
*/
constructor(settings = {}) {
super()
settings.storageClass = settings.storageClass || {}
settings.storageClass = /** @type {Object<string, StorageClass>} */ (
settings.storageClass || {}
)
this.settings = settings
}
@@ -102,12 +141,7 @@ class S3Persistor extends AbstractPersistor {
* @param {string} bucketName
* @param {string} key
* @param {NodeJS.ReadableStream} readStream
* @param {Object} opts
* @param {string} [opts.contentType]
* @param {string} [opts.contentEncoding]
* @param {number} [opts.contentLength]
* @param {'*'} [opts.ifNoneMatch]
* @param {SSECOptions} [opts.ssecOptions]
* @param {StreamOptions} opts
* @return {Promise<void>}
*/
async sendStream(bucketName, key, readStream, opts = {}) {
@@ -128,8 +162,11 @@ class S3Persistor extends AbstractPersistor {
Body: observer,
}
if (this.settings.storageClass[bucketName]) {
uploadOptions.StorageClass = this.settings.storageClass[bucketName]
const storageClass = /** @type {Object<string, StorageClass>} */ (
this.settings.storageClass
)
if (storageClass[bucketName]) {
uploadOptions.StorageClass = storageClass[bucketName]
}
if ('sourceMd5' in opts) {
@@ -239,7 +276,9 @@ class S3Persistor extends AbstractPersistor {
* @return {Promise<string>}
*/
async getRedirectUrl(bucketName, key) {
const expiresSeconds = Math.round(this.settings.signedUrlExpiryInMs / 1000)
const expiresSeconds = Math.round(
/** @type {number} */ (this.settings.signedUrlExpiryInMs) / 1000
)
try {
return await getSignedUrl(
this._getClientForBucket(bucketName),
@@ -311,6 +350,7 @@ class S3Persistor extends AbstractPersistor {
*/
async #listDirectory(bucketName, key, continuationToken) {
let response
/** @type {{ Bucket: string, Prefix: string, ContinuationToken?: string }} */
const options = { Bucket: bucketName, Prefix: key }
if (continuationToken) {
options.ContinuationToken = continuationToken
@@ -501,6 +541,7 @@ class S3Persistor extends AbstractPersistor {
*/
async directorySize(bucketName, key, continuationToken) {
try {
/** @type {{ Bucket: string, Prefix: string, ContinuationToken?: string }} */
const options = {
Bucket: bucketName,
Prefix: key,
@@ -621,7 +662,7 @@ class S3Persistor extends AbstractPersistor {
}
/**
* @param {Object} bucketCredentials
* @param {{auth_key: string, auth_secret: string} | undefined} bucketCredentials
* @param {import('@aws-sdk/client-s3').S3ClientConfig} clientOptions
* @return {import('@aws-sdk/client-s3').S3ClientConfig}
* @private
@@ -637,7 +678,7 @@ class S3Persistor extends AbstractPersistor {
} else if (this.settings.key) {
options.credentials = {
accessKeyId: this.settings.key,
secretAccessKey: this.settings.secret,
secretAccessKey: /** @type {string} */ (this.settings.secret),
}
} else {
// Use the default credentials provider (process.env -> SSP -> ini -> IAM)
@@ -709,6 +750,9 @@ class S3Persistor extends AbstractPersistor {
}
// test-only
/**
* @param {string} bucketName
*/
_createBucket(bucketName) {
return this._getClientForBucket(bucketName).send(
new CreateBucketCommand({ Bucket: bucketName })
@@ -716,6 +760,10 @@ class S3Persistor extends AbstractPersistor {
}
// test-only
/**
* @param {string} bucketName
* @param {import('@aws-sdk/client-s3').PutObjectCommandInput} uploadOptions
*/
_upload(bucketName, uploadOptions) {
return this._getClientForBucket(bucketName).send(
new PutObjectCommand(uploadOptions)