@neat.is/core 0.9.5-dev.20260824 → 0.9.5
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-TGCWMMF6.js → chunk-4SLKQNG7.js} +2 -2
- package/dist/{chunk-IVVF37OU.js → chunk-DGAI4VOE.js} +264 -19
- package/dist/chunk-DGAI4VOE.js.map +1 -0
- package/dist/cli.cjs +1873 -1466
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1534 -1382
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +280 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +280 -26
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +278 -24
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-IVVF37OU.js.map +0 -1
- /package/dist/{chunk-TGCWMMF6.js.map → chunk-4SLKQNG7.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16009,7 +16009,7 @@ function startPersistLoop(graph, outPath, opts = {}) {
|
|
|
16009
16009
|
init_cjs_shims();
|
|
16010
16010
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
16011
16011
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
16012
|
-
var
|
|
16012
|
+
var import_types97 = require("@neat.is/types");
|
|
16013
16013
|
|
|
16014
16014
|
// src/extend/index.ts
|
|
16015
16015
|
init_cjs_shims();
|
|
@@ -20228,9 +20228,229 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
20228
20228
|
};
|
|
20229
20229
|
}
|
|
20230
20230
|
|
|
20231
|
+
// src/connectors/gcp-lb/index.ts
|
|
20232
|
+
init_cjs_shims();
|
|
20233
|
+
|
|
20234
|
+
// src/connectors/gcp-lb/client.ts
|
|
20235
|
+
init_cjs_shims();
|
|
20236
|
+
function gcpLbRequestLogName(projectId) {
|
|
20237
|
+
return `projects/${projectId}/logs/requests`;
|
|
20238
|
+
}
|
|
20239
|
+
function buildGcpLbEntriesFilter(projectId, sinceIso) {
|
|
20240
|
+
return [
|
|
20241
|
+
`logName = "${gcpLbRequestLogName(projectId)}"`,
|
|
20242
|
+
`resource.type = "${GCP_LB_RESOURCE_TYPE}"`,
|
|
20243
|
+
'httpRequest.requestMethod != ""',
|
|
20244
|
+
`timestamp >= "${sinceIso}"`
|
|
20245
|
+
].join(" AND ");
|
|
20246
|
+
}
|
|
20247
|
+
var GCP_LB_RESOURCE_TYPE = "http_load_balancer";
|
|
20248
|
+
var DEFAULT_LOOKBACK_MS3 = 24 * 60 * 60 * 1e3;
|
|
20249
|
+
var ENTRIES_LIST_URL3 = "https://logging.googleapis.com/v2/entries:list";
|
|
20250
|
+
var PAGE_SIZE3 = 1e3;
|
|
20251
|
+
var MAX_PAGES3 = 20;
|
|
20252
|
+
async function fetchGcpLbRequestLogEntries(creds, sinceIso, apiUrl = ENTRIES_LIST_URL3) {
|
|
20253
|
+
const filter = buildGcpLbEntriesFilter(creds.projectId, sinceIso);
|
|
20254
|
+
const out = [];
|
|
20255
|
+
let pageToken;
|
|
20256
|
+
for (let page = 0; page < MAX_PAGES3; page++) {
|
|
20257
|
+
const body = {
|
|
20258
|
+
resourceNames: [`projects/${creds.projectId}`],
|
|
20259
|
+
filter,
|
|
20260
|
+
orderBy: "timestamp asc",
|
|
20261
|
+
pageSize: PAGE_SIZE3,
|
|
20262
|
+
...pageToken ? { pageToken } : {}
|
|
20263
|
+
};
|
|
20264
|
+
const res = await junctionFetch(
|
|
20265
|
+
apiUrl,
|
|
20266
|
+
{
|
|
20267
|
+
method: "POST",
|
|
20268
|
+
headers: {
|
|
20269
|
+
...bearerAuthHeader(creds.accessToken),
|
|
20270
|
+
"Content-Type": "application/json"
|
|
20271
|
+
},
|
|
20272
|
+
body: JSON.stringify(body)
|
|
20273
|
+
},
|
|
20274
|
+
// accountKey: the GCP project id — one customer's Cloud Logging quota is
|
|
20275
|
+
// scoped per GCP project (ADR-131's per-(provider, accountKey) rate-limit
|
|
20276
|
+
// bucket), the same key Cloud Run's and Firebase's connectors use.
|
|
20277
|
+
{ provider: "gcp-lb", accountKey: creds.projectId }
|
|
20278
|
+
);
|
|
20279
|
+
if (!res.ok) {
|
|
20280
|
+
throw new Error(`Cloud Logging entries.list failed: ${res.status} ${res.statusText}`);
|
|
20281
|
+
}
|
|
20282
|
+
const json = await res.json();
|
|
20283
|
+
if (Array.isArray(json.entries)) out.push(...json.entries);
|
|
20284
|
+
if (!json.nextPageToken) break;
|
|
20285
|
+
pageToken = json.nextPageToken;
|
|
20286
|
+
}
|
|
20287
|
+
return out;
|
|
20288
|
+
}
|
|
20289
|
+
|
|
20290
|
+
// src/connectors/gcp-lb/map.ts
|
|
20291
|
+
init_cjs_shims();
|
|
20292
|
+
|
|
20293
|
+
// src/connectors/gcp-lb/types.ts
|
|
20294
|
+
init_cjs_shims();
|
|
20295
|
+
function readGcpLbCredentials(raw) {
|
|
20296
|
+
const projectId = raw["projectId"];
|
|
20297
|
+
const accessToken = raw["accessToken"];
|
|
20298
|
+
if (typeof projectId !== "string" || projectId.length === 0) {
|
|
20299
|
+
throw new Error("gcp-lb connector: credentials.projectId must be a non-empty string");
|
|
20300
|
+
}
|
|
20301
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
20302
|
+
throw new Error("gcp-lb connector: credentials.accessToken must be a non-empty string");
|
|
20303
|
+
}
|
|
20304
|
+
return { projectId, accessToken };
|
|
20305
|
+
}
|
|
20306
|
+
var GCP_LB_TARGET_KIND = "http_load_balancer";
|
|
20307
|
+
var FIELD_SEP3 = "\0";
|
|
20308
|
+
function packGcpLbTargetName(identity) {
|
|
20309
|
+
return [identity.backendServiceName, identity.method, identity.path].join(FIELD_SEP3);
|
|
20310
|
+
}
|
|
20311
|
+
function parseGcpLbTargetName(targetName) {
|
|
20312
|
+
const firstSep = targetName.indexOf(FIELD_SEP3);
|
|
20313
|
+
if (firstSep === -1) return null;
|
|
20314
|
+
const backendServiceName = targetName.slice(0, firstSep);
|
|
20315
|
+
const rest = targetName.slice(firstSep + 1);
|
|
20316
|
+
const secondSep = rest.indexOf(FIELD_SEP3);
|
|
20317
|
+
if (secondSep === -1) return null;
|
|
20318
|
+
const method = rest.slice(0, secondSep);
|
|
20319
|
+
const path76 = rest.slice(secondSep + 1);
|
|
20320
|
+
if (!backendServiceName || !method || !path76) return null;
|
|
20321
|
+
return { backendServiceName, method, path: path76 };
|
|
20322
|
+
}
|
|
20323
|
+
|
|
20324
|
+
// src/connectors/gcp-lb/map.ts
|
|
20325
|
+
var GCP_LB_RESOURCE_TYPE2 = "http_load_balancer";
|
|
20326
|
+
function pathFromRequestUrl3(requestUrl) {
|
|
20327
|
+
if (typeof requestUrl !== "string" || requestUrl.length === 0) return null;
|
|
20328
|
+
if (requestUrl.startsWith("/")) {
|
|
20329
|
+
const withoutQuery = requestUrl.split("?")[0];
|
|
20330
|
+
return withoutQuery && withoutQuery.length > 0 ? withoutQuery : "/";
|
|
20331
|
+
}
|
|
20332
|
+
try {
|
|
20333
|
+
const candidate = requestUrl.startsWith("//") ? `https:${requestUrl}` : requestUrl;
|
|
20334
|
+
const parsed = new URL(candidate);
|
|
20335
|
+
return parsed.pathname || "/";
|
|
20336
|
+
} catch {
|
|
20337
|
+
return null;
|
|
20338
|
+
}
|
|
20339
|
+
}
|
|
20340
|
+
var ERROR_STATUS_THRESHOLD5 = 500;
|
|
20341
|
+
function mapLogEntryToSignal3(entry) {
|
|
20342
|
+
if (!entry || typeof entry !== "object") return null;
|
|
20343
|
+
if (entry.resource?.type !== GCP_LB_RESOURCE_TYPE2) return null;
|
|
20344
|
+
const backendServiceName = entry.resource?.labels?.["backend_service_name"];
|
|
20345
|
+
if (typeof backendServiceName !== "string" || backendServiceName.length === 0) return null;
|
|
20346
|
+
const req = entry.httpRequest;
|
|
20347
|
+
if (!req) return null;
|
|
20348
|
+
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
20349
|
+
const method = req.requestMethod.toUpperCase();
|
|
20350
|
+
const path76 = pathFromRequestUrl3(req.requestUrl);
|
|
20351
|
+
if (path76 === null) return null;
|
|
20352
|
+
const timestamp = entry.timestamp;
|
|
20353
|
+
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
20354
|
+
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
|
|
20355
|
+
return {
|
|
20356
|
+
targetKind: GCP_LB_TARGET_KIND,
|
|
20357
|
+
targetName: packGcpLbTargetName({ backendServiceName, method, path: path76 }),
|
|
20358
|
+
callCount: 1,
|
|
20359
|
+
errorCount: isError ? 1 : 0,
|
|
20360
|
+
lastObservedIso: timestamp
|
|
20361
|
+
};
|
|
20362
|
+
}
|
|
20363
|
+
function mapLogEntriesToSignals3(entries) {
|
|
20364
|
+
const out = [];
|
|
20365
|
+
for (const entry of entries) {
|
|
20366
|
+
const signal = mapLogEntryToSignal3(entry);
|
|
20367
|
+
if (signal) out.push(signal);
|
|
20368
|
+
}
|
|
20369
|
+
return out;
|
|
20370
|
+
}
|
|
20371
|
+
|
|
20372
|
+
// src/connectors/gcp-lb/resolve.ts
|
|
20373
|
+
init_cjs_shims();
|
|
20374
|
+
var import_types82 = require("@neat.is/types");
|
|
20375
|
+
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
20376
|
+
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
20377
|
+
let found = null;
|
|
20378
|
+
graph.forEachNode((_id, attrs) => {
|
|
20379
|
+
if (found) return;
|
|
20380
|
+
const node = attrs;
|
|
20381
|
+
if (node.type !== import_types82.NodeType.RouteNode) return;
|
|
20382
|
+
const route = attrs;
|
|
20383
|
+
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
20384
|
+
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
20385
|
+
const routeMethod = route.method.toUpperCase();
|
|
20386
|
+
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
20387
|
+
found = route.id;
|
|
20388
|
+
});
|
|
20389
|
+
return found;
|
|
20390
|
+
}
|
|
20391
|
+
function createGcpLbResolveTarget(graph, config) {
|
|
20392
|
+
return (signal) => {
|
|
20393
|
+
if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
|
|
20394
|
+
const identity = parseGcpLbTargetName(signal.targetName);
|
|
20395
|
+
if (!identity) return null;
|
|
20396
|
+
const { backendServiceName, method, path: path76 } = identity;
|
|
20397
|
+
const mappedService = config.backendServiceMap?.[backendServiceName];
|
|
20398
|
+
if (mappedService) {
|
|
20399
|
+
const routeNodeId = findMatchingRouteNode3(
|
|
20400
|
+
graph,
|
|
20401
|
+
mappedService,
|
|
20402
|
+
method,
|
|
20403
|
+
normalizePathTemplate(path76)
|
|
20404
|
+
);
|
|
20405
|
+
if (routeNodeId) {
|
|
20406
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
20407
|
+
}
|
|
20408
|
+
}
|
|
20409
|
+
return {
|
|
20410
|
+
targetNodeId: (0, import_types82.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
|
|
20411
|
+
serviceName: mappedService ?? backendServiceName,
|
|
20412
|
+
edgeType: import_types82.EdgeType.CALLS,
|
|
20413
|
+
ensureInfraNode: {
|
|
20414
|
+
kind: GCP_LB_BACKEND_INFRA_KIND,
|
|
20415
|
+
name: backendServiceName,
|
|
20416
|
+
provider: "gcp-lb"
|
|
20417
|
+
}
|
|
20418
|
+
};
|
|
20419
|
+
};
|
|
20420
|
+
}
|
|
20421
|
+
|
|
20422
|
+
// src/connectors/gcp-lb/index.ts
|
|
20423
|
+
var GcpLbConnector = class {
|
|
20424
|
+
constructor(config = {}) {
|
|
20425
|
+
this.config = config;
|
|
20426
|
+
}
|
|
20427
|
+
config;
|
|
20428
|
+
provider = "gcp-lb";
|
|
20429
|
+
async poll(ctx) {
|
|
20430
|
+
const creds = readGcpLbCredentials(ctx.credentials);
|
|
20431
|
+
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_LOOKBACK_MS3;
|
|
20432
|
+
const sinceIso = boundedSinceIso2(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20433
|
+
const entries = await fetchGcpLbRequestLogEntries(creds, sinceIso, this.config.apiUrl);
|
|
20434
|
+
return mapLogEntriesToSignals3(entries);
|
|
20435
|
+
}
|
|
20436
|
+
};
|
|
20437
|
+
function boundedSinceIso2(since, now, maxLookbackMs) {
|
|
20438
|
+
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20439
|
+
if (!since) return floor.toISOString();
|
|
20440
|
+
const sinceMs = new Date(since).getTime();
|
|
20441
|
+
if (Number.isNaN(sinceMs)) return floor.toISOString();
|
|
20442
|
+
return sinceMs < floor.getTime() ? floor.toISOString() : new Date(sinceMs).toISOString();
|
|
20443
|
+
}
|
|
20444
|
+
function createGcpLbConnector(graph, config = {}) {
|
|
20445
|
+
return {
|
|
20446
|
+
connector: new GcpLbConnector(config),
|
|
20447
|
+
resolveTarget: createGcpLbResolveTarget(graph, config)
|
|
20448
|
+
};
|
|
20449
|
+
}
|
|
20450
|
+
|
|
20231
20451
|
// src/connectors/render/index.ts
|
|
20232
20452
|
init_cjs_shims();
|
|
20233
|
-
var
|
|
20453
|
+
var import_types85 = require("@neat.is/types");
|
|
20234
20454
|
|
|
20235
20455
|
// src/connectors/render/types.ts
|
|
20236
20456
|
init_cjs_shims();
|
|
@@ -20308,7 +20528,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
20308
20528
|
const out = [];
|
|
20309
20529
|
graph.forEachNode((_id, attrs) => {
|
|
20310
20530
|
const node = attrs;
|
|
20311
|
-
if (node.type !==
|
|
20531
|
+
if (node.type !== import_types85.NodeType.RouteNode) return;
|
|
20312
20532
|
const route = attrs;
|
|
20313
20533
|
if (route.service !== serviceName) return;
|
|
20314
20534
|
out.push({
|
|
@@ -20393,7 +20613,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
20393
20613
|
function createRenderResolveTarget(config) {
|
|
20394
20614
|
return (signal) => {
|
|
20395
20615
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
20396
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
20616
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
|
|
20397
20617
|
}
|
|
20398
20618
|
return null;
|
|
20399
20619
|
};
|
|
@@ -20531,21 +20751,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
20531
20751
|
|
|
20532
20752
|
// src/connectors/planetscale/resolve.ts
|
|
20533
20753
|
init_cjs_shims();
|
|
20534
|
-
var
|
|
20754
|
+
var import_types89 = require("@neat.is/types");
|
|
20535
20755
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
20536
20756
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
20537
20757
|
const databaseName = `${config.organization}/${config.database}`;
|
|
20538
20758
|
return (signal, _ctx) => {
|
|
20539
20759
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
20540
|
-
const tableId = (0,
|
|
20760
|
+
const tableId = (0, import_types89.infraId)("sql-table", signal.targetName);
|
|
20541
20761
|
if (graph.hasNode(tableId)) {
|
|
20542
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
20762
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
|
|
20543
20763
|
}
|
|
20544
|
-
const providerId = (0,
|
|
20764
|
+
const providerId = (0, import_types89.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
20545
20765
|
return {
|
|
20546
20766
|
targetNodeId: providerId,
|
|
20547
20767
|
serviceName: config.serviceName,
|
|
20548
|
-
edgeType:
|
|
20768
|
+
edgeType: import_types89.EdgeType.CALLS,
|
|
20549
20769
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
20550
20770
|
};
|
|
20551
20771
|
};
|
|
@@ -20611,13 +20831,13 @@ function isTransientFailure(err) {
|
|
|
20611
20831
|
if (code && INTERNAL_ERROR_CODE.test(code)) return true;
|
|
20612
20832
|
return false;
|
|
20613
20833
|
}
|
|
20614
|
-
var
|
|
20834
|
+
var FIELD_SEP4 = "\0";
|
|
20615
20835
|
var EAS_TARGET_KIND = "eas-build";
|
|
20616
20836
|
function packEasTargetName(identity) {
|
|
20617
|
-
return [identity.serviceName, identity.phase].join(
|
|
20837
|
+
return [identity.serviceName, identity.phase].join(FIELD_SEP4);
|
|
20618
20838
|
}
|
|
20619
20839
|
function parseEasTargetName(targetName) {
|
|
20620
|
-
const sep = targetName.indexOf(
|
|
20840
|
+
const sep = targetName.indexOf(FIELD_SEP4);
|
|
20621
20841
|
if (sep === -1) return null;
|
|
20622
20842
|
const serviceName = targetName.slice(0, sep);
|
|
20623
20843
|
const phase = targetName.slice(sep + 1);
|
|
@@ -20810,7 +21030,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
20810
21030
|
|
|
20811
21031
|
// src/connectors/eas/resolve.ts
|
|
20812
21032
|
init_cjs_shims();
|
|
20813
|
-
var
|
|
21033
|
+
var import_types94 = require("@neat.is/types");
|
|
20814
21034
|
var NO_ENV2 = "unknown";
|
|
20815
21035
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
20816
21036
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -20826,8 +21046,8 @@ function configBasenamesForPhase(phase) {
|
|
|
20826
21046
|
function configNodeService(graph, configNodeId) {
|
|
20827
21047
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
20828
21048
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
20829
|
-
if (edge.type !==
|
|
20830
|
-
const parsed = (0,
|
|
21049
|
+
if (edge.type !== import_types94.EdgeType.CONFIGURED_BY) continue;
|
|
21050
|
+
const parsed = (0, import_types94.parseFileId)(edge.source);
|
|
20831
21051
|
if (parsed) return parsed.service;
|
|
20832
21052
|
}
|
|
20833
21053
|
return null;
|
|
@@ -20838,7 +21058,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
20838
21058
|
graph.forEachNode((id, attrs) => {
|
|
20839
21059
|
if (scoped) return;
|
|
20840
21060
|
const node = attrs;
|
|
20841
|
-
if (node.type !==
|
|
21061
|
+
if (node.type !== import_types94.NodeType.ConfigNode) return;
|
|
20842
21062
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
20843
21063
|
if (anyMatch === null) anyMatch = id;
|
|
20844
21064
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -20855,13 +21075,13 @@ function createEasResolveTarget(graph) {
|
|
|
20855
21075
|
if (basenames.length > 0) {
|
|
20856
21076
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
20857
21077
|
if (configNodeId) {
|
|
20858
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
21078
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types94.EdgeType.CALLS };
|
|
20859
21079
|
}
|
|
20860
21080
|
}
|
|
20861
21081
|
return {
|
|
20862
21082
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
20863
21083
|
serviceName,
|
|
20864
|
-
edgeType:
|
|
21084
|
+
edgeType: import_types94.EdgeType.CALLS
|
|
20865
21085
|
};
|
|
20866
21086
|
};
|
|
20867
21087
|
}
|
|
@@ -20873,7 +21093,7 @@ function isBuildSince(build, sinceIso) {
|
|
|
20873
21093
|
if (Number.isNaN(t) || Number.isNaN(s)) return true;
|
|
20874
21094
|
return t > s;
|
|
20875
21095
|
}
|
|
20876
|
-
function
|
|
21096
|
+
function boundedSinceIso3(since, now, maxLookbackMs) {
|
|
20877
21097
|
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20878
21098
|
if (!since) return floor.toISOString();
|
|
20879
21099
|
const sinceMs = new Date(since).getTime();
|
|
@@ -20892,7 +21112,7 @@ var EasConnector = class {
|
|
|
20892
21112
|
const creds = readEasCredentials(ctx.credentials);
|
|
20893
21113
|
const serviceName = this.config.serviceName ?? this.config.appId;
|
|
20894
21114
|
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_MAX_LOOKBACK_MS6;
|
|
20895
|
-
const sinceIso =
|
|
21115
|
+
const sinceIso = boundedSinceIso3(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20896
21116
|
const builds = await fetchErroredBuilds(creds.token, this.config, this.fetchImpl);
|
|
20897
21117
|
const fresh = builds.filter((b) => isBuildSince(b, sinceIso));
|
|
20898
21118
|
const maxLogBytes = this.config.maxLogBytes ?? DEFAULT_MAX_LOG_BYTES;
|
|
@@ -21123,6 +21343,40 @@ var PROVIDER_DISPATCH = {
|
|
|
21123
21343
|
});
|
|
21124
21344
|
}
|
|
21125
21345
|
},
|
|
21346
|
+
"gcp-lb": {
|
|
21347
|
+
provider: "gcp-lb",
|
|
21348
|
+
// Like cloud-run, gcp-lb reads both projectId and accessToken from the
|
|
21349
|
+
// credential; the single-string form maps to the secret (the token), and the
|
|
21350
|
+
// required-fields check below catches a projectId that was never supplied.
|
|
21351
|
+
primaryCredentialKey: "accessToken",
|
|
21352
|
+
requiredCredentialFields: ["projectId", "accessToken"],
|
|
21353
|
+
requiredOptionFields: [],
|
|
21354
|
+
build(graph, options) {
|
|
21355
|
+
return createGcpLbConnector(graph, options);
|
|
21356
|
+
},
|
|
21357
|
+
// POST entries:list with pageSize 1 — the exact surface poll() reads, so the
|
|
21358
|
+
// probe checks the actual `logging.logEntries.list` permission the connector
|
|
21359
|
+
// needs. This is the same Cloud Logging read-verdict cloud-run's validate
|
|
21360
|
+
// uses (a lighter GET on logs.list would instead check `logging.logs.list`,
|
|
21361
|
+
// falsely rejecting a correctly-scoped custom role carrying only
|
|
21362
|
+
// `logging.logEntries.list`). A 2xx means the token can list log entries;
|
|
21363
|
+
// 401/403 means the provider rejected it.
|
|
21364
|
+
validate({ credentials, fetchImpl }) {
|
|
21365
|
+
const projectId = String(credentials.projectId ?? "");
|
|
21366
|
+
return authProbe({
|
|
21367
|
+
provider: "gcp-lb",
|
|
21368
|
+
accountKey: projectId || "validate",
|
|
21369
|
+
url: "https://logging.googleapis.com/v2/entries:list",
|
|
21370
|
+
token: String(credentials.accessToken ?? ""),
|
|
21371
|
+
init: {
|
|
21372
|
+
method: "POST",
|
|
21373
|
+
headers: { "Content-Type": "application/json" },
|
|
21374
|
+
body: JSON.stringify({ resourceNames: [`projects/${projectId}`], pageSize: 1 })
|
|
21375
|
+
},
|
|
21376
|
+
...fetchImpl ? { fetchImpl } : {}
|
|
21377
|
+
});
|
|
21378
|
+
}
|
|
21379
|
+
},
|
|
21126
21380
|
render: {
|
|
21127
21381
|
provider: "render",
|
|
21128
21382
|
primaryCredentialKey: "token",
|
|
@@ -21588,11 +21842,11 @@ function registerRoutes(scope, ctx) {
|
|
|
21588
21842
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
21589
21843
|
const parsed = [];
|
|
21590
21844
|
for (const c of candidates) {
|
|
21591
|
-
const r =
|
|
21845
|
+
const r = import_types97.DivergenceTypeSchema.safeParse(c);
|
|
21592
21846
|
if (!r.success) {
|
|
21593
21847
|
return reply.code(400).send({
|
|
21594
21848
|
error: `unknown divergence type "${c}"`,
|
|
21595
|
-
allowed:
|
|
21849
|
+
allowed: import_types97.DivergenceTypeSchema.options
|
|
21596
21850
|
});
|
|
21597
21851
|
}
|
|
21598
21852
|
parsed.push(r.data);
|
|
@@ -21954,7 +22208,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21954
22208
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
21955
22209
|
let violations = await log.readAll();
|
|
21956
22210
|
if (req.query.severity) {
|
|
21957
|
-
const sev =
|
|
22211
|
+
const sev = import_types97.PolicySeveritySchema.safeParse(req.query.severity);
|
|
21958
22212
|
if (!sev.success) {
|
|
21959
22213
|
return reply.code(400).send({
|
|
21960
22214
|
error: "invalid severity",
|
|
@@ -21993,7 +22247,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21993
22247
|
scope.post("/policies/check", async (req, reply) => {
|
|
21994
22248
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
21995
22249
|
if (!proj) return;
|
|
21996
|
-
const parsed =
|
|
22250
|
+
const parsed = import_types97.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
21997
22251
|
if (!parsed.success) {
|
|
21998
22252
|
return reply.code(400).send({
|
|
21999
22253
|
error: "invalid /policies/check body",
|
|
@@ -22342,7 +22596,7 @@ function unroutedErrorsPath(neatHome3) {
|
|
|
22342
22596
|
}
|
|
22343
22597
|
|
|
22344
22598
|
// src/daemon.ts
|
|
22345
|
-
var
|
|
22599
|
+
var import_types98 = require("@neat.is/types");
|
|
22346
22600
|
function daemonJsonPath(scanPath) {
|
|
22347
22601
|
return import_node_path75.default.join(scanPath, "neat-out", "daemon.json");
|
|
22348
22602
|
}
|
|
@@ -22467,7 +22721,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
|
|
|
22467
22721
|
if (!serviceName) return true;
|
|
22468
22722
|
if (serviceNameMatchesProject(serviceName, project)) return true;
|
|
22469
22723
|
return graph.someNode(
|
|
22470
|
-
(_id, attrs) => attrs.type ===
|
|
22724
|
+
(_id, attrs) => attrs.type === import_types98.NodeType.ServiceNode && attrs.name === serviceName
|
|
22471
22725
|
);
|
|
22472
22726
|
}
|
|
22473
22727
|
async function bootstrapProject(entry, connectors = [], neatHome3) {
|