From 4c7141e1eaee794e420007aa23dc9cd32770cdae Mon Sep 17 00:00:00 2001 From: Long Lam Date: Sun, 16 Nov 2025 02:16:17 -0500 Subject: [PATCH 01/13] feat: update internal sdk --- src/internal/api/analyticsApi.ts | 15 ++-- src/internal/api/analyticsConfigApi.ts | 15 ++-- src/internal/api/apis.ts | 22 +++--- src/internal/api/authApi.ts | 11 ++- src/internal/api/fileConfigApi.ts | 97 ++++++++++++++++++++++++++ src/internal/package.json | 56 +++++++++++++++ 6 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 src/internal/package.json diff --git a/src/internal/api/analyticsApi.ts b/src/internal/api/analyticsApi.ts index a3670a8..52909d6 100644 --- a/src/internal/api/analyticsApi.ts +++ b/src/internal/api/analyticsApi.ts @@ -10,8 +10,8 @@ * Do not edit the class manually. */ -import localVarRequest from 'request'; import http from 'http'; +import localVarRequest from 'request'; /* tslint:disable:no-unused-locals */ import { ClickEventResponse } from '../model/clickEventResponse'; @@ -34,19 +34,14 @@ import { LogVisitEventRequest } from '../model/logVisitEventRequest'; import { VisitEventResponse } from '../model/visitEventResponse'; import { - ObjectSerializer, Authentication, - VoidAuth, - Interceptor, -} from '../model/models'; -import { - HttpBasicAuth, HttpBearerAuth, - ApiKeyAuth, - OAuth, + Interceptor, + ObjectSerializer, + VoidAuth, } from '../model/models'; -import { HttpError, RequestFile } from './apis'; +import { HttpError } from './apis'; let defaultBasePath = 'http://localhost'; diff --git a/src/internal/api/analyticsConfigApi.ts b/src/internal/api/analyticsConfigApi.ts index afd6ef6..3ef718f 100644 --- a/src/internal/api/analyticsConfigApi.ts +++ b/src/internal/api/analyticsConfigApi.ts @@ -10,8 +10,8 @@ * Do not edit the class manually. */ -import localVarRequest from 'request'; import http from 'http'; +import localVarRequest from 'request'; /* tslint:disable:no-unused-locals */ import { AnalyticsConfigResponse } from '../model/analyticsConfigResponse'; @@ -19,19 +19,14 @@ import { CreateAnalyticsConfigModel } from '../model/createAnalyticsConfigModel' import { UpdateAnalyticsConfigModel } from '../model/updateAnalyticsConfigModel'; import { - ObjectSerializer, Authentication, - VoidAuth, - Interceptor, -} from '../model/models'; -import { - HttpBasicAuth, HttpBearerAuth, - ApiKeyAuth, - OAuth, + Interceptor, + ObjectSerializer, + VoidAuth, } from '../model/models'; -import { HttpError, RequestFile } from './apis'; +import { HttpError } from './apis'; let defaultBasePath = 'http://localhost'; diff --git a/src/internal/api/apis.ts b/src/internal/api/apis.ts index 1389143..716e96c 100644 --- a/src/internal/api/apis.ts +++ b/src/internal/api/apis.ts @@ -1,26 +1,26 @@ export * from './analyticsApi'; -import { AnalyticsApi } from './analyticsApi'; export * from './analyticsConfigApi'; -import { AnalyticsConfigApi } from './analyticsConfigApi'; export * from './authApi'; -import { AuthApi } from './authApi'; export * from './emailApi'; -import { EmailApi } from './emailApi'; export * from './fileBucketApi'; -import { FileBucketApi } from './fileBucketApi'; export * from './fileConfigApi'; -import { FileConfigApi } from './fileConfigApi'; export * from './fileDownloadApi'; -import { FileDownloadApi } from './fileDownloadApi'; export * from './fileProviderApi'; -import { FileProviderApi } from './fileProviderApi'; export * from './fileUploadApi'; -import { FileUploadApi } from './fileUploadApi'; export * from './projectApi'; -import { ProjectApi } from './projectApi'; export * from './userApi'; -import { UserApi } from './userApi'; import * as http from 'http'; +import { AnalyticsApi } from './analyticsApi'; +import { AnalyticsConfigApi } from './analyticsConfigApi'; +import { AuthApi } from './authApi'; +import { EmailApi } from './emailApi'; +import { FileBucketApi } from './fileBucketApi'; +import { FileConfigApi } from './fileConfigApi'; +import { FileDownloadApi } from './fileDownloadApi'; +import { FileProviderApi } from './fileProviderApi'; +import { FileUploadApi } from './fileUploadApi'; +import { ProjectApi } from './projectApi'; +import { UserApi } from './userApi'; export class HttpError extends Error { constructor( diff --git a/src/internal/api/authApi.ts b/src/internal/api/authApi.ts index b2ac7ac..f8bc9a8 100644 --- a/src/internal/api/authApi.ts +++ b/src/internal/api/authApi.ts @@ -516,9 +516,9 @@ export class AuthApi { }); } /** - * This endpoint is used to test if authentication is working correctly. - * @summary Test endpoint for validating middleware authentication - * @param authorization Bearer token (API Key or JWT) + * This endpoint validates a user JWT token and returns the associated user information if valid + * @summary Validates user JWT and returns user data + * @param authorization Bearer token (User JWT) */ public async authControllerTestAuth( authorization: string, @@ -557,6 +557,11 @@ export class AuthApi { }; let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } authenticationPromise = authenticationPromise.then(() => this.authentications.default.applyToRequest(localVarRequestOptions) ); diff --git a/src/internal/api/fileConfigApi.ts b/src/internal/api/fileConfigApi.ts index 6c98565..69ba88b 100644 --- a/src/internal/api/fileConfigApi.ts +++ b/src/internal/api/fileConfigApi.ts @@ -105,6 +105,103 @@ export class FileConfigApi { this.interceptors.push(interceptor); } + /** + * + * @summary Delete file configuration by project ID + * @param projectId + */ + public async fileConfigControllerDeleteFileConfigByProjectId( + projectId: string, + options: { headers: { [name: string]: string } } = { headers: {} } + ): Promise<{ response: http.IncomingMessage; body: FileConfigResponse }> { + const localVarPath = + this.basePath + + '/file/config/delete/{projectId}'.replace( + '{' + 'projectId' + '}', + encodeURIComponent(String(projectId)) + ); + let localVarQueryParameters: any = {}; + let localVarHeaderParams: any = (Object).assign( + {}, + this._defaultHeaders + ); + const produces = ['application/json']; + // give precedence to 'application/json' + if (produces.indexOf('application/json') >= 0) { + localVarHeaderParams.Accept = 'application/json'; + } else { + localVarHeaderParams.Accept = produces.join(','); + } + let localVarFormParams: any = {}; + + // verify required parameter 'projectId' is not null or undefined + if (projectId === null || projectId === undefined) { + throw new Error( + 'Required parameter projectId was null or undefined when calling fileConfigControllerDeleteFileConfigByProjectId.' + ); + } + + (Object).assign(localVarHeaderParams, options.headers); + + let localVarUseFormData = false; + + let localVarRequestOptions: localVarRequest.Options = { + method: 'POST', + qs: localVarQueryParameters, + headers: localVarHeaderParams, + uri: localVarPath, + useQuerystring: this._useQuerystring, + json: true, + }; + + let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } + authenticationPromise = authenticationPromise.then(() => + this.authentications.default.applyToRequest(localVarRequestOptions) + ); + + let interceptorPromise = authenticationPromise; + for (const interceptor of this.interceptors) { + interceptorPromise = interceptorPromise.then(() => + interceptor(localVarRequestOptions) + ); + } + + return interceptorPromise.then(() => { + if (Object.keys(localVarFormParams).length) { + if (localVarUseFormData) { + (localVarRequestOptions).formData = localVarFormParams; + } else { + localVarRequestOptions.form = localVarFormParams; + } + } + return new Promise<{ + response: http.IncomingMessage; + body: FileConfigResponse; + }>((resolve, reject) => { + localVarRequest(localVarRequestOptions, (error, response, body) => { + if (error) { + reject(error); + } else { + if ( + response.statusCode && + response.statusCode >= 200 && + response.statusCode <= 299 + ) { + body = ObjectSerializer.deserialize(body, 'FileConfigResponse'); + resolve({ response: response, body: body }); + } else { + reject(new HttpError(response, body, response.statusCode)); + } + } + }); + }); + }); + } /** * * @summary Get file configuration by project ID diff --git a/src/internal/package.json b/src/internal/package.json new file mode 100644 index 0000000..96e6b7a --- /dev/null +++ b/src/internal/package.json @@ -0,0 +1,56 @@ +{ + "private": true, + "packageManager": "pnpm@9.11.0", + "name": "bitsofgood-api", + "scripts": { + "preinstall": "pnpm --filter . gen-proto", + "start:dev": "docker compose -f docker-compose-dev.yml up", + "start:dev:watch-packages": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-packages.yml watch --no-up", + "start:dev:watch-proto": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml watch --no-up", + "start:dev:watch-all": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml -f docker/docker-compose-live-packages.yml watch --no-up", + "start:dev:up-packages": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-packages.yml up", + "start:dev:up-proto": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml up", + "start:dev:up-all": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml -f docker/docker-compose-live-packages.yml up", + "start:dev:live-packages": "concurrently -k \"pnpm start:dev:watch-packages\" \"pnpm start:dev:up-packages\"", + "start:dev:live-proto": "concurrently -k \"pnpm start:dev:watch-proto\" \"pnpm start:dev:up-proto\"", + "start:dev:live-all": "concurrently -k -P --success=\"last\" \"pnpm start:dev:watch-all\" \"pnpm start:dev:up-all {@}\" -- ", + "dev": "pnpm start:dev:live-all", + "format:check": "pnpm prettier --check .", + "format:write": "pnpm prettier --write .", + "format": "pnpm prettier --write .", + "tsc": "nx run-many --target=tsc", + "lint": "nx run-many --target=lint --no-cloud", + "sync-protos": "node syncJunoProtos.js", + "gen-proto": "pnpm --filter juno-proto install && pnpm --filter juno-proto build", + "gen-client-sdk": "pnpm openapi-generator-cli generate -g typescript-node -i ./docs-yaml -o ./juno-client-sdk", + "test:e2e:api-gateway-live": "GATEWAY_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from api-gateway", + "test:e2e:auth-service-live": "AUTH_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from auth-service auth-service", + "test:e2e:email-service-live": "EMAIL_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from email-service email-service", + "test:e2e:file-service-live": "FILE_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from file-service file-service", + "test:e2e:analytics-service-live": "ANALYTICS_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from analytics-service analytics-service", + "test:e2e:db-service-live": "DB_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from db-service db-service", + "test:e2e:logging-service-live": "LOGGING_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from logging-service logging-service", + "test:e2e:api-gateway": "GATEWAY_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from api-gateway", + "test:e2e:auth-service": "AUTH_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from auth-service auth-service", + "test:e2e:email-service": "EMAIL_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from email-service email-service", + "test:e2e:file-service": "FILE_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from file-service file-service", + "test:e2e:analytics-service": "ANALYTICS_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from analytics-service analytics-service", + "test:e2e:db-service": "DB_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from db-service db-service", + "test:e2e:logging-service": "LOGGING_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from logging-service logging-service", + "studio": "scripts/launch-prisma-studio.sh" + }, + "devDependencies": { + "@openapitools/openapi-generator-cli": "^2.13.5", + "concurrently": "^8.2.2", + "nx": "^17.0.0", + "prettier": "^3.0.3", + "prettier-plugin-organize-imports": "^3.2.3", + "ts-proto": "^1.162.1" + }, + "dependencies": { + "@sendgrid/mail": "^8.1.1", + "bcrypt": "^5.1.1", + "fs-extra": "^11.2.0", + "lodash": "^4.17.21" + } +} From bbaa52e5c26c6dbd50e70170adfd604d226543bc Mon Sep 17 00:00:00 2001 From: Long Lam Date: Sun, 16 Nov 2025 02:17:14 -0500 Subject: [PATCH 02/13] feat: expose deleteFileConfig --- src/lib/settings.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/settings.ts b/src/lib/settings.ts index a7f6f60..bae30fe 100644 --- a/src/lib/settings.ts +++ b/src/lib/settings.ts @@ -24,6 +24,14 @@ export class SettingsAPI { return res.body; } + async deleteFileConfig(projectId: string): Promise { + const res = + await this.internalFileConfigApi.fileConfigControllerDeleteFileConfigByProjectId( + projectId + ); + return res.body; + } + async getEmailConfig(projectId: string): Promise { const res = await this.internalEmailApi.emailControllerGetEmailConfigById( projectId From 7eb658dda8b438182357683f1fac7c9826099f9a Mon Sep 17 00:00:00 2001 From: Long Lam Date: Sun, 16 Nov 2025 02:49:31 -0500 Subject: [PATCH 03/13] fix: use delete instead of post --- src/internal/api/fileConfigApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/api/fileConfigApi.ts b/src/internal/api/fileConfigApi.ts index 69ba88b..8e2e9b6 100644 --- a/src/internal/api/fileConfigApi.ts +++ b/src/internal/api/fileConfigApi.ts @@ -146,7 +146,7 @@ export class FileConfigApi { let localVarUseFormData = false; let localVarRequestOptions: localVarRequest.Options = { - method: 'POST', + method: 'DELETE', qs: localVarQueryParameters, headers: localVarHeaderParams, uri: localVarPath, From 3e222f9bdba1f811bdcbc26a1f2992cf882ae048 Mon Sep 17 00:00:00 2001 From: Long Lam Date: Sun, 16 Nov 2025 04:44:59 -0500 Subject: [PATCH 04/13] fix: remove settings API --- src/lib/email.ts | 41 ++++++++++++++++++++-------- src/lib/file.ts | 51 ++++++++++++++++++++++++++++++----- src/lib/juno.ts | 14 +--------- src/lib/settings.ts | 66 --------------------------------------------- 4 files changed, 76 insertions(+), 96 deletions(-) delete mode 100644 src/lib/settings.ts diff --git a/src/lib/email.ts b/src/lib/email.ts index d71a4e0..bcfef65 100644 --- a/src/lib/email.ts +++ b/src/lib/email.ts @@ -1,21 +1,21 @@ import { - RegisterEmailModel, - SendEmailModel, - EmailRecipient, - EmailSender, + EmailApi, + EmailConfigResponse, EmailContent, - SendEmailResponse, - RegisterEmailResponse, + EmailRecipient, + EmailSenderSendEmailModel, RegisterDomainModel, - VerifyDomainModel, - EmailApi, RegisterDomainResponse, - SetupEmailServiceModel, + RegisterEmailModel, + RegisterEmailResponse, + SendEmailModel, + SendEmailResponse, SetupEmailResponse, - EmailSenderSendEmailModel, + SetupEmailServiceModel, + VerifyDomainModel, } from '../internal/api'; -import { AuthAPI } from './auth'; import { ApiCredentials } from './apiCredentials'; +import { AuthAPI } from './auth'; import { JunoValidationError } from './errors'; import { validateEmailContent, @@ -34,6 +34,25 @@ export class EmailAPI { this.internalApi.accessToken = this.auth?.junoApiKey; } + async getEmailConfig( + projectId: string, + credentials?: ApiCredentials + ): Promise { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = await this.internalApi.emailControllerGetEmailConfigById( + projectId, + { headers } + ); + return res.body; + } + async setupEmail( options: SetupEmailServiceModel, credentials?: ApiCredentials diff --git a/src/lib/file.ts b/src/lib/file.ts index af70f40..bf9c594 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -8,13 +8,14 @@ import { FileDownloadApi, FileProviderApi, FileProviderResponse, + FileUploadApi, RegisterFileBucketModel, RegisterFileProviderModel, SetupFileServiceResponse, - FileUploadApi, UploadFileModel, UploadFileResponse, } from '../internal/api'; +import { ApiCredentials } from './apiCredentials'; import { JunoValidationError } from './errors'; import { validateString } from './validators'; @@ -39,16 +40,54 @@ export class FileAPI { this.providerApi.accessToken = apiKey; } - async setup(): Promise { - const res = await this.configApi.fileConfigControllerSetup(); + async setup(credentials?: ApiCredentials): Promise { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + const res = await this.configApi.fileConfigControllerSetup({ headers }); return res.body; } - async getConfigByProjectId(projectId: string): Promise { - validateString(projectId, 'Project ID must be non-empty'); + async getConfig( + projectId: string, + credentials?: ApiCredentials + ): Promise { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + const res = await this.configApi.fileConfigControllerGetFileConfigByProjectId( - projectId + projectId, + { headers } + ); + return res.body; + } + + async deleteConfig( + projectId: string, + credentials?: ApiCredentials + ): Promise { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = + await this.configApi.fileConfigControllerDeleteFileConfigByProjectId( + projectId, + { headers } ); return res.body; } diff --git a/src/lib/juno.ts b/src/lib/juno.ts index 9f8e926..1eb26ae 100644 --- a/src/lib/juno.ts +++ b/src/lib/juno.ts @@ -2,10 +2,9 @@ import { AnalyticsAPI } from './analytics'; import { AnalyticsConfigAPI } from './analyticsConfig'; import { AuthAPI } from './auth'; import { EmailAPI } from './email'; -import { FileAPI } from './file'; import { JunoValidationError } from './errors'; +import { FileAPI } from './file'; import { ProjectAPI } from './project'; -import { SettingsAPI } from './settings'; import { UserAPI } from './user'; class JunoAPI { @@ -14,7 +13,6 @@ class JunoAPI { private emailAPI?: EmailAPI; private projectAPI?: ProjectAPI; private authAPI?: AuthAPI; - private settingsAPI?: SettingsAPI; private analyticsAPI?: AnalyticsAPI; private analyticsConfigAPI?: AnalyticsConfigAPI; private fileAPI?: FileAPI; @@ -46,15 +44,6 @@ class JunoAPI { return this.userAPI; } - get settings(): SettingsAPI { - if (!this.settingsAPI) { - throw new JunoValidationError( - 'juno.init() must be called before using the Juno SDK' - ); - } - return this.settingsAPI; - } - get email(): EmailAPI { if (!this.emailAPI) { throw new JunoValidationError( @@ -95,7 +84,6 @@ class JunoAPI { this.userAPI = new UserAPI(options.baseURL); this.emailAPI = new EmailAPI(options.baseURL, this.authAPI); this.projectAPI = new ProjectAPI(options.baseURL, this.apiKey); - this.settingsAPI = new SettingsAPI(options.baseURL, this.apiKey); this.analyticsAPI = new AnalyticsAPI(options.baseURL, this.apiKey); this.analyticsConfigAPI = new AnalyticsConfigAPI( options.baseURL, diff --git a/src/lib/settings.ts b/src/lib/settings.ts deleted file mode 100644 index 9190052..0000000 --- a/src/lib/settings.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { - EmailApi, - EmailConfigResponse, - FileConfigApi, - FileConfigResponse, -} from '../internal/api'; -import { ApiCredentials } from './apiCredentials'; - -export class SettingsAPI { - private internalFileConfigApi: FileConfigApi; - private internalEmailApi: EmailApi; - constructor(baseURL?: string, apiKey?: string) { - this.internalFileConfigApi = new FileConfigApi(baseURL); - this.internalFileConfigApi.accessToken = apiKey; - - this.internalEmailApi = new EmailApi(baseURL); - this.internalEmailApi.accessToken = apiKey; - } - - async getFileConfig( - projectId: string, - credentials?: ApiCredentials - ): Promise { - const headers: any = {}; - if (credentials?.userJwt) { - headers['X-User-JWT'] = credentials.userJwt; - } - if (credentials?.projectId !== undefined) { - headers['X-Project-Id'] = String(credentials.projectId); - } - - const res = - await this.internalFileConfigApi.fileConfigControllerGetFileConfigByProjectId( - projectId, - { headers } - ); - return res.body; - } - - async deleteFileConfig(projectId: string): Promise { - const res = - await this.internalFileConfigApi.fileConfigControllerDeleteFileConfigByProjectId( - projectId - ); - return res.body; - } - - async getEmailConfig( - projectId: string, - credentials?: ApiCredentials - ): Promise { - const headers: any = {}; - if (credentials?.userJwt) { - headers['X-User-JWT'] = credentials.userJwt; - } - if (credentials?.projectId !== undefined) { - headers['X-Project-Id'] = String(credentials.projectId); - } - - const res = await this.internalEmailApi.emailControllerGetEmailConfigById( - projectId, - { headers } - ); - return res.body; - } -} From 6e6c3a3eb3b3f994c3993737a9a9bfd7f85d144a Mon Sep 17 00:00:00 2001 From: Long Lam Date: Sun, 16 Nov 2025 14:19:15 -0500 Subject: [PATCH 05/13] fix: remove file --- src/internal/package.json | 56 --------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 src/internal/package.json diff --git a/src/internal/package.json b/src/internal/package.json deleted file mode 100644 index 96e6b7a..0000000 --- a/src/internal/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "private": true, - "packageManager": "pnpm@9.11.0", - "name": "bitsofgood-api", - "scripts": { - "preinstall": "pnpm --filter . gen-proto", - "start:dev": "docker compose -f docker-compose-dev.yml up", - "start:dev:watch-packages": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-packages.yml watch --no-up", - "start:dev:watch-proto": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml watch --no-up", - "start:dev:watch-all": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml -f docker/docker-compose-live-packages.yml watch --no-up", - "start:dev:up-packages": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-packages.yml up", - "start:dev:up-proto": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml up", - "start:dev:up-all": "docker compose -f docker-compose-dev.yml -f docker/docker-compose-live-proto.yml -f docker/docker-compose-live-packages.yml up", - "start:dev:live-packages": "concurrently -k \"pnpm start:dev:watch-packages\" \"pnpm start:dev:up-packages\"", - "start:dev:live-proto": "concurrently -k \"pnpm start:dev:watch-proto\" \"pnpm start:dev:up-proto\"", - "start:dev:live-all": "concurrently -k -P --success=\"last\" \"pnpm start:dev:watch-all\" \"pnpm start:dev:up-all {@}\" -- ", - "dev": "pnpm start:dev:live-all", - "format:check": "pnpm prettier --check .", - "format:write": "pnpm prettier --write .", - "format": "pnpm prettier --write .", - "tsc": "nx run-many --target=tsc", - "lint": "nx run-many --target=lint --no-cloud", - "sync-protos": "node syncJunoProtos.js", - "gen-proto": "pnpm --filter juno-proto install && pnpm --filter juno-proto build", - "gen-client-sdk": "pnpm openapi-generator-cli generate -g typescript-node -i ./docs-yaml -o ./juno-client-sdk", - "test:e2e:api-gateway-live": "GATEWAY_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from api-gateway", - "test:e2e:auth-service-live": "AUTH_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from auth-service auth-service", - "test:e2e:email-service-live": "EMAIL_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from email-service email-service", - "test:e2e:file-service-live": "FILE_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from file-service file-service", - "test:e2e:analytics-service-live": "ANALYTICS_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from analytics-service analytics-service", - "test:e2e:db-service-live": "DB_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from db-service db-service", - "test:e2e:logging-service-live": "LOGGING_COMMAND=test:e2e:watch RUN_MODE=test pnpm start:dev:live-all --exit-code-from logging-service logging-service", - "test:e2e:api-gateway": "GATEWAY_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from api-gateway", - "test:e2e:auth-service": "AUTH_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from auth-service auth-service", - "test:e2e:email-service": "EMAIL_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from email-service email-service", - "test:e2e:file-service": "FILE_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from file-service file-service", - "test:e2e:analytics-service": "ANALYTICS_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from analytics-service analytics-service", - "test:e2e:db-service": "DB_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from db-service db-service", - "test:e2e:logging-service": "LOGGING_COMMAND=test:e2e RUN_MODE=test pnpm start:dev --exit-code-from logging-service logging-service", - "studio": "scripts/launch-prisma-studio.sh" - }, - "devDependencies": { - "@openapitools/openapi-generator-cli": "^2.13.5", - "concurrently": "^8.2.2", - "nx": "^17.0.0", - "prettier": "^3.0.3", - "prettier-plugin-organize-imports": "^3.2.3", - "ts-proto": "^1.162.1" - }, - "dependencies": { - "@sendgrid/mail": "^8.1.1", - "bcrypt": "^5.1.1", - "fs-extra": "^11.2.0", - "lodash": "^4.17.21" - } -} From f402819daf81c1aeb621ec76942718c86604ef5e Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 02:55:46 -0500 Subject: [PATCH 06/13] feat: update internal --- src/internal/api/fileBucketApi.ts | 193 ++++++++++++++++++++ src/internal/api/fileProviderApi.ts | 189 ++++++++++++++++++- src/internal/model/deleteFileBucketModel.ts | 56 ++++++ src/internal/model/fileProvider.ts | 74 ++++++++ src/internal/model/fileProviderPartial.ts | 47 +++++ src/internal/model/models.ts | 13 +- 6 files changed, 565 insertions(+), 7 deletions(-) create mode 100644 src/internal/model/deleteFileBucketModel.ts create mode 100644 src/internal/model/fileProvider.ts create mode 100644 src/internal/model/fileProviderPartial.ts diff --git a/src/internal/api/fileBucketApi.ts b/src/internal/api/fileBucketApi.ts index 09bcb79..704db1a 100644 --- a/src/internal/api/fileBucketApi.ts +++ b/src/internal/api/fileBucketApi.ts @@ -14,6 +14,7 @@ import localVarRequest from 'request'; import http from 'http'; /* tslint:disable:no-unused-locals */ +import { DeleteFileBucketModel } from '../model/deleteFileBucketModel'; import { FileBucket } from '../model/fileBucket'; import { RegisterFileBucketModel } from '../model/registerFileBucketModel'; @@ -105,6 +106,198 @@ export class FileBucketApi { this.interceptors.push(interceptor); } + /** + * + * @summary Delete a File Bucket. + * @param deleteFileBucketModel + */ + public async fileBucketControllerDeleteFileBucket( + deleteFileBucketModel: DeleteFileBucketModel, + options: { headers: { [name: string]: string } } = { headers: {} } + ): Promise<{ response: http.IncomingMessage; body: FileBucket }> { + const localVarPath = this.basePath + '/file/bucket'; + let localVarQueryParameters: any = {}; + let localVarHeaderParams: any = (Object).assign( + {}, + this._defaultHeaders + ); + const produces = ['application/json']; + // give precedence to 'application/json' + if (produces.indexOf('application/json') >= 0) { + localVarHeaderParams.Accept = 'application/json'; + } else { + localVarHeaderParams.Accept = produces.join(','); + } + let localVarFormParams: any = {}; + + // verify required parameter 'deleteFileBucketModel' is not null or undefined + if (deleteFileBucketModel === null || deleteFileBucketModel === undefined) { + throw new Error( + 'Required parameter deleteFileBucketModel was null or undefined when calling fileBucketControllerDeleteFileBucket.' + ); + } + + (Object).assign(localVarHeaderParams, options.headers); + + let localVarUseFormData = false; + + let localVarRequestOptions: localVarRequest.Options = { + method: 'DELETE', + qs: localVarQueryParameters, + headers: localVarHeaderParams, + uri: localVarPath, + useQuerystring: this._useQuerystring, + json: true, + body: ObjectSerializer.serialize( + deleteFileBucketModel, + 'DeleteFileBucketModel' + ), + }; + + let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } + authenticationPromise = authenticationPromise.then(() => + this.authentications.default.applyToRequest(localVarRequestOptions) + ); + + let interceptorPromise = authenticationPromise; + for (const interceptor of this.interceptors) { + interceptorPromise = interceptorPromise.then(() => + interceptor(localVarRequestOptions) + ); + } + + return interceptorPromise.then(() => { + if (Object.keys(localVarFormParams).length) { + if (localVarUseFormData) { + (localVarRequestOptions).formData = localVarFormParams; + } else { + localVarRequestOptions.form = localVarFormParams; + } + } + return new Promise<{ response: http.IncomingMessage; body: FileBucket }>( + (resolve, reject) => { + localVarRequest(localVarRequestOptions, (error, response, body) => { + if (error) { + reject(error); + } else { + if ( + response.statusCode && + response.statusCode >= 200 && + response.statusCode <= 299 + ) { + body = ObjectSerializer.deserialize(body, 'FileBucket'); + resolve({ response: response, body: body }); + } else { + reject(new HttpError(response, body, response.statusCode)); + } + } + }); + } + ); + }); + } + /** + * + * @summary Get File Buckets by Config Id and Config Env. + * @param configId + */ + public async fileBucketControllerGetBucketsByConfigIdAndEnv( + configId: string, + options: { headers: { [name: string]: string } } = { headers: {} } + ): Promise<{ response: http.IncomingMessage; body: Array }> { + const localVarPath = + this.basePath + + '/file/bucket/{configId}'.replace( + '{' + 'configId' + '}', + encodeURIComponent(String(configId)) + ); + let localVarQueryParameters: any = {}; + let localVarHeaderParams: any = (Object).assign( + {}, + this._defaultHeaders + ); + const produces = ['application/json']; + // give precedence to 'application/json' + if (produces.indexOf('application/json') >= 0) { + localVarHeaderParams.Accept = 'application/json'; + } else { + localVarHeaderParams.Accept = produces.join(','); + } + let localVarFormParams: any = {}; + + // verify required parameter 'configId' is not null or undefined + if (configId === null || configId === undefined) { + throw new Error( + 'Required parameter configId was null or undefined when calling fileBucketControllerGetBucketsByConfigIdAndEnv.' + ); + } + + (Object).assign(localVarHeaderParams, options.headers); + + let localVarUseFormData = false; + + let localVarRequestOptions: localVarRequest.Options = { + method: 'GET', + qs: localVarQueryParameters, + headers: localVarHeaderParams, + uri: localVarPath, + useQuerystring: this._useQuerystring, + json: true, + }; + + let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } + authenticationPromise = authenticationPromise.then(() => + this.authentications.default.applyToRequest(localVarRequestOptions) + ); + + let interceptorPromise = authenticationPromise; + for (const interceptor of this.interceptors) { + interceptorPromise = interceptorPromise.then(() => + interceptor(localVarRequestOptions) + ); + } + + return interceptorPromise.then(() => { + if (Object.keys(localVarFormParams).length) { + if (localVarUseFormData) { + (localVarRequestOptions).formData = localVarFormParams; + } else { + localVarRequestOptions.form = localVarFormParams; + } + } + return new Promise<{ + response: http.IncomingMessage; + body: Array; + }>((resolve, reject) => { + localVarRequest(localVarRequestOptions, (error, response, body) => { + if (error) { + reject(error); + } else { + if ( + response.statusCode && + response.statusCode >= 200 && + response.statusCode <= 299 + ) { + body = ObjectSerializer.deserialize(body, 'Array'); + resolve({ response: response, body: body }); + } else { + reject(new HttpError(response, body, response.statusCode)); + } + } + }); + }); + }); + } /** * * @summary Registers a File Bucket. diff --git a/src/internal/api/fileProviderApi.ts b/src/internal/api/fileProviderApi.ts index 3db402e..03e935b 100644 --- a/src/internal/api/fileProviderApi.ts +++ b/src/internal/api/fileProviderApi.ts @@ -14,7 +14,8 @@ import localVarRequest from 'request'; import http from 'http'; /* tslint:disable:no-unused-locals */ -import { FileProviderResponse } from '../model/fileProviderResponse'; +import { FileProvider } from '../model/fileProvider'; +import { FileProviderPartial } from '../model/fileProviderPartial'; import { RegisterFileProviderModel } from '../model/registerFileProviderModel'; import { @@ -105,6 +106,186 @@ export class FileProviderApi { this.interceptors.push(interceptor); } + /** + * + * @summary Delete File Provider. + * @param name + */ + public async fileProviderControllerDeleteFileProvider( + name: string, + options: { headers: { [name: string]: string } } = { headers: {} } + ): Promise<{ response: http.IncomingMessage; body: FileProviderPartial }> { + const localVarPath = + this.basePath + + '/file/provider/{name}'.replace( + '{' + 'name' + '}', + encodeURIComponent(String(name)) + ); + let localVarQueryParameters: any = {}; + let localVarHeaderParams: any = (Object).assign( + {}, + this._defaultHeaders + ); + const produces = ['application/json']; + // give precedence to 'application/json' + if (produces.indexOf('application/json') >= 0) { + localVarHeaderParams.Accept = 'application/json'; + } else { + localVarHeaderParams.Accept = produces.join(','); + } + let localVarFormParams: any = {}; + + // verify required parameter 'name' is not null or undefined + if (name === null || name === undefined) { + throw new Error( + 'Required parameter name was null or undefined when calling fileProviderControllerDeleteFileProvider.' + ); + } + + (Object).assign(localVarHeaderParams, options.headers); + + let localVarUseFormData = false; + + let localVarRequestOptions: localVarRequest.Options = { + method: 'DELETE', + qs: localVarQueryParameters, + headers: localVarHeaderParams, + uri: localVarPath, + useQuerystring: this._useQuerystring, + json: true, + }; + + let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } + authenticationPromise = authenticationPromise.then(() => + this.authentications.default.applyToRequest(localVarRequestOptions) + ); + + let interceptorPromise = authenticationPromise; + for (const interceptor of this.interceptors) { + interceptorPromise = interceptorPromise.then(() => + interceptor(localVarRequestOptions) + ); + } + + return interceptorPromise.then(() => { + if (Object.keys(localVarFormParams).length) { + if (localVarUseFormData) { + (localVarRequestOptions).formData = localVarFormParams; + } else { + localVarRequestOptions.form = localVarFormParams; + } + } + return new Promise<{ + response: http.IncomingMessage; + body: FileProviderPartial; + }>((resolve, reject) => { + localVarRequest(localVarRequestOptions, (error, response, body) => { + if (error) { + reject(error); + } else { + if ( + response.statusCode && + response.statusCode >= 200 && + response.statusCode <= 299 + ) { + body = ObjectSerializer.deserialize(body, 'FileProviderPartial'); + resolve({ response: response, body: body }); + } else { + reject(new HttpError(response, body, response.statusCode)); + } + } + }); + }); + }); + } + /** + * + * @summary Get All File Providers. + */ + public async fileProviderControllerGetAllFileProviders( + options: { headers: { [name: string]: string } } = { headers: {} } + ): Promise<{ response: http.IncomingMessage; body: Array }> { + const localVarPath = this.basePath + '/file/provider/all'; + let localVarQueryParameters: any = {}; + let localVarHeaderParams: any = (Object).assign( + {}, + this._defaultHeaders + ); + const produces = ['application/json']; + // give precedence to 'application/json' + if (produces.indexOf('application/json') >= 0) { + localVarHeaderParams.Accept = 'application/json'; + } else { + localVarHeaderParams.Accept = produces.join(','); + } + let localVarFormParams: any = {}; + + (Object).assign(localVarHeaderParams, options.headers); + + let localVarUseFormData = false; + + let localVarRequestOptions: localVarRequest.Options = { + method: 'GET', + qs: localVarQueryParameters, + headers: localVarHeaderParams, + uri: localVarPath, + useQuerystring: this._useQuerystring, + json: true, + }; + + let authenticationPromise = Promise.resolve(); + if (this.authentications.API_Key.accessToken) { + authenticationPromise = authenticationPromise.then(() => + this.authentications.API_Key.applyToRequest(localVarRequestOptions) + ); + } + authenticationPromise = authenticationPromise.then(() => + this.authentications.default.applyToRequest(localVarRequestOptions) + ); + + let interceptorPromise = authenticationPromise; + for (const interceptor of this.interceptors) { + interceptorPromise = interceptorPromise.then(() => + interceptor(localVarRequestOptions) + ); + } + + return interceptorPromise.then(() => { + if (Object.keys(localVarFormParams).length) { + if (localVarUseFormData) { + (localVarRequestOptions).formData = localVarFormParams; + } else { + localVarRequestOptions.form = localVarFormParams; + } + } + return new Promise<{ + response: http.IncomingMessage; + body: Array; + }>((resolve, reject) => { + localVarRequest(localVarRequestOptions, (error, response, body) => { + if (error) { + reject(error); + } else { + if ( + response.statusCode && + response.statusCode >= 200 && + response.statusCode <= 299 + ) { + body = ObjectSerializer.deserialize(body, 'Array'); + resolve({ response: response, body: body }); + } else { + reject(new HttpError(response, body, response.statusCode)); + } + } + }); + }); + }); + } /** * * @summary Registers a File Provider. @@ -113,7 +294,7 @@ export class FileProviderApi { public async fileProviderControllerRegisterFileProvider( registerFileProviderModel: RegisterFileProviderModel, options: { headers: { [name: string]: string } } = { headers: {} } - ): Promise<{ response: http.IncomingMessage; body: FileProviderResponse }> { + ): Promise<{ response: http.IncomingMessage; body: FileProviderPartial }> { const localVarPath = this.basePath + '/file/provider'; let localVarQueryParameters: any = {}; let localVarHeaderParams: any = (Object).assign( @@ -183,7 +364,7 @@ export class FileProviderApi { } return new Promise<{ response: http.IncomingMessage; - body: FileProviderResponse; + body: FileProviderPartial; }>((resolve, reject) => { localVarRequest(localVarRequestOptions, (error, response, body) => { if (error) { @@ -194,7 +375,7 @@ export class FileProviderApi { response.statusCode >= 200 && response.statusCode <= 299 ) { - body = ObjectSerializer.deserialize(body, 'FileProviderResponse'); + body = ObjectSerializer.deserialize(body, 'FileProviderPartial'); resolve({ response: response, body: body }); } else { reject(new HttpError(response, body, response.statusCode)); diff --git a/src/internal/model/deleteFileBucketModel.ts b/src/internal/model/deleteFileBucketModel.ts new file mode 100644 index 0000000..92e5114 --- /dev/null +++ b/src/internal/model/deleteFileBucketModel.ts @@ -0,0 +1,56 @@ +/** + * Juno + * Juno Public API Docs + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { RequestFile } from './models'; + +export class DeleteFileBucketModel { + /** + * The unique name of the bucket + */ + 'name': string; + /** + * Configuration ID for the bucket + */ + 'configId': number; + /** + * The file provider name associated with the bucket + */ + 'fileProviderName': string; + + static discriminator: string | undefined = undefined; + + static attributeTypeMap: Array<{ + name: string; + baseName: string; + type: string; + }> = [ + { + name: 'name', + baseName: 'name', + type: 'string', + }, + { + name: 'configId', + baseName: 'configId', + type: 'number', + }, + { + name: 'fileProviderName', + baseName: 'fileProviderName', + type: 'string', + }, + ]; + + static getAttributeTypeMap() { + return DeleteFileBucketModel.attributeTypeMap; + } +} diff --git a/src/internal/model/fileProvider.ts b/src/internal/model/fileProvider.ts new file mode 100644 index 0000000..a6eae98 --- /dev/null +++ b/src/internal/model/fileProvider.ts @@ -0,0 +1,74 @@ +/** + * Juno + * Juno Public API Docs + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { RequestFile } from './models'; +import { AccessKey } from './accessKey'; + +export class FileProvider { + /** + * The access key to register with + */ + 'accessKey': AccessKey; + /** + * The base url associated with file provider. + */ + 'baseUrl': string; + /** + * The file provider name being registered. + */ + 'providerName': string; + /** + * File provider type (one of S3 or AZURE) + */ + 'type': FileProvider.TypeEnum; + + static discriminator: string | undefined = undefined; + + static attributeTypeMap: Array<{ + name: string; + baseName: string; + type: string; + }> = [ + { + name: 'accessKey', + baseName: 'accessKey', + type: 'AccessKey', + }, + { + name: 'baseUrl', + baseName: 'baseUrl', + type: 'string', + }, + { + name: 'providerName', + baseName: 'providerName', + type: 'string', + }, + { + name: 'type', + baseName: 'type', + type: 'FileProvider.TypeEnum', + }, + ]; + + static getAttributeTypeMap() { + return FileProvider.attributeTypeMap; + } +} + +export namespace FileProvider { + export enum TypeEnum { + _0 = '0', + _1 = '1', + _12 = '-1', + } +} diff --git a/src/internal/model/fileProviderPartial.ts b/src/internal/model/fileProviderPartial.ts new file mode 100644 index 0000000..0c8ce79 --- /dev/null +++ b/src/internal/model/fileProviderPartial.ts @@ -0,0 +1,47 @@ +/** + * Juno + * Juno Public API Docs + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { RequestFile } from './models'; + +export class FileProviderPartial { + /** + * The unique provider name of the file provider + */ + 'providerName': string; + /** + * The metadata of the file provider + */ + 'metadata': string; + + static discriminator: string | undefined = undefined; + + static attributeTypeMap: Array<{ + name: string; + baseName: string; + type: string; + }> = [ + { + name: 'providerName', + baseName: 'providerName', + type: 'string', + }, + { + name: 'metadata', + baseName: 'metadata', + type: 'string', + }, + ]; + + static getAttributeTypeMap() { + return FileProviderPartial.attributeTypeMap; + } +} diff --git a/src/internal/model/models.ts b/src/internal/model/models.ts index ca90a55..b8455bb 100644 --- a/src/internal/model/models.ts +++ b/src/internal/model/models.ts @@ -12,6 +12,7 @@ export * from './customEventResponse'; export * from './customEventTypeResponse'; export * from './customGraphType'; export * from './customGraphTypeResponse'; +export * from './deleteFileBucketModel'; export * from './downloadFileModel'; export * from './downloadFileResponse'; export * from './emailConfigResponse'; @@ -22,7 +23,8 @@ export * from './emailSender'; export * from './emailSenderSendEmailModel'; export * from './fileBucket'; export * from './fileConfigResponse'; -export * from './fileProviderResponse'; +export * from './fileProvider'; +export * from './fileProviderPartial'; export * from './getAllClickEventsResponse'; export * from './getAllCustomEventTypeResponse'; export * from './getAllCustomEventsResponse'; @@ -95,6 +97,7 @@ import { CustomEventResponse } from './customEventResponse'; import { CustomEventTypeResponse } from './customEventTypeResponse'; import { CustomGraphType } from './customGraphType'; import { CustomGraphTypeResponse } from './customGraphTypeResponse'; +import { DeleteFileBucketModel } from './deleteFileBucketModel'; import { DownloadFileModel } from './downloadFileModel'; import { DownloadFileResponse } from './downloadFileResponse'; import { EmailConfigResponse } from './emailConfigResponse'; @@ -105,7 +108,8 @@ import { EmailSender } from './emailSender'; import { EmailSenderSendEmailModel } from './emailSenderSendEmailModel'; import { FileBucket } from './fileBucket'; import { FileConfigResponse } from './fileConfigResponse'; -import { FileProviderResponse } from './fileProviderResponse'; +import { FileProvider } from './fileProvider'; +import { FileProviderPartial } from './fileProviderPartial'; import { GetAllClickEventsResponse } from './getAllClickEventsResponse'; import { GetAllCustomEventTypeResponse } from './getAllCustomEventTypeResponse'; import { GetAllCustomEventsResponse } from './getAllCustomEventsResponse'; @@ -168,6 +172,7 @@ let primitives = [ let enumsMap: { [index: string]: any } = { AggregateInterval: AggregateInterval, + 'FileProvider.TypeEnum': FileProvider.TypeEnum, 'RegisterFileProviderModel.TypeEnum': RegisterFileProviderModel.TypeEnum, 'SetUserTypeModel.TypeEnum': SetUserTypeModel.TypeEnum, 'UserResponse.TypeEnum': UserResponse.TypeEnum, @@ -185,6 +190,7 @@ let typeMap: { [index: string]: any } = { CustomEventTypeResponse: CustomEventTypeResponse, CustomGraphType: CustomGraphType, CustomGraphTypeResponse: CustomGraphTypeResponse, + DeleteFileBucketModel: DeleteFileBucketModel, DownloadFileModel: DownloadFileModel, DownloadFileResponse: DownloadFileResponse, EmailConfigResponse: EmailConfigResponse, @@ -195,7 +201,8 @@ let typeMap: { [index: string]: any } = { EmailSenderSendEmailModel: EmailSenderSendEmailModel, FileBucket: FileBucket, FileConfigResponse: FileConfigResponse, - FileProviderResponse: FileProviderResponse, + FileProvider: FileProvider, + FileProviderPartial: FileProviderPartial, GetAllClickEventsResponse: GetAllClickEventsResponse, GetAllCustomEventTypeResponse: GetAllCustomEventTypeResponse, GetAllCustomEventsResponse: GetAllCustomEventsResponse, From 14b1e36ee197fccf6de52ef4b1d6a6da02eb2cbb Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 02:56:02 -0500 Subject: [PATCH 07/13] fix: typing change --- src/lib/file.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/file.ts b/src/lib/file.ts index bf9c594..453ee46 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -7,7 +7,7 @@ import { FileConfigResponse, FileDownloadApi, FileProviderApi, - FileProviderResponse, + FileProviderPartial, FileUploadApi, RegisterFileBucketModel, RegisterFileProviderModel, @@ -97,7 +97,7 @@ export class FileAPI { providerName: string; type: RegisterFileProviderModel.TypeEnum; accessKey: { accessKeyId: string; secretAccessKey: string }; - }): Promise { + }): Promise { const { baseUrl, providerName, type, accessKey } = options; validateString(baseUrl, 'baseUrl must be non-empty'); From 79849c5f1d96ab9b5ba970734cd9ba86fc4a4162 Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 03:11:15 -0500 Subject: [PATCH 08/13] feat: add provider routes --- src/lib/file.ts | 66 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/src/lib/file.ts b/src/lib/file.ts index 453ee46..66e95e3 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -6,6 +6,7 @@ import { FileConfigApi, FileConfigResponse, FileDownloadApi, + FileProvider, FileProviderApi, FileProviderPartial, FileUploadApi, @@ -92,12 +93,15 @@ export class FileAPI { return res.body; } - async registerProvider(options: { - baseUrl: string; - providerName: string; - type: RegisterFileProviderModel.TypeEnum; - accessKey: { accessKeyId: string; secretAccessKey: string }; - }): Promise { + async registerProvider( + options: { + baseUrl: string; + providerName: string; + type: RegisterFileProviderModel.TypeEnum; + accessKey: { accessKeyId: string; secretAccessKey: string }; + }, + credentials?: ApiCredentials + ): Promise { const { baseUrl, providerName, type, accessKey } = options; validateString(baseUrl, 'baseUrl must be non-empty'); @@ -108,6 +112,14 @@ export class FileAPI { 'secretAccessKey must be non-empty' ); + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + const model = new RegisterFileProviderModel(); (model as any).accessKey = accessKey as any; model.baseUrl = baseUrl; @@ -115,7 +127,47 @@ export class FileAPI { model.type = type; const res = - await this.providerApi.fileProviderControllerRegisterFileProvider(model); + await this.providerApi.fileProviderControllerRegisterFileProvider(model, { + headers, + }); + return res.body; + } + + async deleteProvider( + name: string, + credentials?: ApiCredentials + ): Promise { + validateString(name, 'Provider name must be non-empty'); + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = await this.providerApi.fileProviderControllerDeleteFileProvider( + name, + { headers } + ); + return res.body; + } + + async getAllFileProviders( + credentials?: ApiCredentials + ): Promise> { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = + await this.providerApi.fileProviderControllerGetAllFileProviders({ + headers, + }); return res.body; } From 50750ec89fd03fb4a8a5f66617ab69fb922a1d2e Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 03:25:17 -0500 Subject: [PATCH 09/13] feat: add bucket routes --- src/lib/file.ts | 75 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/src/lib/file.ts b/src/lib/file.ts index 66e95e3..59a10f7 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -1,4 +1,5 @@ import { + DeleteFileBucketModel, DownloadFileModel, DownloadFileResponse, FileBucket, @@ -155,7 +156,7 @@ export class FileAPI { async getAllFileProviders( credentials?: ApiCredentials - ): Promise> { + ): Promise { const headers: any = {}; if (credentials?.userJwt) { headers['X-User-JWT'] = credentials.userJwt; @@ -171,12 +172,15 @@ export class FileAPI { return res.body; } - async registerBucket(options: { - name: string; - configId: number; - fileProviderName: string; - fileServiceFile?: Array; - }): Promise { + async registerBucket( + options: { + name: string; + configId: number; + fileProviderName: string; + fileServiceFile?: Array; + }, + credentials?: ApiCredentials + ): Promise { const { name, configId, fileProviderName, fileServiceFile } = options; validateString(name, 'Bucket name must be non-empty'); @@ -185,6 +189,14 @@ export class FileAPI { } validateString(fileProviderName, 'fileProviderName must be non-empty'); + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + const model = new RegisterFileBucketModel(); model.name = name; model.configId = configId; @@ -192,11 +204,58 @@ export class FileAPI { model.fileServiceFile = fileServiceFile ?? []; const res = await this.bucketApi.fileBucketControllerRegisterFileBucket( - model + model, + { headers } ); return res.body; } + async deleteBucket( + options: DeleteFileBucketModel, + credentials?: ApiCredentials + ): Promise { + const { name, configId, fileProviderName } = options; + validateString(name, 'Bucket name must be non-empty'); + if (typeof configId !== 'number') { + throw new JunoValidationError('configId must be a number'); + } + validateString(fileProviderName, 'fileProviderName must be non-empty'); + + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = await this.bucketApi.fileBucketControllerDeleteFileBucket( + options, + { headers } + ); + return res.body; + } + + async getBucketsByConfigIdAndEnv( + configId: string, + credentials?: ApiCredentials + ): Promise { + const headers: any = {}; + if (credentials?.userJwt) { + headers['X-User-JWT'] = credentials.userJwt; + } + if (credentials?.projectId !== undefined) { + headers['X-Project-Id'] = String(credentials.projectId); + } + + const res = + await this.bucketApi.fileBucketControllerGetBucketsByConfigIdAndEnv( + configId, + { headers } + ); + return res.body; + } + async uploadFile(options: { fileName: string; bucketName: string; From 4810c65d854258b881aec3326394bec63a66064d Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 21:17:34 -0500 Subject: [PATCH 10/13] fix: enum to string --- src/internal/model/fileProvider.ts | 13 ++----------- src/internal/model/models.ts | 1 - 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/internal/model/fileProvider.ts b/src/internal/model/fileProvider.ts index a6eae98..37a8363 100644 --- a/src/internal/model/fileProvider.ts +++ b/src/internal/model/fileProvider.ts @@ -10,7 +10,6 @@ * Do not edit the class manually. */ -import { RequestFile } from './models'; import { AccessKey } from './accessKey'; export class FileProvider { @@ -29,7 +28,7 @@ export class FileProvider { /** * File provider type (one of S3 or AZURE) */ - 'type': FileProvider.TypeEnum; + 'type': string; static discriminator: string | undefined = undefined; @@ -56,7 +55,7 @@ export class FileProvider { { name: 'type', baseName: 'type', - type: 'FileProvider.TypeEnum', + type: 'string', }, ]; @@ -64,11 +63,3 @@ export class FileProvider { return FileProvider.attributeTypeMap; } } - -export namespace FileProvider { - export enum TypeEnum { - _0 = '0', - _1 = '1', - _12 = '-1', - } -} diff --git a/src/internal/model/models.ts b/src/internal/model/models.ts index b8455bb..1ed17b7 100644 --- a/src/internal/model/models.ts +++ b/src/internal/model/models.ts @@ -172,7 +172,6 @@ let primitives = [ let enumsMap: { [index: string]: any } = { AggregateInterval: AggregateInterval, - 'FileProvider.TypeEnum': FileProvider.TypeEnum, 'RegisterFileProviderModel.TypeEnum': RegisterFileProviderModel.TypeEnum, 'SetUserTypeModel.TypeEnum': SetUserTypeModel.TypeEnum, 'UserResponse.TypeEnum': UserResponse.TypeEnum, From c9127cbb1fed66b35cb23352d8db743efdd38477 Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 21:37:54 -0500 Subject: [PATCH 11/13] fix: take string type --- src/internal/model/models.ts | 1 - src/internal/model/registerFileProviderModel.ts | 13 ++----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/internal/model/models.ts b/src/internal/model/models.ts index 1ed17b7..556227b 100644 --- a/src/internal/model/models.ts +++ b/src/internal/model/models.ts @@ -172,7 +172,6 @@ let primitives = [ let enumsMap: { [index: string]: any } = { AggregateInterval: AggregateInterval, - 'RegisterFileProviderModel.TypeEnum': RegisterFileProviderModel.TypeEnum, 'SetUserTypeModel.TypeEnum': SetUserTypeModel.TypeEnum, 'UserResponse.TypeEnum': UserResponse.TypeEnum, }; diff --git a/src/internal/model/registerFileProviderModel.ts b/src/internal/model/registerFileProviderModel.ts index c0fd10e..4aef5d9 100644 --- a/src/internal/model/registerFileProviderModel.ts +++ b/src/internal/model/registerFileProviderModel.ts @@ -10,7 +10,6 @@ * Do not edit the class manually. */ -import { RequestFile } from './models'; import { AccessKey } from './accessKey'; export class RegisterFileProviderModel { @@ -29,7 +28,7 @@ export class RegisterFileProviderModel { /** * File provider type (one of S3 or AZURE) */ - 'type': RegisterFileProviderModel.TypeEnum; + 'type': string; static discriminator: string | undefined = undefined; @@ -56,7 +55,7 @@ export class RegisterFileProviderModel { { name: 'type', baseName: 'type', - type: 'RegisterFileProviderModel.TypeEnum', + type: 'string', }, ]; @@ -64,11 +63,3 @@ export class RegisterFileProviderModel { return RegisterFileProviderModel.attributeTypeMap; } } - -export namespace RegisterFileProviderModel { - export enum TypeEnum { - _0 = '0', - _1 = '1', - _12 = '-1', - } -} From 046daaf4a54d4633df6d74c00a98c2911df74dc0 Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 21:38:53 -0500 Subject: [PATCH 12/13] fix: wrong type --- src/lib/file.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/file.ts b/src/lib/file.ts index 59a10f7..7c645c6 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -98,7 +98,7 @@ export class FileAPI { options: { baseUrl: string; providerName: string; - type: RegisterFileProviderModel.TypeEnum; + type: string; accessKey: { accessKeyId: string; secretAccessKey: string }; }, credentials?: ApiCredentials From 063d89f26378025a730956ece713ab1eacbe6119 Mon Sep 17 00:00:00 2001 From: Long Lam Date: Mon, 17 Nov 2025 23:25:42 -0500 Subject: [PATCH 13/13] fix: key names --- src/lib/file.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/file.ts b/src/lib/file.ts index 7c645c6..1569a4b 100644 --- a/src/lib/file.ts +++ b/src/lib/file.ts @@ -99,7 +99,7 @@ export class FileAPI { baseUrl: string; providerName: string; type: string; - accessKey: { accessKeyId: string; secretAccessKey: string }; + accessKey: { publicAccessKey: string; privateAccessKey: string }; }, credentials?: ApiCredentials ): Promise { @@ -107,10 +107,13 @@ export class FileAPI { validateString(baseUrl, 'baseUrl must be non-empty'); validateString(providerName, 'providerName must be non-empty'); - validateString(accessKey?.accessKeyId, 'accessKeyId must be non-empty'); validateString( - accessKey?.secretAccessKey, - 'secretAccessKey must be non-empty' + accessKey?.publicAccessKey, + 'publicAccessKey must be non-empty' + ); + validateString( + accessKey?.privateAccessKey, + 'privateAccessKey must be non-empty' ); const headers: any = {};