• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

StauroDEV / filebase-upload / 14548630172

19 Apr 2025 11:19AM UTC coverage: 67.246% (-6.3%) from 73.54%
14548630172

push

github

web-flow
Merge pull request #5 from StauroDEV/remove-presigner-dep

fix: remove s3-presigner dep

9 of 27 branches covered (33.33%)

Branch coverage included in aggregate %.

71 of 72 new or added lines in 2 files covered. (98.61%)

35 existing lines in 2 files now uncovered.

223 of 318 relevant lines covered (70.13%)

2.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.15
/mod.ts
1
import { FILEBASE_API_URL } from './constants.ts'
1✔
2
import type { HeaderBag, HttpRequest as IHttpRequest, QueryParameterBag } from '@smithy/types'
3

4
import type aws4 from 'aws4'
5
import { createHash, createHmac, type Hash as NodeHash, type Hmac } from 'node:crypto'
1✔
6
import type { RequiredArgs } from './types.ts'
7

8
import {
1✔
9
  castSourceData,
1✔
10
  createBucket,
1✔
11
  formatUrl,
1✔
12
  fromEnv,
1✔
13
  generateFilebaseRequestOptions,
1✔
14
  parseUrl,
1✔
15
  presignRequest,
1✔
16
  toUint8Array,
1✔
17
} from './utils.ts'
1✔
18

19
export class HashImpl {
1✔
UNCOV
20
  #algorithmIdentifier: string
×
UNCOV
21
  #secret?
×
UNCOV
22
  #hash!: NodeHash | Hmac
×
23

UNCOV
24
  constructor(algorithmIdentifier: string, secret?: string) {
×
UNCOV
25
    this.#algorithmIdentifier = algorithmIdentifier
×
UNCOV
26
    this.#secret = secret
×
UNCOV
27
    this.reset()
×
UNCOV
28
  }
×
29

UNCOV
30
  update(toHash: string, encoding?: 'utf8' | 'ascii' | 'latin1'): void {
×
UNCOV
31
    this.#hash.update(toUint8Array(castSourceData(toHash, encoding)))
×
UNCOV
32
  }
×
33

UNCOV
34
  digest(): Promise<Uint8Array> {
×
NEW
35
    return Promise.resolve(new Uint8Array(this.#hash.digest()))
×
UNCOV
36
  }
×
37

UNCOV
38
  reset(): void {
×
UNCOV
39
    this.#hash = this.#secret
×
UNCOV
40
      ? createHmac(this.#algorithmIdentifier, castSourceData(this.#secret))
×
UNCOV
41
      : createHash(this.#algorithmIdentifier)
×
UNCOV
42
  }
×
43
}
1✔
44

45
class HttpRequest {
1✔
46
  method: string
1✔
47
  protocol: string
2✔
48
  hostname: string
2✔
49
  port?: number
2✔
50
  path: string
2✔
51
  query?: QueryParameterBag | undefined
2✔
52
  headers: HeaderBag
2✔
53
  username?: string
2✔
54
  password?: string
2✔
55
  fragment?: string
2✔
56
  body?: unknown
1✔
57

58
  constructor(options: IHttpRequest) {
1✔
59
    this.method = options.method || 'GET'
×
60
    this.hostname = options.hostname || 'localhost'
×
61
    this.port = options.port
2✔
62
    this.query = options.query || {}
2✔
63
    this.headers = options.headers || {}
×
64
    this.body = options.body
2✔
65
    this.protocol = options.protocol
×
66
      ? options.protocol.slice(-1) !== ':' ? `${options.protocol}:` : options.protocol
×
67
      : 'https:'
×
68
    this.path = options.path ? (options.path.charAt(0) !== '/' ? `/${options.path}` : options.path) : '/'
×
69
    this.username = options.username
2✔
70
    this.password = options.password
2✔
71
    this.fragment = options.fragment
2✔
72
  }
2✔
73
}
1✔
74

75
export const createPresignedUrl = async (
1✔
76
  { bucketName, apiUrl, file, token }: {
1✔
77
    file: File
78
  } & RequiredArgs,
1✔
79
): Promise<string> => {
80
  await createBucket({ bucketName, apiUrl, token })
10✔
81
  const url = parseUrl(`https://${apiUrl ?? FILEBASE_API_URL}/${bucketName}/${file.name}`)
2✔
82
  const { accessKeyId, secretAccessKey } = fromEnv(token)()
2✔
83

84
  const signedRequest = presignRequest(
2✔
85
    new HttpRequest({ ...url, method: 'PUT', headers: {} }),
10✔
86
    {
2✔
87
      accessKeyId,
2✔
88
      secretAccessKey,
2✔
89
      region: 'us-east-1',
2✔
90
      expiresIn: 3600,
2✔
91
    },
2✔
92
  )
93
  return formatUrl(signedRequest)
2✔
94
}
1✔
95

96
export const uploadCar = async ({ file, ...args }: RequiredArgs & { file: File }): Promise<Response> => {
1✔
97
  const url = await createPresignedUrl({ ...args, file })
8✔
98

99
  const res = await fetch(decodeURIComponent(url), {
2✔
100
    method: 'PUT',
2✔
101
    body: file,
2✔
102
    headers: { 'x-amz-meta-import': 'car' },
6✔
103
  })
2✔
104

105
  return res
2✔
106
}
1✔
107

108
export const headObject = async (
×
109
  { bucketName, filename, apiUrl, token }: RequiredArgs & {
×
110
    filename: string
111
  },
×
112
): Promise<[boolean, string | null]> => {
113
  let requestOptions: aws4.Request & { key?: string } = {
×
114
    host: `${bucketName}.${apiUrl ?? FILEBASE_API_URL}`,
×
115
    path: `/${filename}`,
×
116
    key: `/${filename}`,
×
117
    region: 'us-east-1',
×
118
    method: 'HEAD',
×
119
    service: 's3',
×
120
    headers: {},
×
121
  }
×
122
  requestOptions = generateFilebaseRequestOptions(
×
123
    token,
×
124
    requestOptions,
×
125
  )
126
  return await fetch(
×
127
    `https://${requestOptions.host}${requestOptions.path}`,
×
128
    requestOptions as RequestInit,
×
129
  )
130
    .then((res) => [res.status == 200, res.headers.get('x-amz-meta-cid')])
×
131
}
×
132

133
export const getObject = async (
1✔
134
  { bucketName, filename, apiUrl, token }: RequiredArgs & {
1✔
135
    filename: string
136
  },
1✔
137
): Promise<Response> => {
138
  let requestOptions: aws4.Request & { key?: string } = {
3✔
139
    host: `${bucketName}.${apiUrl ?? FILEBASE_API_URL}`,
3✔
140
    path: `/${filename}`,
3✔
141
    key: `/${filename}`,
3✔
142
    region: 'us-east-1',
3✔
143
    method: 'GET',
3✔
144
    service: 's3',
3✔
145
    headers: {},
3✔
146
  }
3✔
147
  requestOptions = generateFilebaseRequestOptions(
3✔
148
    token,
3✔
149
    requestOptions,
3✔
150
  )
151
  return await fetch(
3✔
152
    `https://${requestOptions.host}${requestOptions.path}`,
3✔
153
    requestOptions as RequestInit,
3✔
154
  )
155
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc