@omen.foundation/node-microservice-runtime 0.1.110 → 0.1.112

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omen.foundation/node-microservice-runtime",
3
- "version": "0.1.110",
3
+ "version": "0.1.112",
4
4
  "description": "Beamable microservice runtime for Node.js/TypeScript services.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -887,6 +887,36 @@ async function getAllTypeScriptFiles(dir) {
887
887
  return files;
888
888
  }
889
889
 
890
+ // Read LOG_PROVIDER from beam.env (default: "Cloudwatch")
891
+ async function getLogProvider(packageJsonPath) {
892
+ const defaultLogProvider = 'Cloudwatch';
893
+ try {
894
+ const beamEnvPath = path.join(path.dirname(packageJsonPath), 'beam.env');
895
+ const beamEnvHiddenPath = path.join(path.dirname(packageJsonPath), '.beam.env');
896
+ let beamEnvContent = null;
897
+
898
+ if (await fs.access(beamEnvPath).then(() => true).catch(() => false)) {
899
+ beamEnvContent = await fs.readFile(beamEnvPath, 'utf8');
900
+ } else if (await fs.access(beamEnvHiddenPath).then(() => true).catch(() => false)) {
901
+ beamEnvContent = await fs.readFile(beamEnvHiddenPath, 'utf8');
902
+ }
903
+
904
+ if (beamEnvContent) {
905
+ // Parse LOG_PROVIDER from beam.env
906
+ const logProviderMatch = beamEnvContent.match(/^LOG_PROVIDER\s*=\s*(.+)$/m);
907
+ if (logProviderMatch) {
908
+ const logProvider = logProviderMatch[1].trim().replace(/^["']|["']$/g, '');
909
+ if (logProvider && (logProvider === 'Cloudwatch' || logProvider === 'Clickhouse')) {
910
+ return logProvider;
911
+ }
912
+ }
913
+ }
914
+ } catch (err) {
915
+ // Ignore errors, use default
916
+ }
917
+ return defaultLogProvider;
918
+ }
919
+
890
920
  async function updateManifest({
891
921
  apiHost,
892
922
  token,
@@ -899,6 +929,7 @@ async function updateManifest({
899
929
  discoveredStorage,
900
930
  discoveredComponents,
901
931
  discoveredDependencies,
932
+ packageJson,
902
933
  }) {
903
934
  const serviceReferences = existingManifest?.serviceReferences?.Value
904
935
  ?? existingManifest?.serviceReferences
@@ -1029,6 +1060,9 @@ async function updateManifest({
1029
1060
  });
1030
1061
  const dependencies = Array.from(dependenciesMap.values());
1031
1062
 
1063
+ // Get LOG_PROVIDER from beam.env (default: "Cloudwatch")
1064
+ const logProvider = await getLogProvider(packageJson);
1065
+
1032
1066
  let updated = false;
1033
1067
  const mappedServices = serviceReferences.map((reference) => {
1034
1068
  const name = reference.serviceName?.Value ?? reference.serviceName;
@@ -1041,7 +1075,7 @@ async function updateManifest({
1041
1075
  containerHealthCheckPort: reference.containerHealthCheckPort?.Value ?? reference.containerHealthCheckPort ?? 6565,
1042
1076
  imageId: shortImageId,
1043
1077
  imageCpuArch: reference.imageCpuArch?.Value ?? reference.imageCpuArch ?? 'linux/amd64',
1044
- logProvider: reference.logProvider?.Value ?? reference.logProvider ?? 'Clickhouse',
1078
+ logProvider: reference.logProvider?.Value ?? reference.logProvider ?? logProvider,
1045
1079
  dependencies,
1046
1080
  components,
1047
1081
  };
@@ -1053,7 +1087,7 @@ async function updateManifest({
1053
1087
  containerHealthCheckPort: reference.containerHealthCheckPort?.Value ?? reference.containerHealthCheckPort ?? 6565,
1054
1088
  imageId: reference.imageId?.Value ?? reference.imageId ?? shortImageId,
1055
1089
  imageCpuArch: reference.imageCpuArch?.Value ?? reference.imageCpuArch ?? 'linux/amd64',
1056
- logProvider: reference.logProvider?.Value ?? reference.logProvider ?? 'Clickhouse',
1090
+ logProvider: reference.logProvider?.Value ?? reference.logProvider ?? logProvider,
1057
1091
  dependencies: reference.dependencies?.Value ?? reference.dependencies ?? [],
1058
1092
  components: reference.components?.Value ?? reference.components ?? [],
1059
1093
  };
@@ -1067,31 +1101,12 @@ async function updateManifest({
1067
1101
  containerHealthCheckPort: 6565,
1068
1102
  imageId: shortImageId,
1069
1103
  imageCpuArch: 'linux/amd64',
1070
- logProvider: 'Clickhouse',
1104
+ logProvider: logProvider,
1071
1105
  dependencies,
1072
1106
  components,
1073
1107
  });
1074
1108
  }
1075
1109
 
1076
- // Log storage references being sent to backend
1077
- if (storageReferences.length > 0) {
1078
- console.log(`[beamo-node] Publishing ${storageReferences.length} storage reference(s) in manifest:`);
1079
- storageReferences.forEach(s => {
1080
- const details = [
1081
- `id: ${s.id}`,
1082
- `storageType: ${s.storageType || 'mongov1'}`,
1083
- `enabled: ${s.enabled !== false}`,
1084
- ...(s.templateId ? [`templateId: ${s.templateId}`] : []),
1085
- ...(s.archived !== undefined ? [`archived: ${s.archived}`] : []),
1086
- ].join(', ');
1087
- console.log(`[beamo-node] - ${details}`);
1088
- });
1089
- console.log(`[beamo-node] Storage references JSON: ${JSON.stringify(storageReferences, null, 2)}`);
1090
- } else {
1091
- console.warn(`[beamo-node] ⚠️ WARNING: No storage references in manifest. Database will NOT be created automatically.`);
1092
- console.warn(`[beamo-node] Make sure you have @StorageObject('StorageName') decorators in your code.`);
1093
- }
1094
-
1095
1110
  // Build request body matching C# CLI format exactly
1096
1111
  // C# sends: { comments, manifest, storageReferences } where storageReferences comes from manifest.storageReference
1097
1112
  // C# assigns it directly, so if null/empty it serializes as null (not omitted)
@@ -1102,6 +1117,18 @@ async function updateManifest({
1102
1117
  storageReferences: storageReferences.length > 0 ? storageReferences : null,
1103
1118
  };
1104
1119
 
1120
+ // Save manifest to publishHistory folder
1121
+ try {
1122
+ const publishHistoryDir = path.join(process.cwd(), 'publishHistory');
1123
+ await fs.mkdir(publishHistoryDir, { recursive: true });
1124
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
1125
+ const manifestFile = path.join(publishHistoryDir, `manifest_${timestamp}.json`);
1126
+ await fs.writeFile(manifestFile, JSON.stringify(requestBody, null, 2), 'utf8');
1127
+ console.log(`${colors.dim}Manifest saved to: ${manifestFile}${colors.reset}`);
1128
+ } catch (err) {
1129
+ console.log(`${colors.yellow}⚠${colors.reset} Could not save manifest to file: ${err.message}`);
1130
+ }
1131
+
1105
1132
  const publishUrl = new URL('/basic/beamo/manifest', apiHost);
1106
1133
  const publishHeaders = {
1107
1134
  Authorization: `Bearer ${token}`,
@@ -1110,18 +1137,6 @@ async function updateManifest({
1110
1137
  'X-BEAM-SCOPE': `${cid}.${pid}`,
1111
1138
  };
1112
1139
 
1113
- // Always log the full manifest being sent for debugging
1114
- console.log(`\n=== MANIFEST BEING SENT TO BACKEND ===`);
1115
- console.log(`URL: ${publishUrl}`);
1116
- console.log(`Method: POST`);
1117
- console.log(`Headers:`, JSON.stringify(publishHeaders, null, 2));
1118
- console.log(`\nFull Request Body:`);
1119
- console.log(JSON.stringify(requestBody, null, 2));
1120
- console.log(`\nService Entry in Manifest:`);
1121
- const serviceEntry = mappedServices.find(s => s.serviceName === serviceId);
1122
- console.log(JSON.stringify(serviceEntry, null, 2));
1123
- console.log(`=== END MANIFEST ===\n`);
1124
-
1125
1140
  const response = await fetch(publishUrl, {
1126
1141
  method: 'POST',
1127
1142
  headers: publishHeaders,
@@ -1142,41 +1157,43 @@ async function updateManifest({
1142
1157
 
1143
1158
  const responseBody = await response.json();
1144
1159
  console.log(`\n${colors.green}✓${colors.reset} Manifest published successfully`);
1145
- console.log(`${colors.dim}Backend Response:${colors.reset}`, JSON.stringify(responseBody, null, 2));
1146
1160
 
1147
- // After publishing, fetch the current manifest to see what was stored
1148
- // Note: ManifestView doesn't include storageGroupId, but we can at least verify storageReferences
1149
- try {
1150
- const currentManifestUrl = new URL('/basic/beamo/manifest/current', apiHost);
1151
- const currentManifestResponse = await fetch(currentManifestUrl, {
1152
- method: 'GET',
1153
- headers: {
1154
- Authorization: `Bearer ${token}`,
1155
- Accept: 'application/json',
1156
- 'X-BEAM-SCOPE': `${cid}.${pid}`,
1157
- },
1158
- });
1159
-
1160
- if (currentManifestResponse.ok) {
1161
- const currentManifest = await currentManifestResponse.json();
1162
- console.log(`\n${colors.cyan}=== CURRENT MANIFEST (as stored in backend) ===${colors.reset}`);
1163
- console.log(JSON.stringify(currentManifest, null, 2));
1164
- console.log(`${colors.cyan}=== END CURRENT MANIFEST ===${colors.reset}\n`);
1161
+ // Always try to get and display the storage connection string if storage references exist
1162
+ if (storageReferences.length > 0) {
1163
+ try {
1164
+ const storageConnectionUrl = new URL('/basic/beamo/storage/connection', apiHost);
1165
+ const storageConnectionResponse = await fetch(storageConnectionUrl, {
1166
+ method: 'GET',
1167
+ headers: {
1168
+ Authorization: `Bearer ${token}`,
1169
+ Accept: 'application/json',
1170
+ 'X-BEAM-SCOPE': `${cid}.${pid}`,
1171
+ },
1172
+ });
1165
1173
 
1166
- // Check if storage references are present
1167
- if (currentManifest?.manifest?.storageReference) {
1168
- console.log(`${colors.green}✓${colors.reset} Storage references found in stored manifest: ${currentManifest.manifest.storageReference.length} reference(s)`);
1169
- currentManifest.manifest.storageReference.forEach(sr => {
1170
- console.log(` - ${sr.id}: type=${sr.storageType}, enabled=${sr.enabled}, templateId=${sr.templateId || 'N/A'}, archived=${sr.archived || false}`);
1171
- });
1174
+ if (storageConnectionResponse.ok) {
1175
+ const connectionString = await storageConnectionResponse.text();
1176
+ console.log(`${colors.green}✓${colors.reset} MongoDB Connection String:`);
1177
+ console.log(`${colors.cyan}${connectionString}${colors.reset}`);
1172
1178
  } else {
1173
- console.log(`${colors.yellow}⚠${colors.reset} No storage references found in stored manifest`);
1179
+ const errorText = await storageConnectionResponse.text();
1180
+ let errorMessage = errorText;
1181
+ try {
1182
+ const errorJson = JSON.parse(errorText);
1183
+ errorMessage = errorJson.message || errorText;
1184
+ } catch {
1185
+ // Not JSON, use as-is
1186
+ }
1187
+ console.log(`${colors.red}✗${colors.reset} Could not retrieve connection string: ${errorMessage}`);
1188
+ if (errorMessage.includes('Could not open connection to database') ||
1189
+ errorMessage.includes('Credentials have not been generated') ||
1190
+ errorMessage.includes('storageGroupId')) {
1191
+ console.log(`${colors.yellow}⚠${colors.reset} This may prevent "Explore Data" from working. storageGroupId may not be set in the manifest.`);
1192
+ }
1174
1193
  }
1175
- } else {
1176
- console.log(`${colors.yellow}⚠${colors.reset} Could not fetch current manifest: ${currentManifestResponse.status}`);
1194
+ } catch (err) {
1195
+ console.log(`${colors.yellow}⚠${colors.reset} Could not retrieve connection string: ${err.message}`);
1177
1196
  }
1178
- } catch (err) {
1179
- console.log(`${colors.yellow}⚠${colors.reset} Could not fetch current manifest: ${err.message}`);
1180
1197
  }
1181
1198
  }
1182
1199
 
@@ -1581,6 +1598,7 @@ async function main() {
1581
1598
  discoveredStorage,
1582
1599
  discoveredComponents,
1583
1600
  discoveredDependencies,
1601
+ packageJson: packageJsonPath,
1584
1602
  });
1585
1603
  progress.complete('Manifest published');
1586
1604