@ductape/sdk 0.1.12 → 0.1.14
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/dist/api/services/cloudApi.service.d.ts +3 -1
- package/dist/api/services/cloudApi.service.js +11 -2
- package/dist/api/services/cloudApi.service.js.map +1 -1
- package/dist/api/services/webhooksApi.service.js +6 -4
- package/dist/api/services/webhooksApi.service.js.map +1 -1
- package/dist/apps/services/app.service.d.ts +4 -0
- package/dist/apps/services/app.service.js +37 -0
- package/dist/apps/services/app.service.js.map +1 -1
- package/dist/brokers/brokers.service.js +23 -1
- package/dist/brokers/brokers.service.js.map +1 -1
- package/dist/brokers/utils/broker.util.js +4 -1
- package/dist/brokers/utils/broker.util.js.map +1 -1
- package/dist/brokers/utils/providers/azure-servicebus.service.d.ts +17 -0
- package/dist/brokers/utils/providers/azure-servicebus.service.js +51 -0
- package/dist/brokers/utils/providers/azure-servicebus.service.js.map +1 -0
- package/dist/cloud/cloud-api.util.d.ts +1 -1
- package/dist/cloud/cloud-api.util.js +21 -3
- package/dist/cloud/cloud-api.util.js.map +1 -1
- package/dist/cloud/cloud-broker-link.util.js +32 -11
- package/dist/cloud/cloud-broker-link.util.js.map +1 -1
- package/dist/cloud/cloud-database-link.util.js +8 -11
- package/dist/cloud/cloud-database-link.util.js.map +1 -1
- package/dist/cloud/cloud-graph-link.util.d.ts +12 -0
- package/dist/cloud/cloud-graph-link.util.js +61 -0
- package/dist/cloud/cloud-graph-link.util.js.map +1 -0
- package/dist/cloud/cloud-runtime.util.js +8 -1
- package/dist/cloud/cloud-runtime.util.js.map +1 -1
- package/dist/cloud/cloud-service-map.util.d.ts +3 -0
- package/dist/cloud/cloud-service-map.util.js +52 -0
- package/dist/cloud/cloud-service-map.util.js.map +1 -0
- package/dist/cloud/cloud-vector-link.util.d.ts +12 -0
- package/dist/cloud/cloud-vector-link.util.js +60 -0
- package/dist/cloud/cloud-vector-link.util.js.map +1 -0
- package/dist/cloud/cloud.service.d.ts +2 -1
- package/dist/cloud/cloud.service.js +3 -0
- package/dist/cloud/cloud.service.js.map +1 -1
- package/dist/cloud/index.d.ts +3 -0
- package/dist/cloud/index.js +8 -1
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/types/cloud.types.d.ts +13 -3
- package/dist/database/databases.service.js +27 -10
- package/dist/database/databases.service.js.map +1 -1
- package/dist/database/types/connection.interface.d.ts +3 -0
- package/dist/graph/adapters/adapter.factory.js +4 -0
- package/dist/graph/adapters/adapter.factory.js.map +1 -1
- package/dist/graph/adapters/cosmos-gremlin.adapter.d.ts +12 -0
- package/dist/graph/adapters/cosmos-gremlin.adapter.js +125 -0
- package/dist/graph/adapters/cosmos-gremlin.adapter.js.map +1 -0
- package/dist/graph/adapters/index.d.ts +2 -0
- package/dist/graph/adapters/index.js +5 -1
- package/dist/graph/adapters/index.js.map +1 -1
- package/dist/graph/adapters/neptune.adapter.d.ts +4 -4
- package/dist/graph/adapters/neptune.adapter.js.map +1 -1
- package/dist/graph/adapters/spanner-graph.adapter.d.ts +68 -0
- package/dist/graph/adapters/spanner-graph.adapter.js +220 -0
- package/dist/graph/adapters/spanner-graph.adapter.js.map +1 -0
- package/dist/graph/graphs.service.js +36 -20
- package/dist/graph/graphs.service.js.map +1 -1
- package/dist/graph/types/connection.interface.d.ts +4 -0
- package/dist/graph/types/enums.d.ts +2 -0
- package/dist/graph/types/enums.js +2 -0
- package/dist/graph/types/enums.js.map +1 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/dist/logs/logs.types.d.ts +5 -1
- package/dist/logs/logs.types.js +2 -0
- package/dist/logs/logs.types.js.map +1 -1
- package/dist/products/services/products.service.d.ts +13 -0
- package/dist/products/services/products.service.js +201 -104
- package/dist/products/services/products.service.js.map +1 -1
- package/dist/products/validators/joi-validators/create.productGraph.validator.js +8 -0
- package/dist/products/validators/joi-validators/create.productGraph.validator.js.map +1 -1
- package/dist/products/validators/joi-validators/create.productMessageBrokers.validator.js +28 -5
- package/dist/products/validators/joi-validators/create.productMessageBrokers.validator.js.map +1 -1
- package/dist/products/validators/joi-validators/create.productVector.validator.js +8 -0
- package/dist/products/validators/joi-validators/create.productVector.validator.js.map +1 -1
- package/dist/resilience/fallback.service.js +11 -6
- package/dist/resilience/fallback.service.js.map +1 -1
- package/dist/resilience/quota.service.d.ts +1 -1
- package/dist/resilience/quota.service.js +48 -10
- package/dist/resilience/quota.service.js.map +1 -1
- package/dist/resilience/resilience-mapping.utils.d.ts +5 -0
- package/dist/resilience/resilience-mapping.utils.js +53 -0
- package/dist/resilience/resilience-mapping.utils.js.map +1 -0
- package/dist/types/productsBuilder.types.d.ts +12 -0
- package/dist/types/productsBuilder.types.js +6 -0
- package/dist/types/productsBuilder.types.js.map +1 -1
- package/dist/vector/adapters/azure-search.adapter.d.ts +25 -0
- package/dist/vector/adapters/azure-search.adapter.js +217 -0
- package/dist/vector/adapters/azure-search.adapter.js.map +1 -0
- package/dist/vector/adapters/index.d.ts +3 -0
- package/dist/vector/adapters/index.js +7 -1
- package/dist/vector/adapters/index.js.map +1 -1
- package/dist/vector/adapters/opensearch.adapter.d.ts +25 -0
- package/dist/vector/adapters/opensearch.adapter.js +224 -0
- package/dist/vector/adapters/opensearch.adapter.js.map +1 -0
- package/dist/vector/adapters/vertex-vector-search.adapter.d.ts +29 -0
- package/dist/vector/adapters/vertex-vector-search.adapter.js +178 -0
- package/dist/vector/adapters/vertex-vector-search.adapter.js.map +1 -0
- package/dist/vector/types/enums.d.ts +6 -0
- package/dist/vector/types/enums.js +6 -0
- package/dist/vector/types/enums.js.map +1 -1
- package/dist/vector/vector-database.service.d.ts +6 -0
- package/dist/vector/vector-database.service.js +30 -16
- package/dist/vector/vector-database.service.js.map +1 -1
- package/dist/vector/vector.service.js +6 -0
- package/dist/vector/vector.service.js.map +1 -1
- package/package.json +8 -2
|
@@ -172,6 +172,13 @@ export default class ProductsBuilderService implements IProductsBuilderService {
|
|
|
172
172
|
fetchHealthcheck(access_tag: string, tag: string, throwError?: boolean): Promise<IProductAppHealth | null>;
|
|
173
173
|
fetchHealthchecks(access_tag: string, throwError?: boolean): Promise<Array<IProductAppHealth>>;
|
|
174
174
|
fetchProductHealthchecks(): Promise<Array<IProductAppHealth>>;
|
|
175
|
+
/** Validate quota/fallback provider references a registered product healthcheck component. */
|
|
176
|
+
validateProviderHealthcheckTag(option: {
|
|
177
|
+
healthcheck?: string;
|
|
178
|
+
check_interval?: number;
|
|
179
|
+
}): Promise<void>;
|
|
180
|
+
/** Keep in-memory product component arrays in sync after component CRUD (components API can lag). */
|
|
181
|
+
private mergeProductComponent;
|
|
175
182
|
/**
|
|
176
183
|
* Create a healthcheck from a schema (e.g. from resilience health.define/create).
|
|
177
184
|
* Persists as product component so processor healthcheck workers and health.list/fetch see it.
|
|
@@ -471,6 +478,12 @@ export default class ProductsBuilderService implements IProductsBuilderService {
|
|
|
471
478
|
fetchPriorSequence(meta: IParseInputStringMetaData, stage: string): IFeatureSequence;
|
|
472
479
|
validateActionKeyPlacement(data: IParseActionEventInput): IParsedSample;
|
|
473
480
|
fetchThirdPartyAppByAccessTag(access_tag: string): Promise<IApp & IVersion>;
|
|
481
|
+
/**
|
|
482
|
+
* When workspace access-tag lookup fails (common for product-scoped tags like ductape:paystack:ductape),
|
|
483
|
+
* resolve the app via product-linked components or fetchAppByTag.
|
|
484
|
+
*/
|
|
485
|
+
private fetchThirdPartyAppByAppTagFallback;
|
|
486
|
+
private resolveAppTagFromAccessReference;
|
|
474
487
|
fetchThirdPartyAppActionByTag(actions: Array<IAppAction>, action_tag: string): IAppAction;
|
|
475
488
|
createFeature(data: Partial<IProductFeature>, throwErrorIfExists?: boolean): Promise<void>;
|
|
476
489
|
updateFeature(tag: string, data: Partial<IProductFeature>): Promise<void>;
|
|
@@ -25,6 +25,8 @@ const cloudApi_service_1 = require("../../api/services/cloudApi.service");
|
|
|
25
25
|
const storage_cloud_link_util_1 = require("../../storage/storage-cloud-link.util");
|
|
26
26
|
const cloud_broker_link_util_1 = require("../../cloud/cloud-broker-link.util");
|
|
27
27
|
const cloud_database_link_util_1 = require("../../cloud/cloud-database-link.util");
|
|
28
|
+
const cloud_graph_link_util_1 = require("../../cloud/cloud-graph-link.util");
|
|
29
|
+
const cloud_vector_link_util_1 = require("../../cloud/cloud-vector-link.util");
|
|
28
30
|
const productsBuilder_types_1 = require("../../types/productsBuilder.types");
|
|
29
31
|
const validators_1 = require("../validators");
|
|
30
32
|
const objects_utils_1 = require("../utils/objects.utils");
|
|
@@ -220,6 +222,34 @@ class ProductsBuilderService {
|
|
|
220
222
|
const healthchecks = await this.productApi.fetchProductComponents(this.product_id, 'healthcheck', this.getUserAccess());
|
|
221
223
|
return healthchecks;
|
|
222
224
|
}
|
|
225
|
+
/** Validate quota/fallback provider references a registered product healthcheck component. */
|
|
226
|
+
async validateProviderHealthcheckTag(option) {
|
|
227
|
+
if (!option.healthcheck)
|
|
228
|
+
return;
|
|
229
|
+
const healthchecks = await this.fetchProductHealthchecks();
|
|
230
|
+
const found = healthchecks.some((h) => h.tag === option.healthcheck);
|
|
231
|
+
if (!found) {
|
|
232
|
+
throw new Error(`Product healthcheck "${option.healthcheck}" not found. Register it first (e.g. npm run test:healthchecks:populate).`);
|
|
233
|
+
}
|
|
234
|
+
if (!option.check_interval) {
|
|
235
|
+
option.check_interval = 10000;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/** Keep in-memory product component arrays in sync after component CRUD (components API can lag). */
|
|
239
|
+
mergeProductComponent(kind, item) {
|
|
240
|
+
if (!this.product || !(item === null || item === void 0 ? void 0 : item.tag))
|
|
241
|
+
return;
|
|
242
|
+
const key = kind === 'healthcheck' ? 'healthchecks' : kind === 'quota' ? 'quota' : 'fallbacks';
|
|
243
|
+
const list = Array.isArray(this.product[key])
|
|
244
|
+
? [...this.product[key]]
|
|
245
|
+
: [];
|
|
246
|
+
const idx = list.findIndex((c) => c.tag === item.tag);
|
|
247
|
+
if (idx >= 0)
|
|
248
|
+
list[idx] = Object.assign(Object.assign({}, list[idx]), item);
|
|
249
|
+
else
|
|
250
|
+
list.push(item);
|
|
251
|
+
this.product[key] = list;
|
|
252
|
+
}
|
|
223
253
|
/**
|
|
224
254
|
* Create a healthcheck from a schema (e.g. from resilience health.define/create).
|
|
225
255
|
* Persists as product component so processor healthcheck workers and health.list/fetch see it.
|
|
@@ -1053,19 +1083,7 @@ class ProductsBuilderService {
|
|
|
1053
1083
|
throw new Error(`Cannot find action ${d.event} on app ${app.tag} version ${app.version}`);
|
|
1054
1084
|
}
|
|
1055
1085
|
if (d.healthcheck) {
|
|
1056
|
-
|
|
1057
|
-
if (!d.check_interval) {
|
|
1058
|
-
d.check_interval = 10000;
|
|
1059
|
-
}
|
|
1060
|
-
if (!action) {
|
|
1061
|
-
throw new Error(`Cannot find healthcheck action ${d.healthcheck} on app ${app.tag} version ${app.version}`);
|
|
1062
|
-
}
|
|
1063
|
-
if (action.headers.data.length > 0 ||
|
|
1064
|
-
action.body.data.length > 0 ||
|
|
1065
|
-
action.params.data.length > 0 ||
|
|
1066
|
-
action.query.data.length > 0) {
|
|
1067
|
-
throw new Error('Healthcheck action is expected to have no headers, body, params or query');
|
|
1068
|
-
}
|
|
1086
|
+
await this.validateProviderHealthcheckTag(d);
|
|
1069
1087
|
}
|
|
1070
1088
|
}
|
|
1071
1089
|
d.last_checked = new Date();
|
|
@@ -1073,6 +1091,7 @@ class ProductsBuilderService {
|
|
|
1073
1091
|
d.last_available = true;
|
|
1074
1092
|
}));
|
|
1075
1093
|
await this.productApi.updateProduct(this.product_id, Object.assign(Object.assign({}, data), { component: enums_1.ProductComponents.QUOTA, action: enums_1.RequestAction.CREATE }), this.getUserAccess());
|
|
1094
|
+
this.mergeProductComponent('quota', data);
|
|
1076
1095
|
}
|
|
1077
1096
|
}
|
|
1078
1097
|
catch (e) {
|
|
@@ -1102,19 +1121,7 @@ class ProductsBuilderService {
|
|
|
1102
1121
|
throw new Error(`Cannot find action ${d.event} on app ${app.tag} version ${app.version}`);
|
|
1103
1122
|
}
|
|
1104
1123
|
if (d.healthcheck) {
|
|
1105
|
-
|
|
1106
|
-
if (!d.check_interval) {
|
|
1107
|
-
d.check_interval = 10000;
|
|
1108
|
-
}
|
|
1109
|
-
if (!action) {
|
|
1110
|
-
throw new Error(`Cannot find healthcheck action ${d.healthcheck} on app ${app.tag} version ${app.version}`);
|
|
1111
|
-
}
|
|
1112
|
-
if (action.headers.data.length > 0 ||
|
|
1113
|
-
action.body.data.length > 0 ||
|
|
1114
|
-
action.params.data.length > 0 ||
|
|
1115
|
-
action.query.data.length > 0) {
|
|
1116
|
-
throw new Error('Healthcheck action is expected to have no headers, body, params or query');
|
|
1117
|
-
}
|
|
1124
|
+
await this.validateProviderHealthcheckTag(d);
|
|
1118
1125
|
}
|
|
1119
1126
|
}
|
|
1120
1127
|
d.last_checked = new Date();
|
|
@@ -1133,12 +1140,19 @@ class ProductsBuilderService {
|
|
|
1133
1140
|
}
|
|
1134
1141
|
}
|
|
1135
1142
|
async fetchQuotas(version) {
|
|
1143
|
+
var _a;
|
|
1136
1144
|
const components = await this.productApi.fetchProductComponents(this.product_id, 'quota', this.getUserAccess());
|
|
1137
|
-
|
|
1145
|
+
if (Array.isArray(components) && components.length > 0) {
|
|
1146
|
+
return components;
|
|
1147
|
+
}
|
|
1148
|
+
return Array.isArray((_a = this.product) === null || _a === void 0 ? void 0 : _a.quota) ? this.product.quota : [];
|
|
1138
1149
|
}
|
|
1139
1150
|
async fetchQuota(tag, version) {
|
|
1151
|
+
var _a, _b, _c;
|
|
1140
1152
|
const component = await this.productApi.fetchProductComponentByTag(this.product_id, 'quota', tag, this.getUserAccess());
|
|
1141
|
-
|
|
1153
|
+
if (component)
|
|
1154
|
+
return component;
|
|
1155
|
+
return (_c = ((_b = (_a = this.product) === null || _a === void 0 ? void 0 : _a.quota) !== null && _b !== void 0 ? _b : []).find((q) => q.tag === tag)) !== null && _c !== void 0 ? _c : null;
|
|
1142
1156
|
}
|
|
1143
1157
|
async deleteQuota(tag) {
|
|
1144
1158
|
try {
|
|
@@ -1176,19 +1190,7 @@ class ProductsBuilderService {
|
|
|
1176
1190
|
throw new Error(`Cannot find action ${d.event} on app ${app.tag} version ${app.version}`);
|
|
1177
1191
|
}
|
|
1178
1192
|
if (d.healthcheck) {
|
|
1179
|
-
|
|
1180
|
-
if (!d.check_interval) {
|
|
1181
|
-
d.check_interval = 10000;
|
|
1182
|
-
}
|
|
1183
|
-
if (!action) {
|
|
1184
|
-
throw new Error(`Cannot find healthcheck action ${d.healthcheck} on app ${app.tag} version ${app.version}`);
|
|
1185
|
-
}
|
|
1186
|
-
if (action.headers.data.length > 0 ||
|
|
1187
|
-
action.body.data.length > 0 ||
|
|
1188
|
-
action.params.data.length > 0 ||
|
|
1189
|
-
action.query.data.length > 0) {
|
|
1190
|
-
throw new Error('Healthcheck action is expected to have no headers, body, params or query');
|
|
1191
|
-
}
|
|
1193
|
+
await this.validateProviderHealthcheckTag(d);
|
|
1192
1194
|
}
|
|
1193
1195
|
}
|
|
1194
1196
|
d.last_checked = new Date();
|
|
@@ -1196,6 +1198,7 @@ class ProductsBuilderService {
|
|
|
1196
1198
|
d.last_available = true;
|
|
1197
1199
|
}));
|
|
1198
1200
|
await this.productApi.updateProduct(this.product_id, Object.assign(Object.assign({}, data), { component: enums_1.ProductComponents.FALLBACK, action: enums_1.RequestAction.CREATE }), this.getUserAccess());
|
|
1201
|
+
this.mergeProductComponent('fallback', data);
|
|
1199
1202
|
}
|
|
1200
1203
|
}
|
|
1201
1204
|
catch (e) {
|
|
@@ -1222,19 +1225,7 @@ class ProductsBuilderService {
|
|
|
1222
1225
|
throw new Error(`Cannot find action ${d.event} on app ${app.tag} version ${app.version}`);
|
|
1223
1226
|
}
|
|
1224
1227
|
if (d.healthcheck) {
|
|
1225
|
-
|
|
1226
|
-
if (!d.check_interval) {
|
|
1227
|
-
d.check_interval = 10000;
|
|
1228
|
-
}
|
|
1229
|
-
if (!action) {
|
|
1230
|
-
throw new Error(`Cannot find healthcheck action ${d.healthcheck} on app ${app.tag} version ${app.version}`);
|
|
1231
|
-
}
|
|
1232
|
-
if (action.headers.data.length > 0 ||
|
|
1233
|
-
action.body.data.length > 0 ||
|
|
1234
|
-
action.params.data.length > 0 ||
|
|
1235
|
-
action.query.data.length > 0) {
|
|
1236
|
-
throw new Error('Healthcheck action is expected to have no headers, body, params or query');
|
|
1237
|
-
}
|
|
1228
|
+
await this.validateProviderHealthcheckTag(d);
|
|
1238
1229
|
}
|
|
1239
1230
|
}
|
|
1240
1231
|
d.last_checked = new Date();
|
|
@@ -1253,12 +1244,19 @@ class ProductsBuilderService {
|
|
|
1253
1244
|
}
|
|
1254
1245
|
}
|
|
1255
1246
|
async fetchFallbacks(version) {
|
|
1247
|
+
var _a;
|
|
1256
1248
|
const components = await this.productApi.fetchProductComponents(this.product_id, 'fallback', this.getUserAccess());
|
|
1257
|
-
|
|
1249
|
+
if (Array.isArray(components) && components.length > 0) {
|
|
1250
|
+
return components;
|
|
1251
|
+
}
|
|
1252
|
+
return Array.isArray((_a = this.product) === null || _a === void 0 ? void 0 : _a.fallback) ? this.product.fallback : [];
|
|
1258
1253
|
}
|
|
1259
1254
|
async fetchFallback(tag, version) {
|
|
1255
|
+
var _a, _b, _c;
|
|
1260
1256
|
const component = await this.productApi.fetchProductComponentByTag(this.product_id, 'fallback', tag, this.getUserAccess());
|
|
1261
|
-
|
|
1257
|
+
if (component)
|
|
1258
|
+
return component;
|
|
1259
|
+
return (_c = ((_b = (_a = this.product) === null || _a === void 0 ? void 0 : _a.fallback) !== null && _b !== void 0 ? _b : []).find((f) => f.tag === tag)) !== null && _c !== void 0 ? _c : null;
|
|
1262
1260
|
}
|
|
1263
1261
|
async deleteFallback(tag) {
|
|
1264
1262
|
try {
|
|
@@ -1778,6 +1776,19 @@ class ProductsBuilderService {
|
|
|
1778
1776
|
productTag: (_b = this.product) === null || _b === void 0 ? void 0 : _b.tag,
|
|
1779
1777
|
});
|
|
1780
1778
|
if (!(await this.fetchVector(data.tag))) {
|
|
1779
|
+
const auth = this.getUserAccess();
|
|
1780
|
+
const cloudApi = new cloudApi_service_1.CloudApiService(this.env_type);
|
|
1781
|
+
const productTag = this.product.tag;
|
|
1782
|
+
const materializedEnvs = [];
|
|
1783
|
+
for (const env of data.envs || []) {
|
|
1784
|
+
materializedEnvs.push(await (0, cloud_vector_link_util_1.materializeCloudLinkedVectorEnv)(env, {
|
|
1785
|
+
cloudApi,
|
|
1786
|
+
auth,
|
|
1787
|
+
productTag,
|
|
1788
|
+
vectorTag: data.tag,
|
|
1789
|
+
}));
|
|
1790
|
+
}
|
|
1791
|
+
data.envs = materializedEnvs;
|
|
1781
1792
|
await validators_1.CreateProductVectorSchema.validateAsync(data);
|
|
1782
1793
|
const processedEnvs = [];
|
|
1783
1794
|
for (const env of data.envs) {
|
|
@@ -1863,43 +1874,52 @@ class ProductsBuilderService {
|
|
|
1863
1874
|
}
|
|
1864
1875
|
if (data.envs) {
|
|
1865
1876
|
console.log('[ProductsService.updateVector] Processing envs update');
|
|
1877
|
+
const auth = this.getUserAccess();
|
|
1878
|
+
const cloudApi = new cloudApi_service_1.CloudApiService(this.env_type);
|
|
1879
|
+
const productTag = this.product.tag;
|
|
1866
1880
|
data.envs = await Promise.all(data.envs.map(async (env) => {
|
|
1867
1881
|
var _a, _b;
|
|
1882
|
+
const materialized = await (0, cloud_vector_link_util_1.materializeCloudLinkedVectorEnv)(env, {
|
|
1883
|
+
cloudApi,
|
|
1884
|
+
auth,
|
|
1885
|
+
productTag,
|
|
1886
|
+
vectorTag: data.tag || tag,
|
|
1887
|
+
});
|
|
1868
1888
|
console.log('[ProductsService.updateVector] Processing env:', {
|
|
1869
1889
|
slug: env.slug,
|
|
1870
1890
|
hasApiKey: !!env.apiKey,
|
|
1871
1891
|
hasEndpoint: !!env.endpoint,
|
|
1872
1892
|
});
|
|
1873
|
-
const exists = await this.fetchEnv(
|
|
1893
|
+
const exists = await this.fetchEnv(materialized.slug);
|
|
1874
1894
|
if (!exists) {
|
|
1875
|
-
throw new Error(`Env ${
|
|
1895
|
+
throw new Error(`Env ${materialized.slug} does not exist`);
|
|
1876
1896
|
}
|
|
1877
1897
|
// Store API key as secret and encrypt
|
|
1878
|
-
if (
|
|
1879
|
-
console.log('[ProductsService.updateVector] Converting API key to secret for env:',
|
|
1880
|
-
const originalApiKey =
|
|
1881
|
-
|
|
1898
|
+
if (materialized.apiKey) {
|
|
1899
|
+
console.log('[ProductsService.updateVector] Converting API key to secret for env:', materialized.slug);
|
|
1900
|
+
const originalApiKey = materialized.apiKey;
|
|
1901
|
+
materialized.apiKey = await this.storeVectorApiKeyAsSecret(materialized.apiKey, data.tag || tag, materialized.slug);
|
|
1882
1902
|
console.log('[ProductsService.updateVector] API key after secret conversion:', {
|
|
1883
|
-
wasConverted: originalApiKey !==
|
|
1884
|
-
isSecretRef: (_a =
|
|
1903
|
+
wasConverted: originalApiKey !== materialized.apiKey,
|
|
1904
|
+
isSecretRef: (_a = materialized.apiKey) === null || _a === void 0 ? void 0 : _a.startsWith('$Secret{'),
|
|
1885
1905
|
});
|
|
1886
|
-
|
|
1906
|
+
materialized.apiKey = (0, processor_utils_1.encrypt)(materialized.apiKey, this.product.private_key);
|
|
1887
1907
|
console.log('[ProductsService.updateVector] API key encrypted');
|
|
1888
1908
|
}
|
|
1889
1909
|
// Store endpoint as secret and encrypt
|
|
1890
|
-
if (
|
|
1891
|
-
console.log('[ProductsService.updateVector] Converting endpoint to secret for env:',
|
|
1892
|
-
const originalEndpoint =
|
|
1893
|
-
|
|
1910
|
+
if (materialized.endpoint) {
|
|
1911
|
+
console.log('[ProductsService.updateVector] Converting endpoint to secret for env:', materialized.slug);
|
|
1912
|
+
const originalEndpoint = materialized.endpoint;
|
|
1913
|
+
materialized.endpoint = await this.storeVectorEndpointAsSecret(materialized.endpoint, data.tag || tag, materialized.slug);
|
|
1894
1914
|
console.log('[ProductsService.updateVector] Endpoint after secret conversion:', {
|
|
1895
|
-
wasConverted: originalEndpoint !==
|
|
1896
|
-
isSecretRef: (_b =
|
|
1915
|
+
wasConverted: originalEndpoint !== materialized.endpoint,
|
|
1916
|
+
isSecretRef: (_b = materialized.endpoint) === null || _b === void 0 ? void 0 : _b.startsWith('$Secret{'),
|
|
1897
1917
|
});
|
|
1898
|
-
|
|
1918
|
+
materialized.endpoint = (0, processor_utils_1.encrypt)(materialized.endpoint, this.product.private_key);
|
|
1899
1919
|
console.log('[ProductsService.updateVector] Endpoint encrypted');
|
|
1900
1920
|
}
|
|
1901
|
-
console.log('[ProductsService.updateVector] Env processed successfully:',
|
|
1902
|
-
return
|
|
1921
|
+
console.log('[ProductsService.updateVector] Env processed successfully:', materialized.slug);
|
|
1922
|
+
return materialized;
|
|
1903
1923
|
}));
|
|
1904
1924
|
const overwrite = [];
|
|
1905
1925
|
const newEnvs = [];
|
|
@@ -2580,18 +2600,26 @@ class ProductsBuilderService {
|
|
|
2580
2600
|
}
|
|
2581
2601
|
}
|
|
2582
2602
|
async fetchAppWebhooks(access_tag) {
|
|
2603
|
+
var _a;
|
|
2583
2604
|
try {
|
|
2584
2605
|
const app = await this.fetchThirdPartyAppByAccessTag(access_tag);
|
|
2585
2606
|
if (!app) {
|
|
2586
2607
|
throw new Error(`App with access tag ${access_tag} not found`);
|
|
2587
2608
|
}
|
|
2588
2609
|
const version = app.versions.find((version) => version.tag === app.version);
|
|
2589
|
-
//const status = await this.webhooksApi.fetchWebhooks({access_tag, app_tag: app.tag, version: app.version}, this.getUserAccess())
|
|
2590
|
-
console.log(status);
|
|
2591
2610
|
if (!version) {
|
|
2592
2611
|
throw new Error(`Required app version not found`);
|
|
2593
2612
|
}
|
|
2594
|
-
|
|
2613
|
+
try {
|
|
2614
|
+
const withConfig = await this.webhooksApi.fetchWebhooks({ access_tag, app_tag: app.tag, version: app.version }, this.getUserAccess());
|
|
2615
|
+
if (Array.isArray(withConfig) && withConfig.length > 0) {
|
|
2616
|
+
return withConfig;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
catch (_b) {
|
|
2620
|
+
// Fall back to app definition webhooks when runtime service is unavailable
|
|
2621
|
+
}
|
|
2622
|
+
return (_a = version.webhooks) !== null && _a !== void 0 ? _a : [];
|
|
2595
2623
|
}
|
|
2596
2624
|
catch (e) {
|
|
2597
2625
|
throw e;
|
|
@@ -4070,11 +4098,11 @@ class ProductsBuilderService {
|
|
|
4070
4098
|
return datapoint;
|
|
4071
4099
|
}
|
|
4072
4100
|
async fetchThirdPartyAppByAccessTag(access_tag) {
|
|
4101
|
+
const cached = this.thirdPartyApps.find((item) => access_tag === item.access_tag);
|
|
4102
|
+
if (cached) {
|
|
4103
|
+
return Object.assign(Object.assign({}, cached.app), { version: cached.version });
|
|
4104
|
+
}
|
|
4073
4105
|
try {
|
|
4074
|
-
const app = this.thirdPartyApps.find((item) => access_tag === item.access_tag);
|
|
4075
|
-
if (app) {
|
|
4076
|
-
return Object.assign(Object.assign({}, app.app), { version: app.version });
|
|
4077
|
-
}
|
|
4078
4106
|
const access = await this.appApi.fetchAccessByTag(access_tag, this.getUserAccess());
|
|
4079
4107
|
if (!access) {
|
|
4080
4108
|
throw new Error(`Access to app ${access_tag} not found`);
|
|
@@ -4083,10 +4111,57 @@ class ProductsBuilderService {
|
|
|
4083
4111
|
this.thirdPartyApps.push({ access_tag, app: appData, version: access.version });
|
|
4084
4112
|
return Object.assign(Object.assign({}, appData), { version: access.version });
|
|
4085
4113
|
}
|
|
4086
|
-
catch (
|
|
4087
|
-
|
|
4114
|
+
catch (primaryError) {
|
|
4115
|
+
const resolved = await this.fetchThirdPartyAppByAppTagFallback(access_tag);
|
|
4116
|
+
if (resolved) {
|
|
4117
|
+
this.thirdPartyApps.push({
|
|
4118
|
+
access_tag,
|
|
4119
|
+
app: resolved,
|
|
4120
|
+
version: resolved.version,
|
|
4121
|
+
});
|
|
4122
|
+
return resolved;
|
|
4123
|
+
}
|
|
4124
|
+
throw primaryError;
|
|
4088
4125
|
}
|
|
4089
4126
|
}
|
|
4127
|
+
/**
|
|
4128
|
+
* When workspace access-tag lookup fails (common for product-scoped tags like ductape:paystack:ductape),
|
|
4129
|
+
* resolve the app via product-linked components or fetchAppByTag.
|
|
4130
|
+
*/
|
|
4131
|
+
async fetchThirdPartyAppByAppTagFallback(access_tag) {
|
|
4132
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
4133
|
+
const appTag = await this.resolveAppTagFromAccessReference(access_tag);
|
|
4134
|
+
if (!appTag)
|
|
4135
|
+
return null;
|
|
4136
|
+
const appData = await this.appApi.fetchAppByTag(appTag, this.getUserAccess());
|
|
4137
|
+
if (!appData)
|
|
4138
|
+
return null;
|
|
4139
|
+
const version = (_g = (_d = (_a = (typeof appData.version === 'string'
|
|
4140
|
+
? appData.version
|
|
4141
|
+
: undefined)) !== null && _a !== void 0 ? _a : (_c = (_b = appData.versions) === null || _b === void 0 ? void 0 : _b.find((v) => v.tag === 'ductape')) === null || _c === void 0 ? void 0 : _c.tag) !== null && _d !== void 0 ? _d : (_f = (_e = appData.versions) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.tag) !== null && _g !== void 0 ? _g : 'ductape';
|
|
4142
|
+
return Object.assign(Object.assign({}, appData), { version });
|
|
4143
|
+
}
|
|
4144
|
+
async resolveAppTagFromAccessReference(access_tag) {
|
|
4145
|
+
if (this.product_id) {
|
|
4146
|
+
const productApps = (await this.productApi.fetchProductComponents(this.product_id, 'app', this.getUserAccess()));
|
|
4147
|
+
const linked = productApps.find((a) => {
|
|
4148
|
+
var _a;
|
|
4149
|
+
return a.access_tag === access_tag ||
|
|
4150
|
+
a.app_tag === access_tag ||
|
|
4151
|
+
((_a = a.access_tag) === null || _a === void 0 ? void 0 : _a.startsWith(`${access_tag}:`));
|
|
4152
|
+
});
|
|
4153
|
+
if (linked === null || linked === void 0 ? void 0 : linked.app_tag)
|
|
4154
|
+
return linked.app_tag;
|
|
4155
|
+
}
|
|
4156
|
+
// Heuristic: product access tags are often `{app_tag}:{workspace}` — try app tag prefix
|
|
4157
|
+
if (access_tag.includes(':')) {
|
|
4158
|
+
const parts = access_tag.split(':');
|
|
4159
|
+
if (parts.length >= 2) {
|
|
4160
|
+
return `${parts[0]}:${parts[1]}`;
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
return access_tag;
|
|
4164
|
+
}
|
|
4090
4165
|
fetchThirdPartyAppActionByTag(actions, action_tag) {
|
|
4091
4166
|
const action = actions.find((action) => action.tag === action_tag);
|
|
4092
4167
|
if (!action) {
|
|
@@ -4322,6 +4397,19 @@ class ProductsBuilderService {
|
|
|
4322
4397
|
});
|
|
4323
4398
|
try {
|
|
4324
4399
|
if (!(await this.fetchGraph(data.tag))) {
|
|
4400
|
+
const auth = this.getUserAccess();
|
|
4401
|
+
const cloudApi = new cloudApi_service_1.CloudApiService(this.env_type);
|
|
4402
|
+
const productTag = this.product.tag;
|
|
4403
|
+
const materializedEnvs = [];
|
|
4404
|
+
for (const env of data.envs || []) {
|
|
4405
|
+
materializedEnvs.push(await (0, cloud_graph_link_util_1.materializeCloudLinkedGraphEnv)(env, {
|
|
4406
|
+
cloudApi,
|
|
4407
|
+
auth,
|
|
4408
|
+
productTag,
|
|
4409
|
+
graphTag: data.tag,
|
|
4410
|
+
}));
|
|
4411
|
+
}
|
|
4412
|
+
data.envs = materializedEnvs;
|
|
4325
4413
|
await validators_1.CreateProductGraphSchema.validateAsync(data);
|
|
4326
4414
|
const processedEnvs = [];
|
|
4327
4415
|
for (const env of data.envs) {
|
|
@@ -4402,41 +4490,50 @@ class ProductsBuilderService {
|
|
|
4402
4490
|
throw new Error(`tag ${tag} is in use`);
|
|
4403
4491
|
}
|
|
4404
4492
|
console.log('[ProductsService.updateGraph] Processing envs update');
|
|
4493
|
+
const auth = this.getUserAccess();
|
|
4494
|
+
const cloudApi = new cloudApi_service_1.CloudApiService(this.env_type);
|
|
4495
|
+
const productTag = this.product.tag;
|
|
4405
4496
|
data.envs = await Promise.all(data.envs.map(async (env) => {
|
|
4406
4497
|
var _a;
|
|
4498
|
+
const materialized = await (0, cloud_graph_link_util_1.materializeCloudLinkedGraphEnv)(env, {
|
|
4499
|
+
cloudApi,
|
|
4500
|
+
auth,
|
|
4501
|
+
productTag,
|
|
4502
|
+
graphTag: data.tag || tag,
|
|
4503
|
+
});
|
|
4407
4504
|
console.log('[ProductsService.updateGraph] Processing env:', {
|
|
4408
|
-
slug:
|
|
4409
|
-
hasConnectionUrl: !!
|
|
4410
|
-
hasUsername: !!
|
|
4411
|
-
hasPassword: !!
|
|
4505
|
+
slug: materialized.slug,
|
|
4506
|
+
hasConnectionUrl: !!materialized.connection_url,
|
|
4507
|
+
hasUsername: !!materialized.username,
|
|
4508
|
+
hasPassword: !!materialized.password,
|
|
4412
4509
|
});
|
|
4413
|
-
const exists = await this.fetchEnv(
|
|
4510
|
+
const exists = await this.fetchEnv(materialized.slug);
|
|
4414
4511
|
if (!exists) {
|
|
4415
|
-
throw new Error(`Env ${
|
|
4512
|
+
throw new Error(`Env ${materialized.slug} does not exist`);
|
|
4416
4513
|
}
|
|
4417
|
-
if (
|
|
4514
|
+
if (materialized.connection_url) {
|
|
4418
4515
|
// Store connection URL as secret
|
|
4419
|
-
console.log('[ProductsService.updateGraph] Converting connection URL to secret for env:',
|
|
4420
|
-
const originalUrl =
|
|
4421
|
-
|
|
4516
|
+
console.log('[ProductsService.updateGraph] Converting connection URL to secret for env:', materialized.slug);
|
|
4517
|
+
const originalUrl = materialized.connection_url;
|
|
4518
|
+
materialized.connection_url = await this.storeGraphConnectionUrlAsSecret(materialized.connection_url, data.tag || tag, materialized.slug);
|
|
4422
4519
|
console.log('[ProductsService.updateGraph] Connection URL after secret conversion:', {
|
|
4423
|
-
wasConverted: originalUrl !==
|
|
4424
|
-
isSecretRef: (_a =
|
|
4520
|
+
wasConverted: originalUrl !== materialized.connection_url,
|
|
4521
|
+
isSecretRef: (_a = materialized.connection_url) === null || _a === void 0 ? void 0 : _a.startsWith('$Secret{'),
|
|
4425
4522
|
});
|
|
4426
|
-
|
|
4523
|
+
materialized.connection_url = (0, processor_utils_1.encrypt)(materialized.connection_url, this.product.private_key);
|
|
4427
4524
|
console.log('[ProductsService.updateGraph] Connection URL encrypted');
|
|
4428
4525
|
}
|
|
4429
4526
|
// Encrypt username and password if provided
|
|
4430
|
-
if (
|
|
4431
|
-
console.log('[ProductsService.updateGraph] Encrypting username for env:',
|
|
4432
|
-
|
|
4527
|
+
if (materialized.username) {
|
|
4528
|
+
console.log('[ProductsService.updateGraph] Encrypting username for env:', materialized.slug);
|
|
4529
|
+
materialized.username = (0, processor_utils_1.encrypt)(materialized.username, this.product.private_key);
|
|
4433
4530
|
}
|
|
4434
|
-
if (
|
|
4435
|
-
console.log('[ProductsService.updateGraph] Encrypting password for env:',
|
|
4436
|
-
|
|
4531
|
+
if (materialized.password) {
|
|
4532
|
+
console.log('[ProductsService.updateGraph] Encrypting password for env:', materialized.slug);
|
|
4533
|
+
materialized.password = (0, processor_utils_1.encrypt)(materialized.password, this.product.private_key);
|
|
4437
4534
|
}
|
|
4438
|
-
console.log('[ProductsService.updateGraph] Env processed successfully:',
|
|
4439
|
-
return
|
|
4535
|
+
console.log('[ProductsService.updateGraph] Env processed successfully:', materialized.slug);
|
|
4536
|
+
return materialized;
|
|
4440
4537
|
}));
|
|
4441
4538
|
const overwrite = [];
|
|
4442
4539
|
const newEnvs = [];
|