@kumori/aurora-backend-handler 1.1.24 → 1.1.26

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/event-helper.ts CHANGED
@@ -406,6 +406,9 @@ export class EventHelper {
406
406
  deletionError: this.createEvent<Service>(EventNames.MarketplaceItemDeletionError).publish,
407
407
  loadItems: this.createEvent<string[]>(EventNames.LoadMarketplaceItems).publish,
408
408
  itemsLoaded: this.createEvent<MarketplaceItem[]>(EventNames.MarketplaceItemsLoaded).publish,
409
+ loadSchema: this.createEvent<string>(EventNames.LoadMarketplaceSchema).publish,
410
+ schemaLoaded: this.createEvent<MarketplaceItem>(EventNames.MarketplaceSchemaLoaded).publish,
411
+ schemaLoadError: this.createEvent<string>(EventNames.MarketplaceSchemaLoadError).publish,
409
412
  },
410
413
  subscribe: {
411
414
  deployItem: this.createEvent<MarketplaceService>(EventNames.DeployMarketplaceItem).subscribe,
@@ -419,6 +422,9 @@ export class EventHelper {
419
422
  deletionError: this.createEvent<Service>(EventNames.MarketplaceItemDeletionError).subscribe,
420
423
  loadItems: this.createEvent<string[]>(EventNames.LoadMarketplaceItems).subscribe,
421
424
  itemsLoaded: this.createEvent<MarketplaceItem[]>(EventNames.MarketplaceItemsLoaded).subscribe,
425
+ loadSchema: this.createEvent<string>(EventNames.LoadMarketplaceSchema).subscribe,
426
+ schemaLoaded: this.createEvent<MarketplaceItem>(EventNames.MarketplaceSchemaLoaded).subscribe,
427
+ schemaLoadError: this.createEvent<string>(EventNames.MarketplaceSchemaLoadError).subscribe,
422
428
  },
423
429
  unsubscribe: {
424
430
  deployItem: this.createEvent<MarketplaceService>(EventNames.DeployMarketplaceItem).unsubscribe,
@@ -432,6 +438,9 @@ export class EventHelper {
432
438
  deletionError: this.createEvent<Service>(EventNames.MarketplaceItemDeletionError).unsubscribe,
433
439
  loadItems: this.createEvent<string[]>(EventNames.LoadMarketplaceItems).unsubscribe,
434
440
  itemsLoaded: this.createEvent<MarketplaceItem[]>(EventNames.MarketplaceItemsLoaded).unsubscribe,
441
+ loadSchema: this.createEvent<string>(EventNames.LoadMarketplaceSchema).unsubscribe,
442
+ schemaLoaded: this.createEvent<MarketplaceItem>(EventNames.MarketplaceSchemaLoaded).unsubscribe,
443
+ schemaLoadError: this.createEvent<string>(EventNames.MarketplaceSchemaLoadError).unsubscribe,
435
444
  },
436
445
  };
437
446
  }
package/event-names.ts CHANGED
@@ -117,6 +117,9 @@ export enum EventNames {
117
117
  MarketplaceItemDeletionError = "marketplaceItemDeletionError",
118
118
  LoadMarketplaceItems = "loadMarketplaceItems",
119
119
  MarketplaceItemsLoaded = "marketplaceItemsLoaded",
120
+ LoadMarketplaceSchema = "loadMarketplaceSchema",
121
+ MarketplaceSchemaLoaded = "marketplaceSchemaLoaded",
122
+ MarketplaceSchemaLoadError = "marketplaceSchemaLoadError",
120
123
  // * Resource
121
124
  CreateResource = "createResource",
122
125
  ResourceCreated = "resourceCreated",
@@ -0,0 +1,109 @@
1
+ export const processMarketplaceSchemaResponse = (rawEntry: any, nameKey: string) => {
2
+ const roles: string[] = rawEntry.roles || [];
3
+ const roleName = roles.join(", ");
4
+ const schemas = rawEntry.schemas || [];
5
+
6
+ const processSchema = (schema: any) => {
7
+ const parameters: any[] = [];
8
+ const resources: any[] = [];
9
+ const channels: any[] = [];
10
+
11
+ const configProps = schema.properties?.config?.properties;
12
+ if (configProps) {
13
+ Object.entries(configProps).forEach(([key, value]: [string, any]) => {
14
+ parameters.push({
15
+ name: key,
16
+ type: value.type || "string",
17
+ required: schema.properties?.config?.required?.includes(key) || false,
18
+ defaultValue: value.default ?? value.enum?.[0] ?? value.const ?? undefined,
19
+ });
20
+ });
21
+ }
22
+
23
+ const volumeTypes = ["Registered", "NonReplicated", "Persisted", "Volatile", "Ephemeral", "Persistent"];
24
+ const isVolumeResource = (v: any): boolean => {
25
+ if (!v.oneOf) return false;
26
+ return v.oneOf.some((o: any) => {
27
+ if (o.oneOf) return o.oneOf.some((n: any) => volumeTypes.includes(n?.properties?.$kdsl?.const?.NamedType?.Name));
28
+ return volumeTypes.includes(o?.properties?.$kdsl?.const?.NamedType?.Name);
29
+ });
30
+ };
31
+
32
+ const resourceProps = schema.properties?.resource;
33
+ if (resourceProps?.properties) {
34
+ Object.entries(resourceProps.properties).forEach(([key, value]: [string, any]) => {
35
+ if (isVolumeResource(value)) {
36
+ resources.push({
37
+ name: key,
38
+ type: "volume",
39
+ required: resourceProps.required?.includes(key) || false,
40
+ });
41
+ } else {
42
+ const typeName = value.properties?.["$kdsl"]?.const?.NamedType?.Name;
43
+ const resourceType = typeName ? typeName.toLowerCase() : Object.keys(value.properties || {})[0];
44
+ const inner = value.properties?.[resourceType] || value.properties?.inner;
45
+ const defaultValue =
46
+ inner?.default !== undefined
47
+ ? String(inner.default)
48
+ : inner?.enum?.[0]
49
+ ? String(inner.enum[0])
50
+ : undefined;
51
+ resources.push({
52
+ name: key,
53
+ type: resourceType || "string",
54
+ required: resourceProps.required?.includes(key) || false,
55
+ defaultValue,
56
+ });
57
+ }
58
+ });
59
+ }
60
+
61
+ const srvProps = schema.properties?.srv?.properties;
62
+ if (srvProps) {
63
+ (["client", "server", "duplex"] as const).forEach((channelType) => {
64
+ if (srvProps[channelType]?.properties) {
65
+ Object.entries(srvProps[channelType].properties).forEach(([channelName, channelData]: [string, any]) => {
66
+ const port = channelData.properties?.port?.const || channelData.properties?.port?.enum?.[0];
67
+ const protocol = channelData.properties?.protocol?.const || channelData.properties?.protocol?.enum?.[0];
68
+ channels.push({
69
+ name: channelName,
70
+ type: channelType,
71
+ resource: port && protocol ? { type: "port", value: `${protocol}:${port}` } : undefined,
72
+ });
73
+ });
74
+ }
75
+ });
76
+ }
77
+
78
+ return { parameters, resources, channels };
79
+ };
80
+
81
+ if (schemas.length > 0 && schemas[0].oneOf) {
82
+ const processedVariants: any[] = [];
83
+ for (const schemaRef of schemas[0].oneOf) {
84
+ const refKey = schemaRef.$ref?.replace("#/$defs/", "");
85
+ const actualSchema = schemas[0].$defs?.[refKey];
86
+ if (actualSchema) {
87
+ const result = processSchema(actualSchema);
88
+ processedVariants.push({ name: nameKey, roleName, roles, variant: refKey, ...result });
89
+ }
90
+ }
91
+ return {
92
+ parameters: processedVariants[0]?.parameters || [],
93
+ resources: processedVariants[0]?.resources || [],
94
+ channels: processedVariants[0]?.channels || [],
95
+ name: nameKey,
96
+ roleName,
97
+ roles,
98
+ hasVariants: true,
99
+ variants: processedVariants,
100
+ };
101
+ }
102
+
103
+ if (schemas[0]) {
104
+ const result = processSchema(schemas[0]);
105
+ return { ...result, name: nameKey, roleName, roles, hasVariants: false };
106
+ }
107
+
108
+ return { parameters: [], resources: [], channels: [], name: nameKey, roleName, roles, hasVariants: false };
109
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumori/aurora-backend-handler",
3
- "version": "1.1.24",
3
+ "version": "1.1.26",
4
4
  "description": "backend handler",
5
5
  "main": "backend-handler.ts",
6
6
  "scripts": {
@@ -6,6 +6,7 @@ import {
6
6
  ClusterToken,
7
7
  Environment,
8
8
  Instance,
9
+ MarketplaceItem,
9
10
  Notification,
10
11
  Organization,
11
12
  Plan,
@@ -73,6 +74,7 @@ import { handleLinkEvent } from "./helpers/link-helper";
73
74
  import { eventHelper } from "./backend-handler";
74
75
  import { Revision } from "@kumori/aurora-interfaces/interfaces/revision-interface";
75
76
  import { requestRevisionData } from "./api/service-api-service";
77
+ import { processMarketplaceSchemaResponse } from "./helpers/marketplace-helper";
76
78
 
77
79
  let WebSocketClass: any;
78
80
 
@@ -2038,3 +2040,55 @@ const resolveServiceStatus = (service: Service): Service => {
2038
2040
  status: currentRevision.status,
2039
2041
  };
2040
2042
  };
2043
+ export const fetchAndStoreMarketplaceSchema = async (
2044
+ item: MarketplaceItem,
2045
+ ): Promise<void> => {
2046
+ const tenantsWithItem: string[] = [];
2047
+ tenantsMap.forEach((tenantEntry, tenantId) => {
2048
+ const hasItem = (tenantEntry.marketplaceItems || []).some(
2049
+ (i) => i.name === item.name && i.domain === item.domain,
2050
+ );
2051
+ if (hasItem) tenantsWithItem.push(tenantId);
2052
+ });
2053
+
2054
+ if (tenantsWithItem.length === 0) return;
2055
+
2056
+ await Promise.all(
2057
+ tenantsWithItem.map(async (tenantId) => {
2058
+ try {
2059
+ const response = await makeGlobalWebSocketRequest(
2060
+ "marketplace:artifact_schema",
2061
+ {
2062
+ tenant: tenantId,
2063
+ module: item.name,
2064
+ version: item.version,
2065
+ domain: item.domain,
2066
+ artifact: item.artifact,
2067
+ },
2068
+ 30000,
2069
+ "GET",
2070
+ tenantId,
2071
+ );
2072
+
2073
+ const data = response?.data;
2074
+ if (!data) return;
2075
+
2076
+ const nameKeys = Object.keys(data);
2077
+ const schema = processMarketplaceSchemaResponse(data[nameKeys[0]], nameKeys[0]);
2078
+
2079
+ const tenantEntry = tenantsMap.get(tenantId);
2080
+ if (tenantEntry) {
2081
+ tenantEntry.marketplaceItems = tenantEntry.marketplaceItems.map((i) =>
2082
+ i.name === item.name && i.domain === item.domain ? { ...i, schema } : i,
2083
+ );
2084
+ tenantsMap.set(tenantId, tenantEntry);
2085
+ }
2086
+ } catch (error) {
2087
+ console.error(`Error loading schema for tenant ${tenantId}:`, error);
2088
+ }
2089
+ }),
2090
+ );
2091
+
2092
+ rebuildHierarchy();
2093
+ await updateUserWithPlatformInfo();
2094
+ };