Compare commits

...

4 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
c3a4fe6b37 Merge pull request #924 from bigcapitalhq/20260201-180532-f578
fix(webapp): normalize api path
2026-02-01 18:06:51 +02:00
Ahmed Bouhuolia
02be959461 fix(webapp): normalize api path 2026-02-01 18:05:51 +02:00
Ahmed Bouhuolia
d5bf56e333 Merge pull request #923 from bigcapitalhq/20260201-165255-f063
fix(server): copy .js migration files
2026-02-01 16:56:49 +02:00
Ahmed Bouhuolia
e3182c15b3 fix(server): copy .js migration files 2026-02-01 16:53:21 +02:00
14 changed files with 31 additions and 47 deletions

View File

@@ -7,7 +7,7 @@
"deleteOutDir": true, "deleteOutDir": true,
"assets": [ "assets": [
{ "include": "i18n/**/*", "watchAssets": true }, { "include": "i18n/**/*", "watchAssets": true },
{ "include": "database/**/*", "watchAssets": true } { "include": "database/**/*", "exclude": "**/*.ts", "watchAssets": true }
] ]
}, },
"projects": { "projects": {

View File

@@ -1,10 +1,6 @@
import { Processor, WorkerHost } from '@nestjs/bullmq'; import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Scope } from '@nestjs/common'; import { Scope } from '@nestjs/common';
import { import { SendResetPasswordMailQueue } from '../Auth.constants';
SendResetPasswordMailJob,
SendResetPasswordMailQueue,
} from '../Auth.constants';
import { Process } from '@nestjs/bull';
import { Job } from 'bullmq'; import { Job } from 'bullmq';
import { AuthenticationMailMesssages } from '../AuthMailMessages.esrvice'; import { AuthenticationMailMesssages } from '../AuthMailMessages.esrvice';
import { MailTransporter } from '@/modules/Mail/MailTransporter.service'; import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
@@ -23,7 +19,6 @@ export class SendResetPasswordMailProcessor extends WorkerHost {
super(); super();
} }
@Process(SendResetPasswordMailJob)
async process(job: Job<SendResetPasswordMailJobPayload>) { async process(job: Job<SendResetPasswordMailJobPayload>) {
try { try {
await this.authMailMesssages.sendResetPasswordMail( await this.authMailMesssages.sendResetPasswordMail(

View File

@@ -1,11 +1,7 @@
import { Scope } from '@nestjs/common'; import { Scope } from '@nestjs/common';
import { Job } from 'bullmq'; import { Job } from 'bullmq';
import { Process } from '@nestjs/bull';
import { Processor, WorkerHost } from '@nestjs/bullmq'; import { Processor, WorkerHost } from '@nestjs/bullmq';
import { import { SendSignupVerificationMailQueue } from '../Auth.constants';
SendSignupVerificationMailJob,
SendSignupVerificationMailQueue,
} from '../Auth.constants';
import { MailTransporter } from '@/modules/Mail/MailTransporter.service'; import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
import { AuthenticationMailMesssages } from '../AuthMailMessages.esrvice'; import { AuthenticationMailMesssages } from '../AuthMailMessages.esrvice';
@@ -21,7 +17,6 @@ export class SendSignupVerificationMailProcessor extends WorkerHost {
super(); super();
} }
@Process(SendSignupVerificationMailJob)
async process(job: Job<SendSignupVerificationMailJobPayload>) { async process(job: Job<SendSignupVerificationMailJobPayload>) {
try { try {
await this.authMailMesssages.sendSignupVerificationMail( await this.authMailMesssages.sendSignupVerificationMail(

View File

@@ -1,11 +1,9 @@
import { Process } from '@nestjs/bull';
import { UseCls } from 'nestjs-cls'; import { UseCls } from 'nestjs-cls';
import { Processor, WorkerHost } from '@nestjs/bullmq'; import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Scope } from '@nestjs/common'; import { Scope } from '@nestjs/common';
import { Job } from 'bullmq'; import { Job } from 'bullmq';
import { import {
PlaidFetchTransitonsEventPayload, PlaidFetchTransitonsEventPayload,
UpdateBankingPlaidTransitionsJob,
UpdateBankingPlaidTransitionsQueueJob, UpdateBankingPlaidTransitionsQueueJob,
} from '../types/BankingPlaid.types'; } from '../types/BankingPlaid.types';
import { PlaidUpdateTransactions } from '../command/PlaidUpdateTransactions'; import { PlaidUpdateTransactions } from '../command/PlaidUpdateTransactions';
@@ -28,7 +26,6 @@ export class PlaidFetchTransactionsProcessor extends WorkerHost {
/** /**
* Triggers the function. * Triggers the function.
*/ */
@Process(UpdateBankingPlaidTransitionsJob)
@UseCls() @UseCls()
async process(job: Job<PlaidFetchTransitonsEventPayload>) { async process(job: Job<PlaidFetchTransitonsEventPayload>) {
const { plaidItemId } = job.data; const { plaidItemId } = job.data;

View File

@@ -7,7 +7,6 @@ import {
RecognizeUncategorizedTransactionsJobPayload, RecognizeUncategorizedTransactionsJobPayload,
RecognizeUncategorizedTransactionsQueue, RecognizeUncategorizedTransactionsQueue,
} from '../_types'; } from '../_types';
import { Process } from '@nestjs/bull';
@Processor({ @Processor({
name: RecognizeUncategorizedTransactionsQueue, name: RecognizeUncategorizedTransactionsQueue,
@@ -28,7 +27,6 @@ export class RegonizeTransactionsPrcessor extends WorkerHost {
/** /**
* Triggers sending invoice mail. * Triggers sending invoice mail.
*/ */
@Process(RecognizeUncategorizedTransactionsQueue)
@UseCls() @UseCls()
async process(job: Job<RecognizeUncategorizedTransactionsJobPayload>) { async process(job: Job<RecognizeUncategorizedTransactionsJobPayload>) {
const { ruleId, transactionsCriteria } = job.data; const { ruleId, transactionsCriteria } = job.data;

View File

@@ -22,6 +22,7 @@ export abstract class BaseCommand extends CommandRunner {
}, },
migrations: { migrations: {
directory: this.configService.get('systemDatabase.migrationDir'), directory: this.configService.get('systemDatabase.migrationDir'),
loadExtensions: ['.js'],
}, },
seeds: { seeds: {
directory: this.configService.get('systemDatabase.seedsDir'), directory: this.configService.get('systemDatabase.seedsDir'),
@@ -43,6 +44,7 @@ export abstract class BaseCommand extends CommandRunner {
}, },
migrations: { migrations: {
directory: this.configService.get('tenantDatabase.migrationsDir') || './src/database/migrations', directory: this.configService.get('tenantDatabase.migrationsDir') || './src/database/migrations',
loadExtensions: ['.js'],
}, },
seeds: { seeds: {
directory: this.configService.get('tenantDatabase.seedsDir') || './src/database/seeds/core', directory: this.configService.get('tenantDatabase.seedsDir') || './src/database/seeds/core',

View File

@@ -7,11 +7,7 @@ import * as moment from 'moment';
import { TenantJobPayload } from '@/interfaces/Tenant'; import { TenantJobPayload } from '@/interfaces/Tenant';
import { InventoryComputeCostService } from '../commands/InventoryComputeCost.service'; import { InventoryComputeCostService } from '../commands/InventoryComputeCost.service';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { import { ComputeItemCostQueue } from '../types/InventoryCost.types';
ComputeItemCostQueue,
ComputeItemCostQueueJob,
} from '../types/InventoryCost.types';
import { Process } from '@nestjs/bull';
interface ComputeItemCostJobPayload extends TenantJobPayload { interface ComputeItemCostJobPayload extends TenantJobPayload {
itemId: number; itemId: number;
@@ -39,7 +35,6 @@ export class ComputeItemCostProcessor extends WorkerHost {
* Process the compute item cost job. * Process the compute item cost job.
* @param {Job<ComputeItemCostJobPayload>} job - The job to process * @param {Job<ComputeItemCostJobPayload>} job - The job to process
*/ */
@Process(ComputeItemCostQueueJob)
@UseCls() @UseCls()
async process(job: Job<ComputeItemCostJobPayload>) { async process(job: Job<ComputeItemCostJobPayload>) {
const { itemId, startingDate, organizationId, userId } = job.data; const { itemId, startingDate, organizationId, userId } = job.data;

View File

@@ -1,8 +1,4 @@
import { Process } from '@nestjs/bull'; import { WriteInventoryTransactionsGLEntriesQueue } from '../types/InventoryCost.types';
import {
WriteInventoryTransactionsGLEntriesQueue,
WriteInventoryTransactionsGLEntriesQueueJob,
} from '../types/InventoryCost.types';
import { Processor, WorkerHost } from '@nestjs/bullmq'; import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Scope } from '@nestjs/common'; import { Scope } from '@nestjs/common';
@@ -15,6 +11,5 @@ export class WriteInventoryTransactionsGLEntriesProcessor extends WorkerHost {
super(); super();
} }
@Process(WriteInventoryTransactionsGLEntriesQueueJob)
async process() {} async process() {}
} }

View File

@@ -2,10 +2,8 @@ import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Scope } from '@nestjs/common'; import { Scope } from '@nestjs/common';
import { Job } from 'bullmq'; import { Job } from 'bullmq';
import { ClsService, UseCls } from 'nestjs-cls'; import { ClsService, UseCls } from 'nestjs-cls';
import { Process } from '@nestjs/bull';
import { import {
OrganizationBuildQueue, OrganizationBuildQueue,
OrganizationBuildQueueJob,
OrganizationBuildQueueJobPayload, OrganizationBuildQueueJobPayload,
} from '../Organization.types'; } from '../Organization.types';
import { BuildOrganizationService } from '../commands/BuildOrganization.service'; import { BuildOrganizationService } from '../commands/BuildOrganization.service';
@@ -22,7 +20,6 @@ export class OrganizationBuildProcessor extends WorkerHost {
super(); super();
} }
@Process(OrganizationBuildQueueJob)
@UseCls() @UseCls()
async process(job: Job<OrganizationBuildQueueJobPayload>) { async process(job: Job<OrganizationBuildQueueJobPayload>) {
console.log('Processing organization build job:', job.id); console.log('Processing organization build job:', job.id);

View File

@@ -22,6 +22,7 @@ const providers = [
}, },
migrations: { migrations: {
directory: configService.get('systemDatabase.migrationDir'), directory: configService.get('systemDatabase.migrationDir'),
loadExtensions: ['.js'],
}, },
seeds: { seeds: {
directory: configService.get('systemDatabase.seedsDir'), directory: configService.get('systemDatabase.seedsDir'),

View File

@@ -33,6 +33,7 @@ export const TenancyDatabaseProxyProvider = ClsModule.forFeatureAsync({
}, },
migrations: { migrations: {
directory: configService.get('tenantDatabase.migrationsDir'), directory: configService.get('tenantDatabase.migrationsDir'),
loadExtensions: ['.js'],
}, },
seeds: { seeds: {
directory: configService.get('tenantDatabase.seedsDir'), directory: configService.get('tenantDatabase.seedsDir'),

View File

@@ -3,6 +3,7 @@ import { useQuery } from 'react-query';
import { castArray, defaultTo } from 'lodash'; import { castArray, defaultTo } from 'lodash';
import { useAuthOrganizationId } from './state'; import { useAuthOrganizationId } from './state';
import useApiRequest from './useRequest'; import useApiRequest from './useRequest';
import { normalizeApiPath } from '../utils';
import { useRef } from 'react'; import { useRef } from 'react';
/** /**
@@ -19,7 +20,11 @@ export function useRequestQuery(query, axios, props) {
const states = useQuery( const states = useQuery(
query, query,
() => apiRequest.http({ ...axios, url: `/api/${axios.url}` }), () =>
apiRequest.http({
...axios,
url: `/api/${normalizeApiPath(axios.url)}`,
}),
props, props,
); );
// Momerize the default data. // Momerize the default data.

View File

@@ -7,7 +7,7 @@ import {
useSetGlobalErrors, useSetGlobalErrors,
useAuthToken, useAuthToken,
} from './state'; } from './state';
import { getCookie } from '../utils'; import { getCookie, normalizeApiPath } from '../utils';
export default function useApiRequest() { export default function useApiRequest() {
const setGlobalErrors = useSetGlobalErrors(); const setGlobalErrors = useSetGlobalErrors();
@@ -93,27 +93,27 @@ export default function useApiRequest() {
http, http,
get(resource, params) { get(resource, params) {
return http.get(`/api/${resource}`, params); return http.get(`/api/${normalizeApiPath(resource)}`, params);
}, },
post(resource, params, config) { post(resource, params, config) {
return http.post(`/api/${resource}`, params, config); return http.post(`/api/${normalizeApiPath(resource)}`, params, config);
}, },
update(resource, slug, params) { update(resource, slug, params) {
return http.put(`/api/${resource}/${slug}`, params); return http.put(`/api/${normalizeApiPath(resource)}/${slug}`, params);
}, },
put(resource, params) { put(resource, params) {
return http.put(`/api/${resource}`, params); return http.put(`/api/${normalizeApiPath(resource)}`, params);
}, },
patch(resource, params, config) { patch(resource, params, config) {
return http.patch(`/api/${resource}`, params, config); return http.patch(`/api/${normalizeApiPath(resource)}`, params, config);
}, },
delete(resource, params) { delete(resource, params) {
return http.delete(`/api/${resource}`, params); return http.delete(`/api/${normalizeApiPath(resource)}`, params);
}, },
}), }),
[http], [http],
@@ -130,22 +130,22 @@ export function useAuthApiRequest() {
() => ({ () => ({
http, http,
get(resource, params) { get(resource, params) {
return http.get(`/api/${resource}`, params); return http.get(`/api/${normalizeApiPath(resource)}`, params);
}, },
post(resource, params, config) { post(resource, params, config) {
return http.post(`/api/${resource}`, params, config); return http.post(`/api/${normalizeApiPath(resource)}`, params, config);
}, },
update(resource, slug, params) { update(resource, slug, params) {
return http.put(`/api/${resource}/${slug}`, params); return http.put(`/api/${normalizeApiPath(resource)}/${slug}`, params);
}, },
put(resource, params) { put(resource, params) {
return http.put(`/api/${resource}`, params); return http.put(`/api/${normalizeApiPath(resource)}`, params);
}, },
patch(resource, params, config) { patch(resource, params, config) {
return http.patch(`/api/${resource}`, params, config); return http.patch(`/api/${normalizeApiPath(resource)}`, params, config);
}, },
delete(resource, params) { delete(resource, params) {
return http.delete(`/api/${resource}`, params); return http.delete(`/api/${normalizeApiPath(resource)}`, params);
}, },
}), }),
[http], [http],

View File

@@ -13,6 +13,9 @@ import jsCookie from 'js-cookie';
import { deepMapKeys } from './map-key-deep'; import { deepMapKeys } from './map-key-deep';
export * from './deep'; export * from './deep';
/** Strips leading slash from a path segment to avoid double slashes when joining with a base (e.g. `/api/` + path). */
export const normalizeApiPath = (path) => (path || '').replace(/^\//, '');
export const getCookie = (name, defaultValue) => export const getCookie = (name, defaultValue) =>
_.defaultTo(jsCookie.get(name), defaultValue); _.defaultTo(jsCookie.get(name), defaultValue);