Skip to content

Commit

Permalink
feat: Upgrade to Node.js 20.
Browse files Browse the repository at this point in the history
feat: Upgrade to ESLint 9 and fix errors.
feat: Upgrade dependencies.
  • Loading branch information
loune committed Jul 27, 2024
1 parent 221dce8 commit e9d2947
Show file tree
Hide file tree
Showing 19 changed files with 2,335 additions and 2,420 deletions.
38 changes: 0 additions & 38 deletions .eslintrc.json

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/nodejs-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
node-version: [18.x]
node-version: [20.x]

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ azurite
azurite2
.env
**/node_modules
coverage
3 changes: 1 addition & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"printWidth": 120,
"singleQuote": true,
"trailingComma": "es5"
"singleQuote": true
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Upgrade to Node.js 20.16.
- Upgrade ESLint 9

## [6.1.1] - 2023-12-28

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

## Installation

### For Amazon S3
### For Amazon S3 (or compatible services such as Cloudflare R2, MinIO)

```bash
yarn add snap-push @aws-sdk/client-s3 @aws-sdk/lib-storage
Expand Down
44 changes: 44 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';

const eslintTsConfig = tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
eslintPluginPrettierRecommended,
{
languageOptions: {
parserOptions: {
project: './tsconfig.json',
// tsconfigRootDir: import.meta.dirname,
},
},
rules: {
'class-methods-use-this': 'off',
'no-param-reassign': 'off',
'lines-between-class-members': 'off',
'no-restricted-syntax': 'off',
'@typescript-eslint/explicit-member-accessibility': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'react/prop-types': 'off',

'no-useless-constructor': 'off',
},
}
);

export default [
...eslintTsConfig,
{
files: ['**/*.test.ts', '**/*.test.tsx'],

languageOptions: {
globals: {
...globals.jest,
},
},
},
];
27 changes: 13 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}
},
"engines": {
"node": ">=16.10"
"node": ">=20.16"
},
"bin": {
"snap-push": "dist-esm/cli.js"
Expand All @@ -34,8 +34,8 @@
"CHANGELOG.md"
],
"scripts": {
"test": "yarn lint && yarn env-cmd --silent jest --detectOpenHandles",
"lint": "npx eslint --ext .js,.ts src",
"test": "yarn lint && yarn env-cmd --silent jest --detectOpenHandles --coverage",
"lint": "npx eslint src",
"build": "rimraf dist-esm dist-cjs dist-types && yarn tsc -b ./tsconfig.esm.json ./tsconfig.cjs.json ./tsconfig.types.json && chmod +x dist-esm/cli.js && echo '{\"type\": \"commonjs\"}' > ./dist-cjs/package.json",
"prepublish": "yarn build"
},
Expand Down Expand Up @@ -81,25 +81,24 @@
"devDependencies": {
"@aws-sdk/client-s3": "^3.388.0",
"@aws-sdk/lib-storage": "^3.388.0",
"@azure/storage-blob": "^12.15.0",
"@azure/storage-blob": "12.18.0",
"@eslint/js": "^9.6.0",
"@google-cloud/storage": "^7.0.1",
"@types/eslint__js": "^8.42.3",
"@types/jest": "^29.5.1",
"@types/node": "^16",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"azurite": "^3.25.1",
"@types/node": "^20",
"azurite": "^3.31.0",
"env-cmd": "^10.1.0",
"eslint": "^8.2.0",
"eslint-config-airbnb": "^19.0.4",
"eslint": "^9.6.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.5.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^5.1.2",
"globals": "^15.8.0",
"jest": "^29.5.0",
"prettier": "^3.1.1",
"rimraf": "^5.0.0",
"rimraf": "^6.0.1",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"typescript-eslint": "^7.15.0"
},
"dependencies": {
"fast-glob": "^3.2.4",
Expand Down
4 changes: 2 additions & 2 deletions src/azure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test('azure uploadFile', async () => {
const options: AzureProviderOptions = {
credential: new StorageSharedKeyCredential(
accountName,
'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='
'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
),
serviceUrl: `http://127.0.0.1:39858/${accountName}`,
containerName: `snappushtest${new Date().getTime()}`,
Expand Down Expand Up @@ -82,7 +82,7 @@ test('azure uploadFile', async () => {
const streamString = await new Promise((resolve, reject) => {
const buffers: Buffer[] = [];
expect(downloadBlockBlobResponse.readableStreamBody).toBeTruthy();
downloadBlockBlobResponse.readableStreamBody?.on('data', (data) => {
downloadBlockBlobResponse.readableStreamBody?.on('data', (data: Buffer) => {
buffers.push(data);
});
downloadBlockBlobResponse.readableStreamBody?.on('end', () => {
Expand Down
23 changes: 6 additions & 17 deletions src/azure.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { BlobServiceClient } from '@azure/storage-blob';
import { BlobServiceClient, newPipeline } from '@azure/storage-blob';
import { UploadFileProvider, UploadFile } from './types.js';

export interface AzureProviderOptions {
credential: any;
credential: Parameters<typeof newPipeline>[0];
account?: string;
containerName: string;
serviceUrl?: string;
Expand All @@ -19,22 +19,12 @@ export default function uploadFileFactory(providerOptions: AzureProviderOptions)
throw new Error('account or serviceUrl is required for providerOptions');
}

const blobServiceClient = new BlobServiceClient(serviceUrl || `https://${account}.blob.core.windows.net`, credential);
const blobServiceClient = new BlobServiceClient(serviceUrl ?? `https://${account}.blob.core.windows.net`, credential);

const containerClient = blobServiceClient.getContainerClient(containerName);

return {
upload: async ({
source,
destFileName,
contentLength,
contentType,
md5Hash,
metadata,
tags,
cacheControl,
contentEncoding,
}) => {
upload: async ({ source, destFileName, contentType, md5Hash, metadata, tags, cacheControl, contentEncoding }) => {
const blockBlobClient = containerClient.getBlockBlobClient(destFileName);

await blockBlobClient.uploadStream(source, source.readableHighWaterMark, undefined, {
Expand All @@ -56,13 +46,12 @@ export default function uploadFileFactory(providerOptions: AzureProviderOptions)
...(includeMetadata ? { include: ['metadata'] } : {}),
});

// eslint-disable-next-line no-await-in-loop
for await (const blob of response) {
results.push({
name: blob.name,
md5: blob.properties.contentMD5 ? Buffer.from(blob.properties.contentMD5).toString('hex') : undefined,
size: blob.properties.contentLength || 0,
metadata: blob.metadata || {},
size: blob.properties.contentLength ?? 0,
metadata: blob.metadata ?? {},
});
}

Expand Down
40 changes: 24 additions & 16 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node
import yargs from 'yargs';
import push from './push.js';
import { UploadFileProvider } from './types.js';

interface Argv {
source: string;
Expand All @@ -13,58 +14,61 @@ interface Argv {
accountKey?: string;
}

function getProvider(argv: Argv) {
const [, proto, bucket] = /^([a-zA-Z0-9]+):\/\/([a-zA-Z0-9-.]+)\/*/.exec(argv.destination) || [null, null, null];
type UploadFileProviderConstructor = (options: unknown) => UploadFileProvider;

function getProvider(argv: Argv): UploadFileProvider {
const [, proto, bucket] = /^([a-zA-Z0-9]+):\/\/([a-zA-Z0-9-.]+)\/*/.exec(argv.destination) ?? [null, null, null];

if (proto === null) {
throw new Error(
`destination ${argv.destination} is not valid. It should be in the format of <provider>://<bucket> e.g. s3://my-bucket-name`
`destination ${argv.destination} is not valid. It should be in the format of <provider>://<bucket> e.g. s3://my-bucket-name`,
);
}

if (proto === 's3') {
const providerOptions = { bucket, listMetaDataConcurrency: argv.concurrency };
// eslint-disable-next-line global-require,@typescript-eslint/no-var-requires
const s3FileProvider = require('./s3').default;
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
const s3FileProvider = require('./s3').default as UploadFileProviderConstructor;
return s3FileProvider(providerOptions);
}

if (proto === 'gcp') {
const providerOptions = { bucket };
// eslint-disable-next-line global-require,@typescript-eslint/no-var-requires
const gcpProvider = require('./gcp').default;
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
const gcpProvider = require('./gcp').default as UploadFileProviderConstructor;
return gcpProvider(providerOptions);
}

if (proto === 'azure') {
// eslint-disable-next-line @typescript-eslint/no-var-requires,global-require
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
const { SharedKeyCredential } = require('@azure/storage-blob');
const providerOptions = {
account: argv.accountName,
containerName: bucket,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
credential: argv.accountName ? new SharedKeyCredential(argv.accountName, argv.accountKey) : undefined,
};
// eslint-disable-next-line global-require,@typescript-eslint/no-var-requires
const gcpProvider = require('./azure').default;
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
const gcpProvider = require('./azure').default as UploadFileProviderConstructor;
return gcpProvider(providerOptions);
}

throw new Error(`${proto} is not supported`);
}

const logger = {
info(...args: any) {
info(...args: unknown[]) {
console.log(...args);
},
error(...args: any) {
error(...args: unknown[]) {
console.error(...args);
},
warn(...args: any) {
warn(...args: unknown[]) {
console.warn(...args);
},
};

yargs // eslint-disable-line no-unused-expressions
const result = yargs
.command<Argv>(
'* <source> <destination>',
'Push files to the remote file service.',
Expand Down Expand Up @@ -92,13 +96,13 @@ yargs // eslint-disable-line no-unused-expressions
logger.info(
`Finished in ${Math.round((Date.now() - startTime) / 1000)}s. (Uploaded ${
result.uploadedKeys.length
}. Deleted ${result.deletedKeys.length}. Skipped ${result.skippedKeys.length}.)`
}. Deleted ${result.deletedKeys.length}. Skipped ${result.skippedKeys.length}.)`,
);
})
.catch((error) => {
logger.error(`Error: ${error}`);
});
}
},
)
.option('concurrency', {
alias: 'c',
Expand All @@ -119,3 +123,7 @@ yargs // eslint-disable-line no-unused-expressions
.option('force', {
default: false,
}).argv;

if (result instanceof Promise) {
result.catch((err: any) => logger.error(err));
}
2 changes: 1 addition & 1 deletion src/contentType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async function readChars(filename: string, numOfChars: number): Promise<string>

export default async function getFileMimeType(
filename: string,
customMimeTypes?: Record<string, string[]> | undefined
customMimeTypes?: Record<string, string[]> | undefined,
): Promise<string | undefined> {
const extension = filename.substring(filename.lastIndexOf('.') + 1);

Expand Down
8 changes: 5 additions & 3 deletions src/dryrun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ export default function uploadFileFactory(providerOptions: DryRunOptions): Uploa
const { realProvider, logger } = providerOptions;

return {
upload: async ({ destFileName, contentType }) => {
upload: ({ destFileName, contentType }) => {
logger.info(`Pretend upload: ${destFileName} (${contentType})`);
return Promise.resolve();
},
list: async (prefix: string, includeMetadata: boolean) => {
list: (prefix: string, includeMetadata: boolean) => {
return realProvider.list(prefix, includeMetadata);
},
delete: async (key: string) => {
delete: (key: string) => {
logger.info(`Pretend delete: ${key}`);
return Promise.resolve();
},
};
}
2 changes: 1 addition & 1 deletion src/gcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function uploadFileFactory(providerOptions: GcpProviderOptions):
name: f.name,
md5: f.metadata.md5Hash ? Buffer.from(f.metadata.md5Hash, 'base64').toString('hex') : undefined,
size: Number(f.metadata.size),
metadata: includeMetadata ? f.metadata.metadata ?? {} : {},
metadata: includeMetadata ? (f.metadata.metadata ?? {}) : {},
}));
},
delete: async (key: string) => {
Expand Down
Loading

0 comments on commit e9d2947

Please sign in to comment.