Skip to content

Commit 9d6535f

Browse files
v1.4.0 (#1045)
2 parents b8c8e84 + a59cab5 commit 9d6535f

File tree

20 files changed

+130
-28
lines changed

20 files changed

+130
-28
lines changed

apps/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@impler/api",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"author": "implerhq",
55
"license": "MIT",
66
"private": true,

apps/api/src/app/shared/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ export const APIMessages = {
4242
ONBOARD_TEMPLATE_SHEET_NOT_FOUND: 'No sheets found in the workbook',
4343
ONBOARD_TEMPLATE_FILE_EMPTY: 'File is empty or invalid',
4444
ONBOARD_TEMPLATE_FILE_EMPTY_RECORDS: 'The file contains empty records',
45+
46+
INVALID_API_RESPONSE_STRUCTURE: `Invalid API response structure. Please recheck the URL and ensure the API is correctly configured to return data.`,
47+
DATATYPE_EMPTY: `The datatype appears to be empty. Please add at least one entry and verify the URL points to the correct data source.`,
4548
};
4649

4750
export const CONSTANTS = {

apps/api/src/app/shared/services/bubble-io.service.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
33
import { BubbleBaseService } from '@impler/services';
44
import { BubbleDestinationEntity } from '@impler/dal';
55
import { ColumnTypesEnum, DEFAULT_KEYS_OBJ, IColumn } from '@impler/shared';
6+
import { APIMessages } from '@shared/constants';
67

78
interface IThingsResponse {
89
response: {
@@ -17,13 +18,19 @@ interface IThingsResponse {
1718
export class BubbleIoService extends BubbleBaseService {
1819
async getDatatypeData(data: Omit<BubbleDestinationEntity, '_id' | '_templateId'>) {
1920
try {
20-
const response = await axios.get<IThingsResponse>(data.bubbleAppUrl, {
21+
const response = await axios.get<IThingsResponse>(this.createBubbleIoUrl(data.bubbleAppUrl), {
2122
headers: {
2223
Authorization: `Bearer ${data.apiPrivateKey}`,
2324
},
2425
});
25-
if (!response.data.response.results.length)
26-
throw new Error('Datatype is empty. Please add at least one entry to the datatype');
26+
27+
if (!Array.isArray(response.data.response.results)) {
28+
throw new Error(APIMessages.INVALID_API_RESPONSE_STRUCTURE);
29+
}
30+
31+
if (response.data.response.results.length === 0) {
32+
throw new Error(APIMessages.DATATYPE_EMPTY);
33+
}
2734

2835
return response.data.response.results;
2936
} catch (error: unknown) {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
*This migrartion is for the having only the bubbleAppUrl or streamlined using this send the bubble data to the specified destionation, the
3+
*bubbleAppUrl contains everything the version the datatype and other things, if these fields are not there we construct using the existing data
4+
*/
5+
import '../../config';
6+
import { AppModule } from '../../app.module';
7+
8+
import { NestFactory } from '@nestjs/core';
9+
import { BubbleDestinationRepository } from '@impler/dal';
10+
11+
export async function run() {
12+
const bubbleDestinationRepository: BubbleDestinationRepository = new BubbleDestinationRepository();
13+
14+
// eslint-disable-next-line no-console
15+
console.log('start migration - Constructing, Generating and Updating the bubbleAppUrl');
16+
17+
// Init the mongodb connection
18+
const app = await NestFactory.create(AppModule, {
19+
logger: false,
20+
});
21+
22+
const constructBubbleUrl = async (bubbleDestination: any | undefined | null) => {
23+
const bubbleAppUrl = [{ _id: '', bubbleAppUrl: '' }];
24+
bubbleDestination.forEach((destination) => {
25+
/*
26+
* If no direct URL, try to construct it from available fields
27+
* Type assertion to access potential additional properties
28+
*/
29+
const customDomainName = destination.customDomainName as string | undefined;
30+
const appName = destination.appName as string | undefined;
31+
const environment = destination.environment as string | undefined;
32+
const datatype = destination.datatype as string | undefined;
33+
34+
if (customDomainName || appName) {
35+
// Use custom domain if available, otherwise use app name with bubbleapps.io
36+
let baseUrl = customDomainName ? `https://${customDomainName}` : `https://${appName}.bubbleapps.io`;
37+
38+
// Add version-test for development environment if specified
39+
if (environment === 'development') {
40+
baseUrl += '/version-test';
41+
}
42+
43+
// Construct the full URL with the data type if available
44+
if (datatype) {
45+
bubbleAppUrl.push({ _id: destination._id, bubbleAppUrl: `${baseUrl}/api/1.1/obj/${datatype}` });
46+
}
47+
}
48+
});
49+
50+
return bubbleAppUrl;
51+
};
52+
53+
const bubbleDestinationLink = await bubbleDestinationRepository.find({
54+
bubbleAppUrl: { $exists: true, $ne: null },
55+
});
56+
57+
const bubbleDestinations = await bubbleDestinationRepository.find({});
58+
const bubbleAppUrls = await constructBubbleUrl(bubbleDestinations);
59+
bubbleDestinationLink.map((link) => {
60+
bubbleAppUrls.push({ _id: link._id, bubbleAppUrl: link.bubbleAppUrl });
61+
});
62+
63+
bubbleAppUrls.map(async (url) => {
64+
if (!url._id || !url.bubbleAppUrl) return;
65+
66+
try {
67+
await bubbleDestinationRepository.update({ _id: url._id }, { $set: { bubbleAppUrl: url.bubbleAppUrl } });
68+
} catch (error) {
69+
return null;
70+
}
71+
});
72+
73+
// eslint-disable-next-line no-console
74+
console.log('end migration - Constructed, Generated and Updated the bubbleAppUrl');
75+
76+
app.close();
77+
process.exit(0);
78+
}
79+
run();

apps/queue-manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@impler/queue-manager",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"author": "implerhq",
55
"license": "MIT",
66
"private": true,

apps/queue-manager/src/consumers/send-bubble-data.consumer.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class SendBubbleDataConsumer extends BaseConsumer {
4242
const uploadId = data.uploadId;
4343
const cachedData = data.cache || (await this.getInitialCachedData(uploadId));
4444

45-
if (cachedData && cachedData.bubbleUrl) {
45+
if (cachedData && cachedData.bubbleAppUrl) {
4646
// Get valid data information
4747
let allDataJson: null | any[] = null;
4848
if (cachedData.allDataFilePath) {
@@ -67,7 +67,7 @@ export class SendBubbleDataConsumer extends BaseConsumer {
6767
uploadId,
6868
page,
6969
method: 'POST',
70-
url: cachedData.bubbleUrl,
70+
url: cachedData.bubbleAppUrl,
7171
headers: {
7272
Authorization: `Bearer ${cachedData.apiPrivateKey}`,
7373
'Content-Type': 'text/plain',
@@ -76,7 +76,7 @@ export class SendBubbleDataConsumer extends BaseConsumer {
7676

7777
await this.makeResponseEntry(
7878
response,
79-
{ bubbleAppUrl: cachedData.bubbleUrl, datatype: cachedData.datatype },
79+
{ bubbleAppUrl: cachedData.bubbleAppUrl, datatype: cachedData.datatype },
8080
cachedData.name,
8181
cachedData.email
8282
);
@@ -142,7 +142,14 @@ export class SendBubbleDataConsumer extends BaseConsumer {
142142
const templateData = await this.templateRepository.findById(uploadata._templateId, 'name');
143143

144144
const bubbleDestination = await this.bubbleDestinationRepository.findOne({ _templateId: uploadata._templateId });
145-
const bubbleUrl = bubbleDestination.bubbleAppUrl;
145+
if (!bubbleDestination) return null;
146+
147+
const bubbleAppUrl = bubbleDestination.bubbleAppUrl;
148+
149+
// If still no URL, return null as we can't proceed without a valid URL
150+
if (!bubbleAppUrl) {
151+
return null;
152+
}
146153

147154
const defaultValueObj = {};
148155
const customSchema = JSON.parse(uploadata.customSchema) as ITemplateSchemaItem;
@@ -163,7 +170,7 @@ export class SendBubbleDataConsumer extends BaseConsumer {
163170

164171
return {
165172
page: 1,
166-
bubbleUrl,
173+
bubbleAppUrl,
167174
chunkSize: 500,
168175
email: userEmail,
169176
datatype: bubbleDestination.datatype,

apps/web/components/imports/destination/Destination.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ export function Destination({ template }: DestinationProps) {
147147
<Input
148148
required
149149
label="Bubble App URL"
150-
placeholder="Bubble App URL"
150+
placeholder="https://acme.in/api/1.1/obj/customers"
151+
description={
152+
<>
153+
<div>Example with default domain: https://your-app.bubbleapps.io/api/1.1/obj/your-datatype</div>
154+
<div>Example with custom domain: https://yourapp.com/api/1.1/obj/your-datatype</div>
155+
</>
156+
}
151157
{...register('bubbleIo.bubbleAppUrl')}
152158
error={errors?.bubbleIo?.bubbleAppUrl?.message}
153159
/>

apps/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@impler/web",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"author": "implerhq",
55
"license": "MIT",
66
"private": true,

apps/widget/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@impler/widget",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"author": "implerhq",
55
"license": "MIT",
66
"private": true,

apps/widget/src/hooks/Phase3/usePhase3.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ export function usePhase3({ onNext }: IUsePhase3Props) {
196196
setTotalPages(reviewDataResponse.totalPages);
197197
},
198198
onError(error: IErrorObject) {
199-
notifier.showError({ message: 'Hellow World', title: error.error });
199+
notifier.showError({ message: error.message, title: error.error });
200200
},
201201
}
202202
);

0 commit comments

Comments
 (0)