@neat.is/core 0.4.3 → 0.4.4
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/{chunk-NTQHMXWE.js → chunk-G3YGPWJL.js} +2 -2
- package/dist/{chunk-CB2UK4EH.js → chunk-J4YBTD24.js} +44 -3
- package/dist/{chunk-CB2UK4EH.js.map → chunk-J4YBTD24.js.map} +1 -1
- package/dist/{chunk-D5PIJFBE.js → chunk-YJOA7BBF.js} +2 -2
- package/dist/{chunk-KYRIQIPG.js → chunk-ZVNP3ZDH.js} +97 -25
- package/dist/chunk-ZVNP3ZDH.js.map +1 -0
- package/dist/cli.cjs +276 -99
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +184 -79
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +136 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +136 -23
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-QTX2YQJZ.js → otel-grpc-FIERFRGD.js} +3 -3
- package/dist/server.cjs +95 -23
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-KYRIQIPG.js.map +0 -1
- /package/dist/{chunk-NTQHMXWE.js.map → chunk-G3YGPWJL.js.map} +0 -0
- /package/dist/{chunk-D5PIJFBE.js.map → chunk-YJOA7BBF.js.map} +0 -0
- /package/dist/{otel-grpc-QTX2YQJZ.js.map → otel-grpc-FIERFRGD.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -41,15 +41,15 @@ import {
|
|
|
41
41
|
setStatus,
|
|
42
42
|
startPersistLoop,
|
|
43
43
|
startStalenessLoop
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-G3YGPWJL.js";
|
|
45
45
|
import {
|
|
46
46
|
startOtelGrpcReceiver
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-YJOA7BBF.js";
|
|
48
48
|
import {
|
|
49
49
|
__dirname,
|
|
50
50
|
__require,
|
|
51
51
|
buildOtelReceiver
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-ZVNP3ZDH.js";
|
|
53
53
|
|
|
54
54
|
// src/cli.ts
|
|
55
55
|
import path8 from "path";
|
|
@@ -694,45 +694,31 @@ import path4 from "path";
|
|
|
694
694
|
// src/installers/templates.ts
|
|
695
695
|
var OTEL_INIT_HEADER = "// Generated by `neat init --apply` (ADR-069). OpenTelemetry auto-instrumentation hook.";
|
|
696
696
|
var OTEL_INIT_CJS = `${OTEL_INIT_HEADER}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
try {
|
|
701
|
-
require('dotenv').config({ path: path.join(__dirname, '.env.neat') })
|
|
702
|
-
} catch (err) {
|
|
703
|
-
// dotenv unavailable \u2014 fall through to process.env.
|
|
704
|
-
}
|
|
697
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
698
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
699
|
+
|
|
705
700
|
require('@opentelemetry/auto-instrumentations-node/register')
|
|
706
701
|
`;
|
|
707
702
|
var OTEL_INIT_ESM = `${OTEL_INIT_HEADER}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
import { fileURLToPath } from 'node:url'
|
|
711
|
-
import path from 'node:path'
|
|
712
|
-
import dotenv from 'dotenv'
|
|
713
|
-
|
|
714
|
-
const here = path.dirname(fileURLToPath(import.meta.url))
|
|
715
|
-
dotenv.config({ path: path.join(here, '.env.neat') })
|
|
703
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
704
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
716
705
|
|
|
717
706
|
await import('@opentelemetry/auto-instrumentations-node/register')
|
|
718
707
|
`;
|
|
719
708
|
var OTEL_INIT_TS = `${OTEL_INIT_HEADER}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
import { fileURLToPath } from 'node:url'
|
|
723
|
-
import path from 'node:path'
|
|
724
|
-
import dotenv from 'dotenv'
|
|
725
|
-
|
|
726
|
-
const here = path.dirname(fileURLToPath(import.meta.url))
|
|
727
|
-
dotenv.config({ path: path.join(here, '.env.neat') })
|
|
709
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
710
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
728
711
|
|
|
729
712
|
await import('@opentelemetry/auto-instrumentations-node/register')
|
|
730
713
|
`;
|
|
731
|
-
function
|
|
714
|
+
function renderNodeOtelInit(template, serviceName, projectName) {
|
|
715
|
+
return template.replace(/__SERVICE_NAME__/g, serviceName).replace(/__PROJECT__/g, projectName);
|
|
716
|
+
}
|
|
717
|
+
function renderEnvNeat(serviceName, projectName) {
|
|
732
718
|
return [
|
|
733
719
|
"# Generated by `neat init --apply` (ADR-069).",
|
|
734
|
-
`OTEL_SERVICE_NAME=${
|
|
735
|
-
|
|
720
|
+
`OTEL_SERVICE_NAME=${serviceName}`,
|
|
721
|
+
`OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/projects/${projectName}/v1/traces`,
|
|
736
722
|
""
|
|
737
723
|
].join("\n");
|
|
738
724
|
}
|
|
@@ -752,8 +738,8 @@ export async function register() {
|
|
|
752
738
|
}
|
|
753
739
|
`;
|
|
754
740
|
var NEXT_INSTRUMENTATION_NODE_TS = `${NEXT_INSTRUMENTATION_HEADER}
|
|
755
|
-
process.env.OTEL_SERVICE_NAME ||= '
|
|
756
|
-
process.env.
|
|
741
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
742
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
757
743
|
|
|
758
744
|
import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
759
745
|
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
|
@@ -761,30 +747,25 @@ import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentation
|
|
|
761
747
|
new NodeSDK({ instrumentations: [getNodeAutoInstrumentations()] }).start()
|
|
762
748
|
`;
|
|
763
749
|
var NEXT_INSTRUMENTATION_NODE_JS = `${NEXT_INSTRUMENTATION_HEADER}
|
|
764
|
-
process.env.OTEL_SERVICE_NAME ||= '
|
|
765
|
-
process.env.
|
|
750
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
751
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
766
752
|
|
|
767
753
|
const { NodeSDK } = require('@opentelemetry/sdk-node')
|
|
768
754
|
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')
|
|
769
755
|
|
|
770
756
|
new NodeSDK({ instrumentations: [getNodeAutoInstrumentations()] }).start()
|
|
771
757
|
`;
|
|
772
|
-
function renderNextInstrumentationNode(template, projectName) {
|
|
773
|
-
return template.replace(/
|
|
758
|
+
function renderNextInstrumentationNode(template, serviceName, projectName) {
|
|
759
|
+
return template.replace(/__SERVICE_NAME__/g, serviceName).replace(/__PROJECT__/g, projectName);
|
|
774
760
|
}
|
|
775
761
|
var FRAMEWORK_OTEL_INIT_HEADER = "// Generated by `neat init --apply` (ADR-074). OpenTelemetry SDK hook.";
|
|
776
762
|
var FRAMEWORK_OTEL_INIT_TS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
import path from 'node:path'
|
|
781
|
-
import dotenv from 'dotenv'
|
|
763
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
764
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
765
|
+
|
|
782
766
|
import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
783
767
|
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
|
784
768
|
|
|
785
|
-
const here = path.dirname(fileURLToPath(import.meta.url))
|
|
786
|
-
dotenv.config({ path: path.join(here, '.env.neat') })
|
|
787
|
-
|
|
788
769
|
const sdk = new NodeSDK({
|
|
789
770
|
serviceName: process.env.OTEL_SERVICE_NAME,
|
|
790
771
|
instrumentations: [getNodeAutoInstrumentations()],
|
|
@@ -792,14 +773,9 @@ const sdk = new NodeSDK({
|
|
|
792
773
|
sdk.start()
|
|
793
774
|
`;
|
|
794
775
|
var FRAMEWORK_OTEL_INIT_JS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
try {
|
|
799
|
-
require('dotenv').config({ path: path.join(__dirname, '.env.neat') })
|
|
800
|
-
} catch (err) {
|
|
801
|
-
// dotenv unavailable \u2014 fall through to process.env.
|
|
802
|
-
}
|
|
776
|
+
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
777
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
778
|
+
|
|
803
779
|
const { NodeSDK } = require('@opentelemetry/sdk-node')
|
|
804
780
|
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')
|
|
805
781
|
|
|
@@ -809,6 +785,9 @@ const sdk = new NodeSDK({
|
|
|
809
785
|
})
|
|
810
786
|
sdk.start()
|
|
811
787
|
`;
|
|
788
|
+
function renderFrameworkOtelInit(template, serviceName, projectName) {
|
|
789
|
+
return template.replace(/__SERVICE_NAME__/g, serviceName).replace(/__PROJECT__/g, projectName);
|
|
790
|
+
}
|
|
812
791
|
var REMIX_OTEL_SERVER_TS = FRAMEWORK_OTEL_INIT_TS_BODY;
|
|
813
792
|
var REMIX_OTEL_SERVER_JS = FRAMEWORK_OTEL_INIT_JS_BODY;
|
|
814
793
|
var SVELTEKIT_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY;
|
|
@@ -871,11 +850,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
871
850
|
var SDK_PACKAGES = [
|
|
872
851
|
{ name: "@opentelemetry/api", version: "^1.9.0" },
|
|
873
852
|
{ name: "@opentelemetry/sdk-node", version: "^0.57.0" },
|
|
874
|
-
{ name: "@opentelemetry/auto-instrumentations-node", version: "^0.55.0" }
|
|
875
|
-
// ADR-069 §5 — dotenv is the fourth dep. The generated otel-init loads
|
|
876
|
-
// .env.neat through it so OTEL_SERVICE_NAME and the endpoint are in scope
|
|
877
|
-
// before the auto-instrumentation hook attaches.
|
|
878
|
-
{ name: "dotenv", version: "^16.4.5" }
|
|
853
|
+
{ name: "@opentelemetry/auto-instrumentations-node", version: "^0.55.0" }
|
|
879
854
|
];
|
|
880
855
|
var OTEL_ENV = {
|
|
881
856
|
// ADR-069 §4 — endpoint moves into the per-package .env.neat (written
|
|
@@ -883,13 +858,36 @@ var OTEL_ENV = {
|
|
|
883
858
|
// patch render: it documents the key/value the user can inspect in the
|
|
884
859
|
// generated .env.neat.
|
|
885
860
|
file: null,
|
|
886
|
-
key: "
|
|
887
|
-
value: "http://localhost:4318"
|
|
861
|
+
key: "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
|
|
862
|
+
value: "http://localhost:4318/projects/<project>/v1/traces"
|
|
888
863
|
};
|
|
889
|
-
function
|
|
864
|
+
function serviceNodeName(pkg, serviceDir) {
|
|
865
|
+
return pkg.name ?? path4.basename(serviceDir);
|
|
866
|
+
}
|
|
867
|
+
function projectToken(pkg, serviceDir, project) {
|
|
890
868
|
if (project && project.length > 0) return project;
|
|
891
869
|
return pkg.name ?? path4.basename(serviceDir);
|
|
892
870
|
}
|
|
871
|
+
async function readJsonFile(p) {
|
|
872
|
+
try {
|
|
873
|
+
const raw = await fs4.readFile(p, "utf8");
|
|
874
|
+
return JSON.parse(raw);
|
|
875
|
+
} catch {
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
async function detectRuntimeKind(pkgRoot, pkg) {
|
|
880
|
+
const deps = allDeps(pkg);
|
|
881
|
+
if ("react-native" in deps || "expo" in deps) return "react-native";
|
|
882
|
+
const appJson = await readJsonFile(path4.join(pkgRoot, "app.json"));
|
|
883
|
+
if (appJson && typeof appJson === "object" && "expo" in appJson) {
|
|
884
|
+
return "react-native";
|
|
885
|
+
}
|
|
886
|
+
if (await exists(path4.join(pkgRoot, "vite.config.js")) || await exists(path4.join(pkgRoot, "vite.config.ts")) || await exists(path4.join(pkgRoot, "vite.config.mjs")) || "vite" in deps) {
|
|
887
|
+
return "browser-bundle";
|
|
888
|
+
}
|
|
889
|
+
return "node";
|
|
890
|
+
}
|
|
893
891
|
async function readPackageJson(serviceDir) {
|
|
894
892
|
try {
|
|
895
893
|
const raw = await fs4.readFile(path4.join(serviceDir, "package.json"), "utf8");
|
|
@@ -1136,7 +1134,6 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
1136
1134
|
const existingDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
1137
1135
|
const dependencyEdits = [];
|
|
1138
1136
|
for (const sdk of SDK_PACKAGES) {
|
|
1139
|
-
if (sdk.name === "dotenv") continue;
|
|
1140
1137
|
if (sdk.name in existingDeps) continue;
|
|
1141
1138
|
dependencyEdits.push({
|
|
1142
1139
|
file: manifestPath,
|
|
@@ -1145,7 +1142,8 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
1145
1142
|
version: sdk.version
|
|
1146
1143
|
});
|
|
1147
1144
|
}
|
|
1148
|
-
const
|
|
1145
|
+
const svcName = serviceNodeName(pkg, serviceDir);
|
|
1146
|
+
const projectName = projectToken(pkg, serviceDir, project);
|
|
1149
1147
|
const generatedFiles = [];
|
|
1150
1148
|
if (!await exists(instrumentationFile)) {
|
|
1151
1149
|
generatedFiles.push({
|
|
@@ -1159,6 +1157,7 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
1159
1157
|
file: instrumentationNodeFile,
|
|
1160
1158
|
contents: renderNextInstrumentationNode(
|
|
1161
1159
|
useTs ? NEXT_INSTRUMENTATION_NODE_TS : NEXT_INSTRUMENTATION_NODE_JS,
|
|
1160
|
+
svcName,
|
|
1162
1161
|
projectName
|
|
1163
1162
|
),
|
|
1164
1163
|
skipIfExists: true
|
|
@@ -1167,7 +1166,7 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
1167
1166
|
if (!await exists(envNeatFile)) {
|
|
1168
1167
|
generatedFiles.push({
|
|
1169
1168
|
file: envNeatFile,
|
|
1170
|
-
contents: renderEnvNeat(projectName),
|
|
1169
|
+
contents: renderEnvNeat(svcName, projectName),
|
|
1171
1170
|
skipIfExists: true
|
|
1172
1171
|
});
|
|
1173
1172
|
}
|
|
@@ -1228,11 +1227,21 @@ async function queueEnvNeat(serviceDir, pkg, project, generatedFiles) {
|
|
|
1228
1227
|
if (!await exists(envNeatFile)) {
|
|
1229
1228
|
generatedFiles.push({
|
|
1230
1229
|
file: envNeatFile,
|
|
1231
|
-
contents: renderEnvNeat(
|
|
1230
|
+
contents: renderEnvNeat(
|
|
1231
|
+
serviceNodeName(pkg, serviceDir),
|
|
1232
|
+
projectToken(pkg, serviceDir, project)
|
|
1233
|
+
),
|
|
1232
1234
|
skipIfExists: true
|
|
1233
1235
|
});
|
|
1234
1236
|
}
|
|
1235
1237
|
}
|
|
1238
|
+
function renderFrameworkOtelInitForPkg(template, pkg, serviceDir, project) {
|
|
1239
|
+
return renderFrameworkOtelInit(
|
|
1240
|
+
template,
|
|
1241
|
+
serviceNodeName(pkg, serviceDir),
|
|
1242
|
+
projectToken(pkg, serviceDir, project)
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1236
1245
|
function fileImportsOtelHook(raw, specifiers) {
|
|
1237
1246
|
const lines = raw.split(/\r?\n/);
|
|
1238
1247
|
for (const line of lines) {
|
|
@@ -1258,7 +1267,12 @@ async function planRemix(serviceDir, pkg, manifestPath, entryFile, project) {
|
|
|
1258
1267
|
if (!await exists(otelServerFile)) {
|
|
1259
1268
|
generatedFiles.push({
|
|
1260
1269
|
file: otelServerFile,
|
|
1261
|
-
contents:
|
|
1270
|
+
contents: renderFrameworkOtelInitForPkg(
|
|
1271
|
+
useTs ? REMIX_OTEL_SERVER_TS : REMIX_OTEL_SERVER_JS,
|
|
1272
|
+
pkg,
|
|
1273
|
+
serviceDir,
|
|
1274
|
+
project
|
|
1275
|
+
),
|
|
1262
1276
|
skipIfExists: true
|
|
1263
1277
|
});
|
|
1264
1278
|
}
|
|
@@ -1312,7 +1326,12 @@ async function planSvelteKit(serviceDir, pkg, manifestPath, hooksFile, project)
|
|
|
1312
1326
|
if (!await exists(otelInitFile)) {
|
|
1313
1327
|
generatedFiles.push({
|
|
1314
1328
|
file: otelInitFile,
|
|
1315
|
-
contents:
|
|
1329
|
+
contents: renderFrameworkOtelInitForPkg(
|
|
1330
|
+
useTs ? SVELTEKIT_OTEL_INIT_TS : SVELTEKIT_OTEL_INIT_JS,
|
|
1331
|
+
pkg,
|
|
1332
|
+
serviceDir,
|
|
1333
|
+
project
|
|
1334
|
+
),
|
|
1316
1335
|
skipIfExists: true
|
|
1317
1336
|
});
|
|
1318
1337
|
}
|
|
@@ -1375,7 +1394,12 @@ async function planNuxt(serviceDir, pkg, manifestPath, project) {
|
|
|
1375
1394
|
if (!await exists(otelInitFile)) {
|
|
1376
1395
|
generatedFiles.push({
|
|
1377
1396
|
file: otelInitFile,
|
|
1378
|
-
contents:
|
|
1397
|
+
contents: renderFrameworkOtelInitForPkg(
|
|
1398
|
+
useTs ? NUXT_OTEL_INIT_TS : NUXT_OTEL_INIT_JS,
|
|
1399
|
+
pkg,
|
|
1400
|
+
serviceDir,
|
|
1401
|
+
project
|
|
1402
|
+
),
|
|
1379
1403
|
skipIfExists: true
|
|
1380
1404
|
});
|
|
1381
1405
|
}
|
|
@@ -1431,7 +1455,12 @@ async function planAstro(serviceDir, pkg, manifestPath, project) {
|
|
|
1431
1455
|
if (!await exists(otelInitFile)) {
|
|
1432
1456
|
generatedFiles.push({
|
|
1433
1457
|
file: otelInitFile,
|
|
1434
|
-
contents:
|
|
1458
|
+
contents: renderFrameworkOtelInitForPkg(
|
|
1459
|
+
useTs ? ASTRO_OTEL_INIT_TS : ASTRO_OTEL_INIT_JS,
|
|
1460
|
+
pkg,
|
|
1461
|
+
serviceDir,
|
|
1462
|
+
project
|
|
1463
|
+
),
|
|
1435
1464
|
skipIfExists: true
|
|
1436
1465
|
});
|
|
1437
1466
|
}
|
|
@@ -1523,6 +1552,10 @@ async function plan(serviceDir, opts) {
|
|
|
1523
1552
|
return planAstro(serviceDir, pkg, manifestPath, project);
|
|
1524
1553
|
}
|
|
1525
1554
|
}
|
|
1555
|
+
const runtimeKind = await detectRuntimeKind(serviceDir, pkg);
|
|
1556
|
+
if (runtimeKind !== "node") {
|
|
1557
|
+
return { ...empty, runtimeKind };
|
|
1558
|
+
}
|
|
1526
1559
|
const entryFile = await resolveEntry(serviceDir, pkg);
|
|
1527
1560
|
if (!entryFile) {
|
|
1528
1561
|
return { ...empty, libOnly: true };
|
|
@@ -1557,18 +1590,20 @@ async function plan(serviceDir, opts) {
|
|
|
1557
1590
|
} catch {
|
|
1558
1591
|
return { ...empty, libOnly: true };
|
|
1559
1592
|
}
|
|
1593
|
+
const svcName = serviceNodeName(pkg, serviceDir);
|
|
1594
|
+
const projectName = projectToken(pkg, serviceDir, project);
|
|
1560
1595
|
const generatedFiles = [];
|
|
1561
1596
|
if (!await exists(otelInitFile)) {
|
|
1562
1597
|
generatedFiles.push({
|
|
1563
1598
|
file: otelInitFile,
|
|
1564
|
-
contents: otelInitContents(flavor),
|
|
1599
|
+
contents: renderNodeOtelInit(otelInitContents(flavor), svcName, projectName),
|
|
1565
1600
|
skipIfExists: true
|
|
1566
1601
|
});
|
|
1567
1602
|
}
|
|
1568
1603
|
if (!await exists(envNeatFile)) {
|
|
1569
1604
|
generatedFiles.push({
|
|
1570
1605
|
file: envNeatFile,
|
|
1571
|
-
contents: renderEnvNeat(
|
|
1606
|
+
contents: renderEnvNeat(svcName, projectName),
|
|
1572
1607
|
skipIfExists: true
|
|
1573
1608
|
});
|
|
1574
1609
|
}
|
|
@@ -1625,6 +1660,22 @@ async function apply(installPlan) {
|
|
|
1625
1660
|
writtenFiles: []
|
|
1626
1661
|
};
|
|
1627
1662
|
}
|
|
1663
|
+
if (installPlan.runtimeKind === "browser-bundle") {
|
|
1664
|
+
return {
|
|
1665
|
+
serviceDir,
|
|
1666
|
+
outcome: "browser-bundle",
|
|
1667
|
+
reason: "browser bundle; Node OTel SDK cannot run here",
|
|
1668
|
+
writtenFiles: []
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
if (installPlan.runtimeKind === "react-native") {
|
|
1672
|
+
return {
|
|
1673
|
+
serviceDir,
|
|
1674
|
+
outcome: "react-native",
|
|
1675
|
+
reason: "React Native / Expo target; Node OTel SDK cannot run here",
|
|
1676
|
+
writtenFiles: []
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1628
1679
|
if (installPlan.dependencyEdits.length === 0 && installPlan.entrypointEdits.length === 0 && (installPlan.generatedFiles?.length ?? 0) === 0 && installPlan.nextConfigEdit === void 0) {
|
|
1629
1680
|
return {
|
|
1630
1681
|
serviceDir,
|
|
@@ -2108,11 +2159,13 @@ async function applyInstallersOver(services, project) {
|
|
|
2108
2159
|
let instrumented = 0;
|
|
2109
2160
|
let already = 0;
|
|
2110
2161
|
let libOnly = 0;
|
|
2162
|
+
let browserBundle = 0;
|
|
2163
|
+
let reactNative = 0;
|
|
2111
2164
|
for (const svc of services) {
|
|
2112
2165
|
const installer = await pickInstaller(svc.dir);
|
|
2113
2166
|
if (!installer) continue;
|
|
2114
2167
|
const plan3 = await installer.plan(svc.dir, { project });
|
|
2115
|
-
if (isEmptyPlan(plan3) && !plan3.libOnly) {
|
|
2168
|
+
if (isEmptyPlan(plan3) && !plan3.libOnly && plan3.runtimeKind === void 0) {
|
|
2116
2169
|
already++;
|
|
2117
2170
|
continue;
|
|
2118
2171
|
}
|
|
@@ -2120,8 +2173,15 @@ async function applyInstallersOver(services, project) {
|
|
|
2120
2173
|
if (outcome.outcome === "instrumented") instrumented++;
|
|
2121
2174
|
else if (outcome.outcome === "already-instrumented") already++;
|
|
2122
2175
|
else if (outcome.outcome === "lib-only") libOnly++;
|
|
2176
|
+
else if (outcome.outcome === "browser-bundle") {
|
|
2177
|
+
browserBundle++;
|
|
2178
|
+
console.log(`skipping ${svc.dir}: browser bundle; browser-OTel support lands in a future release.`);
|
|
2179
|
+
} else if (outcome.outcome === "react-native") {
|
|
2180
|
+
reactNative++;
|
|
2181
|
+
console.log(`skipping ${svc.dir}: React Native target; browser-OTel support lands in a future release.`);
|
|
2182
|
+
}
|
|
2123
2183
|
}
|
|
2124
|
-
return { instrumented, alreadyInstrumented: already, libOnly };
|
|
2184
|
+
return { instrumented, alreadyInstrumented: already, libOnly, browserBundle, reactNative };
|
|
2125
2185
|
}
|
|
2126
2186
|
async function promptYesNo(question) {
|
|
2127
2187
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -2325,13 +2385,15 @@ async function runOrchestrator(opts) {
|
|
|
2325
2385
|
if (gi.action !== "unchanged") {
|
|
2326
2386
|
console.log(`${gi.action} .gitignore (neat-out/)`);
|
|
2327
2387
|
}
|
|
2388
|
+
let currentProjectName = opts.project;
|
|
2328
2389
|
try {
|
|
2329
|
-
await addProject({
|
|
2390
|
+
const entry2 = await addProject({
|
|
2330
2391
|
name: opts.project,
|
|
2331
2392
|
path: opts.scanPath,
|
|
2332
2393
|
languages,
|
|
2333
2394
|
status: "active"
|
|
2334
2395
|
});
|
|
2396
|
+
currentProjectName = entry2.name;
|
|
2335
2397
|
} catch (err) {
|
|
2336
2398
|
if (!(err instanceof ProjectNameCollisionError)) throw err;
|
|
2337
2399
|
console.error(`neat: ${err.message}`);
|
|
@@ -2339,6 +2401,20 @@ async function runOrchestrator(opts) {
|
|
|
2339
2401
|
result.exitCode = 1;
|
|
2340
2402
|
return result;
|
|
2341
2403
|
}
|
|
2404
|
+
const siblings = await listProjects();
|
|
2405
|
+
const paused = [];
|
|
2406
|
+
for (const p of siblings) {
|
|
2407
|
+
if (p.name !== currentProjectName && p.status === "active") {
|
|
2408
|
+
await setStatus(p.name, "paused");
|
|
2409
|
+
paused.push(p.name);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
if (paused.length > 0) {
|
|
2413
|
+
const plural = paused.length === 1 ? "" : "s";
|
|
2414
|
+
console.log(
|
|
2415
|
+
`neat: paused ${paused.length} sibling project${plural}; run \`neat resume <name>\` to bring one back active.`
|
|
2416
|
+
);
|
|
2417
|
+
}
|
|
2342
2418
|
if (!runApply) {
|
|
2343
2419
|
result.steps.apply.skipped = true;
|
|
2344
2420
|
console.log("skipped instrumentation (--no-instrument)");
|
|
@@ -3009,7 +3085,7 @@ async function runSync(opts) {
|
|
|
3009
3085
|
snapshotPath = target;
|
|
3010
3086
|
}
|
|
3011
3087
|
const skipApply = opts.dryRun || opts.noInstrument;
|
|
3012
|
-
const applyTally = skipApply ? { instrumented: 0, alreadyInstrumented: 0, libOnly: 0 } : await applyInstallersOver(persisted.services, entry2.name);
|
|
3088
|
+
const applyTally = skipApply ? { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, browserBundle: 0, reactNative: 0 } : await applyInstallersOver(persisted.services, entry2.name);
|
|
3013
3089
|
const warnings = [];
|
|
3014
3090
|
let daemonState = "skipped";
|
|
3015
3091
|
let exitCode = 0;
|
|
@@ -3357,7 +3433,7 @@ async function buildPatchSections(services, project) {
|
|
|
3357
3433
|
const installer = await pickInstaller(svc.dir);
|
|
3358
3434
|
if (!installer) continue;
|
|
3359
3435
|
const plan3 = await installer.plan(svc.dir, { project });
|
|
3360
|
-
if (isEmptyPlan(plan3) && !plan3.libOnly) continue;
|
|
3436
|
+
if (isEmptyPlan(plan3) && !plan3.libOnly && plan3.runtimeKind === void 0) continue;
|
|
3361
3437
|
sections.push({ installer: installer.name, plan: plan3 });
|
|
3362
3438
|
}
|
|
3363
3439
|
return sections;
|
|
@@ -3401,13 +3477,15 @@ async function runInit(opts) {
|
|
|
3401
3477
|
written.push(gitignoreResult.file);
|
|
3402
3478
|
}
|
|
3403
3479
|
const languages = [...new Set(services.map((s) => s.node.language))].sort();
|
|
3480
|
+
let currentProjectName = opts.project;
|
|
3404
3481
|
try {
|
|
3405
|
-
await addProject({
|
|
3482
|
+
const entry2 = await addProject({
|
|
3406
3483
|
name: opts.project,
|
|
3407
3484
|
path: opts.scanPath,
|
|
3408
3485
|
languages,
|
|
3409
3486
|
status: "active"
|
|
3410
3487
|
});
|
|
3488
|
+
currentProjectName = entry2.name;
|
|
3411
3489
|
} catch (err) {
|
|
3412
3490
|
if (err instanceof ProjectNameCollisionError) {
|
|
3413
3491
|
console.error(`neat init: ${err.message}`);
|
|
@@ -3416,11 +3494,27 @@ async function runInit(opts) {
|
|
|
3416
3494
|
}
|
|
3417
3495
|
throw err;
|
|
3418
3496
|
}
|
|
3497
|
+
const siblings = await listProjects();
|
|
3498
|
+
const paused = [];
|
|
3499
|
+
for (const p of siblings) {
|
|
3500
|
+
if (p.name !== currentProjectName && p.status === "active") {
|
|
3501
|
+
await setStatus(p.name, "paused");
|
|
3502
|
+
paused.push(p.name);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
if (paused.length > 0) {
|
|
3506
|
+
const plural = paused.length === 1 ? "" : "s";
|
|
3507
|
+
console.log(
|
|
3508
|
+
`neat: paused ${paused.length} sibling project${plural}; run \`neat resume <name>\` to bring one back active.`
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
3419
3511
|
if (!opts.noInstall) {
|
|
3420
3512
|
if (opts.apply) {
|
|
3421
3513
|
let instrumented = 0;
|
|
3422
3514
|
let alreadyInstrumented = 0;
|
|
3423
3515
|
let libOnly = 0;
|
|
3516
|
+
let browserBundle = 0;
|
|
3517
|
+
let reactNative = 0;
|
|
3424
3518
|
for (const section of sections) {
|
|
3425
3519
|
const installer = INSTALLERS.find((i) => i.name === section.installer);
|
|
3426
3520
|
if (!installer) continue;
|
|
@@ -3432,13 +3526,24 @@ async function runInit(opts) {
|
|
|
3432
3526
|
alreadyInstrumented++;
|
|
3433
3527
|
} else if (outcome.outcome === "lib-only") {
|
|
3434
3528
|
libOnly++;
|
|
3529
|
+
} else if (outcome.outcome === "browser-bundle") {
|
|
3530
|
+
browserBundle++;
|
|
3531
|
+
console.log(`skipping ${section.plan.serviceDir}: browser bundle; browser-OTel support lands in a future release.`);
|
|
3532
|
+
} else if (outcome.outcome === "react-native") {
|
|
3533
|
+
reactNative++;
|
|
3534
|
+
console.log(`skipping ${section.plan.serviceDir}: React Native target; browser-OTel support lands in a future release.`);
|
|
3435
3535
|
}
|
|
3436
3536
|
}
|
|
3437
3537
|
if (sections.length > 0) {
|
|
3438
3538
|
console.log("");
|
|
3439
|
-
|
|
3440
|
-
`
|
|
3441
|
-
|
|
3539
|
+
const parts = [
|
|
3540
|
+
`instrumented ${instrumented}`,
|
|
3541
|
+
`already-instrumented ${alreadyInstrumented}`,
|
|
3542
|
+
`lib-only ${libOnly}`
|
|
3543
|
+
];
|
|
3544
|
+
if (browserBundle > 0) parts.push(`browser-bundle ${browserBundle}`);
|
|
3545
|
+
if (reactNative > 0) parts.push(`react-native ${reactNative}`);
|
|
3546
|
+
console.log(`apply: ${parts.join(", ")}`);
|
|
3442
3547
|
console.log("Run `npm install` (or your language equivalent) to refresh lockfiles.");
|
|
3443
3548
|
}
|
|
3444
3549
|
} else {
|