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

StauroDEV / filebase-upload / 7005261298

27 Nov 2023 12:53PM UTC coverage: 29.699% (+1.6%) from 28.077%
7005261298

push

github

web-flow
Merge pull request #1 from StauroDEV/aaron/api

feat: made `apiUrl` optional and added tests

7 of 9 branches covered (0.0%)

Branch coverage included in aggregate %.

6 of 10 new or added lines in 4 files covered. (60.0%)

72 of 257 relevant lines covered (28.02%)

0.92 hits per line

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

29.66
/mod.ts
1
import { FILEBASE_API_URL } from './constants.ts'
1✔
2
import {
1✔
3
  aws4,
4
  ChecksumConstructor,
5
  createHash,
1✔
6
  createHmac,
1✔
7
  HeaderBag,
8
  Hmac,
9
  IHttpRequest,
10
  NodeHash,
11
  QueryParameterBag,
12
  S3RequestPresigner,
1✔
13
} from './deps.ts'
1✔
14
import { RequiredArgs } from './types.ts'
15

16
import {
1✔
17
  castSourceData,
1✔
18
  createBucket,
1✔
19
  formatUrl,
1✔
20
  fromEnv,
1✔
21
  generateFilebaseRequestOptions,
1✔
22
  parseUrl,
1✔
23
  toUint8Array,
1✔
24
} from './utils.ts'
1✔
25

26
export class HashImpl {
×
27
  #algorithmIdentifier: string
×
28
  #secret?
×
29
  #hash!: NodeHash | Hmac
×
30

31
  constructor(algorithmIdentifier: string, secret?: string) {
×
32
    this.#algorithmIdentifier = algorithmIdentifier
×
33
    this.#secret = secret
×
34
    this.reset()
×
35
  }
×
36

37
  update(toHash: string, encoding?: 'utf8' | 'ascii' | 'latin1'): void {
×
38
    this.#hash.update(toUint8Array(castSourceData(toHash, encoding)))
×
39
  }
×
40

41
  digest(): Promise<Uint8Array> {
×
42
    return Promise.resolve(this.#hash.digest())
×
43
  }
×
44

45
  reset(): void {
×
46
    this.#hash = this.#secret
×
47
      ? createHmac(this.#algorithmIdentifier, castSourceData(this.#secret))
×
48
      : createHash(this.#algorithmIdentifier)
×
49
  }
×
50
}
×
51

52
class HttpRequest {
×
53
  method: string
×
54
  protocol: string
×
55
  hostname: string
×
56
  port?: number
×
57
  path: string
×
58
  query?: QueryParameterBag | undefined
×
59
  headers: HeaderBag
×
60
  username?: string
×
61
  password?: string
×
62
  fragment?: string
×
63
  body?: unknown
×
64

65
  constructor(options: IHttpRequest) {
×
66
    this.method = options.method || 'GET'
×
67
    this.hostname = options.hostname || 'localhost'
×
68
    this.port = options.port
×
69
    this.query = options.query || {}
×
70
    this.headers = options.headers || {}
×
71
    this.body = options.body
×
72
    this.protocol = options.protocol
×
73
      ? options.protocol.slice(-1) !== ':' ? `${options.protocol}:` : options.protocol
×
74
      : 'https:'
×
75
    this.path = options.path ? (options.path.charAt(0) !== '/' ? `/${options.path}` : options.path) : '/'
×
76
    this.username = options.username
×
77
    this.password = options.password
×
78
    this.fragment = options.fragment
×
79
  }
×
80
}
×
81

82
export const createPresignedUrl = async (
×
NEW
83
  { bucketName, apiUrl, file, token }: { bucketName: string; apiUrl?: string; file: File; token: string },
×
84
) => {
85
  await createBucket({ bucketName, apiUrl, token })
×
NEW
86
  const url = parseUrl(`https://${apiUrl ?? FILEBASE_API_URL}/${bucketName}/${file.name}`)
×
87
  const presigner = new S3RequestPresigner({
×
88
    credentials: fromEnv(token),
×
89
    region: 'us-east-1',
×
90
    sha256: HashImpl.bind(null, 'sha256') as unknown as ChecksumConstructor,
×
91
  })
×
92

93
  const signedUrlObject = await presigner.presign(
×
94
    new HttpRequest({ ...url, method: 'PUT', headers: {} }),
×
95
    { expiresIn: 3600 },
×
96
  )
97
  return formatUrl(signedUrlObject)
×
98
}
×
99

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

125
export const getObject = async (
1✔
126
  { bucketName, filename, apiUrl, token }: RequiredArgs & {
1✔
127
    filename: string
128
  },
1✔
129
) => {
130
  let requestOptions: aws4.Request & { key?: string } = {
3✔
131
    host: `${bucketName}.${apiUrl ?? FILEBASE_API_URL}`,
3✔
132
    path: `/${filename}`,
3✔
133
    key: `/${filename}`,
3✔
134
    region: 'us-east-1',
3✔
135
    method: 'GET',
3✔
136
    service: 's3',
3✔
137
    headers: {},
3✔
138
  }
3✔
139
  requestOptions = generateFilebaseRequestOptions(
3✔
140
    token,
3✔
141
    requestOptions,
3✔
142
  )
143
  return await fetch(
3✔
144
    `https://${requestOptions.host}${requestOptions.path}`,
3✔
145
    requestOptions as RequestInit,
3✔
146
  )
147
}
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