Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to TypeScript #683

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2d64821
Convert first file to TypeScript
Acconut Apr 16, 2024
f16b675
Transpile using TypeScript
Acconut Apr 16, 2024
e7ce111
Remove Babel
Acconut Apr 16, 2024
677e063
Add back missing dependencies for ESLint
Acconut Apr 16, 2024
f04835f
Move eslint exceptions into .eslintrc
Acconut Apr 16, 2024
12effd8
Move logger.js to TypeScript
Acconut Apr 16, 2024
9a65843
Rename tsconfig-base.json to tsconfig.json
Acconut Apr 16, 2024
b887d7e
Move upload.js to TypeScript
Acconut Apr 16, 2024
b85b7e1
Move all node-related source files to TypeScript
Acconut Apr 16, 2024
de3473f
Move browser source code to TypeScript
Acconut May 13, 2024
d8e4f16
Lint
Acconut May 17, 2024
044dad0
Add linting rules for TypeScript
Acconut May 17, 2024
3cd76fd
Remove obsolete type definitions
Acconut May 17, 2024
4620b9c
Properly transpile to ESM and CJS
Acconut May 17, 2024
3407b9b
Fix build command
Acconut May 17, 2024
4e349f5
Restructure exports in `package.json`
Acconut May 17, 2024
5a9f228
Keep main pointing to Node index
Acconut May 27, 2024
ca9081e
Merge branch 'main' into typescript2
Acconut May 28, 2024
3bfdacc
Remove ESLint comments
Acconut May 28, 2024
f0bad11
Remove typescript-eslint
Acconut May 28, 2024
43372eb
Remove Babel (again)
Acconut May 28, 2024
7c9425d
Remove empty line
Acconut May 28, 2024
dbafd50
Revert to original structure in `package.json`
Acconut May 28, 2024
57cbb49
Remove `tsd`
Acconut May 28, 2024
8538ead
Rename `lib.es5` to more appropriate `lib.cjs`
Acconut May 28, 2024
e5a38ea
Explicitly install `types/node`
Acconut May 29, 2024
f68c22c
Move types and values for options in own file
Acconut May 29, 2024
d3670cc
Remove `unknown` type for timeout value
Acconut May 29, 2024
695a763
Remove generics to unify the types for Browser and Node.js
Acconut May 29, 2024
2e79a9c
Better detect input types for fingerprinting
Acconut May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .babelrc

This file was deleted.

5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
"devDependencies": ["test/**/*.js"]
}
],
"import/extensions": ["error", "ignorePackages"]
// Disabled for now, because we cannot use the .ts extension.
// TODO: Reevaluate this once all source files have been moved to TS
"import/extensions": ["off"],
"import/no-unresolved": ["off"]
},
"overrides": [
{
Expand Down
10 changes: 5 additions & 5 deletions lib/browser/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import BaseUpload from '../upload.js'
import BaseUpload, { defaultOptions as baseDefaultOptions, terminate } from '../upload'
import NoopUrlStorage from '../noopUrlStorage.js'
import { enableDebugLog } from '../logger.js'
import DetailedError from '../error.js'
import { enableDebugLog } from '../logger'
import DetailedError from '../error'

import { canStoreURLs, WebStorageUrlStorage } from './urlStorage.js'
import DefaultHttpStack from './httpStack.js'
import FileReader from './fileReader.js'
import fingerprint from './fileSignature.js'

const defaultOptions = {
...BaseUpload.defaultOptions,
...baseDefaultOptions,
httpStack: new DefaultHttpStack(),
fileReader: new FileReader(),
urlStorage: canStoreURLs ? new WebStorageUrlStorage() : new NoopUrlStorage(),
Expand All @@ -24,7 +24,7 @@ class Upload extends BaseUpload {

static terminate(url, options = {}) {
options = { ...defaultOptions, ...options }
return BaseUpload.terminate(url, options)
return terminate(url, options)
}
}

Expand Down
8 changes: 7 additions & 1 deletion lib/error.js → lib/error.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { HttpRequest, HttpResponse } from './upload'

class DetailedError extends Error {
constructor(message, causingErr = null, req = null, res = null) {
originalRequest?: HttpRequest<unknown>
originalResponse?: HttpResponse
causingError?: Error

constructor(message: string, causingErr?: Error, req?: HttpRequest<unknown>, res?: HttpResponse) {
super(message)

this.originalRequest = req
Expand Down
1 change: 1 addition & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Type definitions for tus-js-client
// TODO: Remove this file

export const isSupported: boolean
export const canStoreURLs: boolean
Expand Down
1 change: 1 addition & 0 deletions lib/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This is a test file for ensuring that the type definitions in index.d.ts are
// working correctly. For more details see:
// https://github.com/SamVerschueren/tsd
// TODO: Remove this file

import * as tus from '../'
import { expectType } from 'tsd'
Expand Down
4 changes: 2 additions & 2 deletions lib/logger.js → lib/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

let isEnabled = false

export function enableDebugLog() {
export function enableDebugLog(): void {
isEnabled = true
}

export function log(msg) {
export function log(msg: string): void {
if (!isEnabled) return
console.log(msg)
}
14 changes: 9 additions & 5 deletions lib/node/fileReader.js → lib/node/fileReader.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { ReadStream } from 'fs'
import isStream from 'is-stream'

import BufferSource from './sources/BufferSource.js'
import getFileSource from './sources/FileSource.js'
import StreamSource from './sources/StreamSource.js'
import { FileReader as IFileReader } from '../upload'
import BufferSource from './sources/BufferSource'
import getFileSource from './sources/FileSource'
import StreamSource from './sources/StreamSource'
import { FileSliceTypes, FileTypes } from './index'

export default class FileReader {
openFile(input, chunkSize) {
// TODO: Consider renaming this NodeFileReader
export default class FileReader implements IFileReader<FileTypes, FileSliceTypes> {
// TODO: Use async here and less Promise.resolve
openFile(input: FileTypes, chunkSize: number) {
if (Buffer.isBuffer(input)) {
return Promise.resolve(new BufferSource(input))
}
Expand Down
11 changes: 9 additions & 2 deletions lib/node/fileSignature.js → lib/node/fileSignature.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import * as fs from 'fs'
import * as path from 'path'
import { createHash } from 'crypto'
import { UploadOptions } from '../upload'
import { FileTypes, FileSliceTypes } from './index'

/**
* Generate a fingerprint for a file which will be used the store the endpoint
*
* @param {File} file
* @param {Object} options
*/
export default function fingerprint(file, options) {
export default function fingerprint(
file: FileTypes,
options: UploadOptions<FileTypes, FileSliceTypes>,
): Promise<string | null> {
if (Buffer.isBuffer(file)) {
// create MD5 hash for buffer type
const blockSize = 64 * 1024 // 64kb
Expand All @@ -20,7 +25,9 @@ export default function fingerprint(file, options) {

if (file instanceof fs.ReadStream && file.path != null) {
return new Promise((resolve, reject) => {
const name = path.resolve(file.path)
const name = path.resolve(
Buffer.isBuffer(file.path) ? file.path.toString('utf-8') : file.path,
)
fs.stat(file.path, (err, info) => {
if (err) {
reject(err)
Expand Down
66 changes: 44 additions & 22 deletions lib/node/httpStack.js → lib/node/httpStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import * as https from 'https'
import { parse } from 'url'
import { Readable, Transform } from 'stream'
import throttle from 'lodash.throttle'
import { HttpProgressHandler, HttpRequest, HttpResponse, HttpStack } from '../upload'
import { FileSliceTypes } from './index'

export default class NodeHttpStack {
constructor(requestOptions = {}) {
export default class NodeHttpStack implements HttpStack<FileSliceTypes> {
private _requestOptions: http.RequestOptions

constructor(requestOptions: http.RequestOptions = {}) {
this._requestOptions = requestOptions
}

createRequest(method, url) {
createRequest(method: string, url: string) {
return new Request(method, url, this._requestOptions)
}

Expand All @@ -21,14 +25,18 @@ export default class NodeHttpStack {
}
}

class Request {
constructor(method, url, options) {
class Request implements HttpRequest<FileSliceTypes> {
_method: string
_url: string
_headers: Record<string, string> = {}
_request: http.ClientRequest | null = null
_progressHandler: HttpProgressHandler = () => {}
_requestOptions: http.RequestOptions

constructor(method: string, url: string, options: http.RequestOptions) {
this._method = method
this._url = url
this._headers = {}
this._request = null
this._progressHandler = () => {}
this._requestOptions = options || {}
this._requestOptions = options
}

getMethod() {
Expand All @@ -39,19 +47,19 @@ class Request {
return this._url
}

setHeader(header, value) {
setHeader(header: string, value: string) {
this._headers[header] = value
}

getHeader(header) {
getHeader(header: string) {
return this._headers[header]
}

setProgressHandler(progressHandler) {
setProgressHandler(progressHandler: HttpProgressHandler) {
this._progressHandler = progressHandler
}

send(body = null) {
send(body?: FileSliceTypes): Promise<HttpResponse> {
return new Promise((resolve, reject) => {
const options = {
...parse(this._url),
Expand All @@ -64,16 +72,18 @@ class Request {
},
}

//@ts-expect-error
if (body && body.size) {
//@ts-expect-error
options.headers['Content-Length'] = body.size
}

const httpModule = options.protocol === 'https:' ? https : http
this._request = httpModule.request(options)
const req = this._request
req.on('response', (res) => {
const resChunks = []
res.on('data', (data) => {
const resChunks: Buffer[] = []
res.on('data', (data: Buffer) => {
resChunks.push(data)
})

Expand Down Expand Up @@ -114,18 +124,28 @@ class Request {
}
}

class Response {
constructor(res, body) {
class Response implements HttpResponse {
_response: http.IncomingMessage
_body: string

constructor(res: http.IncomingMessage, body: string) {
this._response = res
this._body = body
}

getStatus() {
if (this._response.statusCode == undefined) {
throw new Error('no status code available yet')
}
return this._response.statusCode
}

getHeader(header) {
return this._response.headers[header.toLowerCase()]
getHeader(header: string) {
const values = this._response.headers[header.toLowerCase()]
if (Array.isArray(values)) {
return values.join(', ')
}
return values
}

getBody() {
Expand All @@ -141,7 +161,10 @@ class Response {
// track of the number of bytes which have been piped through it and will
// invoke the `onprogress` function whenever new number are available.
class ProgressEmitter extends Transform {
constructor(onprogress) {
_onprogress: HttpProgressHandler
_position = 0

constructor(onprogress: HttpProgressHandler) {
super()

// The _onprogress property will be invoked, whenever a chunk is piped
Expand All @@ -153,10 +176,9 @@ class ProgressEmitter extends Transform {
leading: true,
trailing: false,
})
this._position = 0
}

_transform(chunk, encoding, callback) {
_transform(chunk: Buffer, encoding: string, callback: (err: Error | null, data: Buffer) => void) {
this._position += chunk.length
this._onprogress(this._position)
callback(null, chunk)
Expand Down
50 changes: 0 additions & 50 deletions lib/node/index.js

This file was deleted.

Loading
Loading