@cuboapp/api-backend 1.0.38 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/s3/index.ts DELETED
@@ -1,104 +0,0 @@
1
- import { CuboS3UploadFunction } from './types'
2
- import {
3
- defaultFileName,
4
- encodeRfc3986,
5
- encodeS3Key,
6
- toAmzDate,
7
- sha256Hex,
8
- normalizeHeaderValue,
9
- getSignatureKey,
10
- hmacHex,
11
- buildS3Key
12
- } from './utils'
13
-
14
- /**
15
- * Upload buffer to S3 using PUT Object.
16
- * - Uses path-style URL: {endpoint}/{bucket}/{key}
17
- */
18
- export const uploadToS3: CuboS3UploadFunction = async (buffer, opts) => {
19
- const { bucket, region, endpoint, access_key, secret } = opts.s3
20
- const mimeType = opts.mime_type || 'application/octet-stream'
21
-
22
- const baseName = opts.file_name || defaultFileName(mimeType)
23
- const fileName = buildS3Key(baseName, opts.s3.folder)
24
-
25
- const ep = new URL(endpoint)
26
- const host = ep.host
27
-
28
- const canonicalUri = `/${encodeRfc3986(bucket)}/${encodeS3Key(fileName)}`
29
- const url = new URL(`${ep.origin}${canonicalUri}`)
30
-
31
- const method = 'PUT'
32
- const service = 's3'
33
-
34
- const amzDate = toAmzDate(new Date()) // YYYYMMDDTHHMMSSZ
35
- const dateStamp = amzDate.slice(0, 8) // YYYYMMDD
36
-
37
- const payloadHash = sha256Hex(buffer)
38
-
39
- const headers: Record<string, string> = {
40
- host,
41
- 'content-type': mimeType,
42
- 'x-amz-content-sha256': payloadHash,
43
- 'x-amz-date': amzDate
44
- }
45
-
46
- const signedHeaders = Object.keys(headers)
47
- .map((h) => h.toLowerCase())
48
- .sort()
49
- .join(';')
50
-
51
- const canonicalHeaders = Object.keys(headers)
52
- .map((k) => k.toLowerCase())
53
- .sort()
54
- .map((k) => `${k}:${normalizeHeaderValue(headers[k])}\n`)
55
- .join('')
56
-
57
- const canonicalQueryString = ''
58
-
59
- const canonicalRequest =
60
- `${method}\n` + `${canonicalUri}\n` + `${canonicalQueryString}\n` + `${canonicalHeaders}\n` + `${signedHeaders}\n` + `${payloadHash}`
61
-
62
- const algorithm = 'AWS4-HMAC-SHA256'
63
- const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`
64
- const stringToSign = `${algorithm}\n` + `${amzDate}\n` + `${credentialScope}\n` + `${sha256Hex(Buffer.from(canonicalRequest, 'utf8'))}`
65
-
66
- const signingKey = getSignatureKey(secret, dateStamp, region, service)
67
- const signature = hmacHex(signingKey, stringToSign)
68
-
69
- const authorization =
70
- `${algorithm} ` + `Credential=${access_key}/${credentialScope}, ` + `SignedHeaders=${signedHeaders}, ` + `Signature=${signature}`
71
-
72
- try {
73
- const res = await fetch(url.toString(), {
74
- method,
75
- headers: {
76
- ...headers,
77
- Authorization: authorization
78
- },
79
- body: buffer as any
80
- })
81
-
82
- if (!res.ok) {
83
- const text = await res.text()
84
- throw {
85
- code: res.status,
86
- error: res.statusText,
87
- text
88
- }
89
- }
90
-
91
- const resUrl = res.url || url.toString()
92
-
93
- return { fileName: baseName, url: resUrl }
94
- } catch (error) {
95
- console.log('error')
96
- throw {
97
- code: 500,
98
- text: error
99
- }
100
- }
101
- }
102
-
103
- export * from './types'
104
- export * from './utils'
@@ -1,19 +0,0 @@
1
- export type CuboS3UploadFunctionOptions = {
2
- file_name?: string
3
- mime_type: string
4
- s3: {
5
- bucket: string
6
- region: string
7
- endpoint: string
8
- access_key: string
9
- secret: string
10
- folder?: string
11
- }
12
- }
13
-
14
- export type CuboS3UploadFunctionResult = {
15
- fileName: string
16
- url: string
17
- }
18
-
19
- export type CuboS3UploadFunction = (buffer: Buffer, opts: CuboS3UploadFunctionOptions) => Promise<CuboS3UploadFunctionResult>
@@ -1,74 +0,0 @@
1
- import { uuid } from '@cuboapp/utils'
2
- import crypto from 'node:crypto'
3
- import { extension } from 'mime-types'
4
-
5
- export const defaultFileName = (mimeType: string) => {
6
- const ext = extension(mimeType)
7
- const id = uuid()
8
- return `${id}.${ext}`
9
- }
10
-
11
- export const normalizeFileName = (name: string) => {
12
- return name.replace(/^\/+/, '')
13
- }
14
-
15
- export const toAmzDate = (d: Date) => {
16
- // YYYYMMDDTHHMMSSZ
17
- const pad = (n: number) => String(n).padStart(2, '0')
18
- return (
19
- d.getUTCFullYear() +
20
- pad(d.getUTCMonth() + 1) +
21
- pad(d.getUTCDate()) +
22
- 'T' +
23
- pad(d.getUTCHours()) +
24
- pad(d.getUTCMinutes()) +
25
- pad(d.getUTCSeconds()) +
26
- 'Z'
27
- )
28
- }
29
-
30
- export const sha256Hex = (data: Buffer) => {
31
- return crypto.createHash('sha256').update(data).digest('hex')
32
- }
33
-
34
- export const hmac = (key: Buffer | string, data: string) => {
35
- return crypto.createHmac('sha256', key).update(data, 'utf8').digest()
36
- }
37
-
38
- export const hmacHex = (key: Buffer | string, data: string) => {
39
- return crypto.createHmac('sha256', key).update(data, 'utf8').digest('hex')
40
- }
41
-
42
- export const getSignatureKey = (secretKey: string, dateStamp: string, region: string, service: string) => {
43
- const kDate = hmac('AWS4' + secretKey, dateStamp)
44
- const kRegion = hmac(kDate, region)
45
- const kService = hmac(kRegion, service)
46
- const kSigning = hmac(kService, 'aws4_request')
47
- return kSigning
48
- }
49
-
50
- export const normalizeHeaderValue = (v: string) => {
51
- return v.trim().replace(/\s+/g, ' ')
52
- }
53
-
54
- export const encodeRfc3986 = (str: string) => {
55
- return encodeURIComponent(str).replace(/[!'()*]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase())
56
- }
57
-
58
- export const encodeS3Key = (key: string) => {
59
- return key
60
- .split('/')
61
- .map((seg) => encodeRfc3986(seg))
62
- .join('/')
63
- }
64
-
65
- export const buildS3Key = (fileName: string, folder?: string) => {
66
- const cleanFile = normalizeFileName(fileName)
67
-
68
- if (!folder) {
69
- return cleanFile
70
- }
71
-
72
- const cleanFolder = folder.replace(/^\/+|\/+$/g, '')
73
- return `${cleanFolder}/${cleanFile}`
74
- }
@@ -1,51 +0,0 @@
1
- import { CuboApiEntitiesMap, CuboEntity } from '@cuboapp/types'
2
-
3
- import { WsServerSocket } from '@cuboapp/ws'
4
- import { CuboCrudAction, CuboCrudGetManyResponse, CuboCrudRequest } from './basic'
5
- import { CuboCrudMethodOptions, CuboCrudQueryOptions } from './db'
6
-
7
- export type CuboCrudAugmentationsStore<T extends CuboApiEntitiesMap<T>> = {
8
- [K in Extract<keyof T, string>]?: CuboCrudAugmentationInstance<T[K]>
9
- }
10
-
11
- export type CuboCrudCrdtEvent<A, T> = {
12
- client: WsServerSocket
13
- auth: A
14
- entity: CuboEntity
15
- req?: CuboCrudRequest
16
- dto: {
17
- // type: string
18
- event: string
19
- action: CuboCrudAction
20
- row: T
21
- id: number
22
- }
23
- }
24
-
25
- export interface CuboCrudAugmentationInstance<T> {
26
- beforeGetMany?: (req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<CuboCrudQueryOptions>
27
- afterGetMany?: (
28
- result: CuboCrudGetManyResponse<T>,
29
- req: CuboCrudRequest,
30
- opts?: CuboCrudMethodOptions
31
- ) => Promise<CuboCrudGetManyResponse<T>>
32
-
33
- beforeGetOne?: (req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<CuboCrudQueryOptions>
34
- afterGetOne?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<T | undefined>
35
-
36
- beforeCreate?: (req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<CuboCrudQueryOptions>
37
- afterCreate?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<T>
38
- afterCrdtCreate?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<void>
39
-
40
- beforeUpdate?: (req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<CuboCrudQueryOptions>
41
- afterUpdate?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<T>
42
- afterCrdtUpdate?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<void>
43
-
44
- beforeDelete?: (req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<CuboCrudQueryOptions>
45
- afterDelete?: (result: T, req: CuboCrudRequest, opts?: CuboCrudMethodOptions) => Promise<boolean>
46
-
47
- filterRowForCrdtEvent?: (row: T, filters: any) => boolean
48
- sendCrdtEvent?: <A>(context: CuboCrudCrdtEvent<A, T>) => void | Promise<void>
49
-
50
- can?: <A>(action: CuboCrudAction, context: { auth: A; entity: CuboEntity; row: T; req?: CuboCrudRequest }) => boolean | Promise<boolean>
51
- }