@cmflow/atlas 3.7.0 → 3.8.0
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/README.md +14 -0
- package/dist/{UserConfig-BlRknCRh.d.mts → UserConfig-CIMgqCt1.d.mts} +9 -4
- package/dist/bin/atlas.mjs +270 -157
- package/dist/bin/atlas.mjs.map +1 -1
- package/dist/{dist-D8VumL0r.mjs → dist-DIU2ATkt.mjs} +231 -10
- package/dist/dist-DIU2ATkt.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +24 -7
- package/dist/index.mjs.map +1 -1
- package/dist/rules/lodashGetRule.d.mts +1 -1
- package/dist/rules/mappingUtilityRule.d.mts +1 -1
- package/dist/rules/memberGetFieldRule.d.mts +1 -1
- package/package.json +2 -1
- package/dist/dist-D8VumL0r.mjs.map +0 -1
package/dist/bin/atlas.mjs
CHANGED
|
@@ -4,13 +4,13 @@ const __filename = __atlasFileURLToPath(import.meta.url);
|
|
|
4
4
|
import { n as __require, r as __toESM, t as __commonJSMin } from "../rolldown-runtime-CGR6nZuH.mjs";
|
|
5
5
|
import { a as isCancel, c as userConfig$1, i as select, n as atlasLogger, o as getUserConfig, r as progress, s as setUserConfig, t as taskProgressService } from "../taskProgressService-DAEpEqsT.mjs";
|
|
6
6
|
import { a as resolveModulePath, c as filterAnalysisFiles, d as globby, i as matchesRouteSelector, l as shouldKeepAnalysisFile, n as generateBackendTopologyArtifactsInWorkers, o as inferBackendNameFromFile, s as isKnownBackendType, u as normalizeFilePath } from "../routeBackendTopologyService-_-yZSfG8.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { c as loadOpenApiDocument, i as extractOpenApiOutputProperties, o as transformTypeFrom, r as extractOpenApiInputProperties, s as pickPropertyMetadata, t as require_dist$1 } from "../dist-DIU2ATkt.mjs";
|
|
8
8
|
import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "../token-util-Dnzm6rU4.mjs";
|
|
9
9
|
import { readFileSync } from "node:fs";
|
|
10
10
|
import path, { resolve } from "node:path";
|
|
11
11
|
import { Node, Project, SyntaxKind } from "ts-morph";
|
|
12
12
|
import fsPromises from "node:fs/promises";
|
|
13
|
-
import { createHash } from "node:crypto";
|
|
13
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
14
14
|
|
|
15
15
|
//#region node_modules/commander/lib/error.js
|
|
16
16
|
var require_error = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
@@ -2948,18 +2948,12 @@ async function createClient() {
|
|
|
2948
2948
|
//#region src/services/directus/queries/deleteOrphanedPropertyLinks.ts
|
|
2949
2949
|
const DIRECTUS_DELETE_WORKERS = 2;
|
|
2950
2950
|
async function deleteOrphanedPropertyLinks(client, orphanedLinks) {
|
|
2951
|
-
const links =
|
|
2952
|
-
collection: "route_input_properties_backend_properties",
|
|
2953
|
-
id: link.id
|
|
2954
|
-
})), ...orphanedLinks.output.map((link) => ({
|
|
2955
|
-
collection: "route_output_properties_backend_properties",
|
|
2956
|
-
id: link.id
|
|
2957
|
-
}))];
|
|
2951
|
+
const links = orphanedLinks.links;
|
|
2958
2952
|
let nextIndex = 0;
|
|
2959
2953
|
await Promise.all(Array.from({ length: Math.min(DIRECTUS_DELETE_WORKERS, links.length) }, async () => {
|
|
2960
2954
|
while (nextIndex < links.length) {
|
|
2961
2955
|
const link = links[nextIndex++];
|
|
2962
|
-
await client.request(r$1(
|
|
2956
|
+
await client.request(r$1("route_properties_backend_properties", link.id));
|
|
2963
2957
|
}
|
|
2964
2958
|
}));
|
|
2965
2959
|
return links.length;
|
|
@@ -2968,12 +2962,8 @@ async function deleteOrphanedPropertyLinks(client, orphanedLinks) {
|
|
|
2968
2962
|
//#endregion
|
|
2969
2963
|
//#region src/services/directus/queries/findOrphanedPropertyLinks.ts
|
|
2970
2964
|
async function findOrphanedPropertyLinks(client) {
|
|
2971
|
-
const [
|
|
2972
|
-
client.request(n$1("
|
|
2973
|
-
fields: ["id"],
|
|
2974
|
-
limit: -1
|
|
2975
|
-
})),
|
|
2976
|
-
client.request(n$1("route_output_properties", {
|
|
2965
|
+
const [routeProperties, backendProperties, links] = await Promise.all([
|
|
2966
|
+
client.request(n$1("route_properties", {
|
|
2977
2967
|
fields: ["id"],
|
|
2978
2968
|
limit: -1
|
|
2979
2969
|
})),
|
|
@@ -2981,31 +2971,19 @@ async function findOrphanedPropertyLinks(client) {
|
|
|
2981
2971
|
fields: ["id"],
|
|
2982
2972
|
limit: -1
|
|
2983
2973
|
})),
|
|
2984
|
-
client.request(n$1("
|
|
2985
|
-
fields: [
|
|
2986
|
-
"id",
|
|
2987
|
-
"route_input_properties_id",
|
|
2988
|
-
"backend_properties_id"
|
|
2989
|
-
],
|
|
2990
|
-
limit: -1
|
|
2991
|
-
})),
|
|
2992
|
-
client.request(n$1("route_output_properties_backend_properties", {
|
|
2974
|
+
client.request(n$1("route_properties_backend_properties", {
|
|
2993
2975
|
fields: [
|
|
2994
2976
|
"id",
|
|
2995
|
-
"
|
|
2977
|
+
"route_properties_id",
|
|
2996
2978
|
"backend_properties_id"
|
|
2997
2979
|
],
|
|
2998
2980
|
limit: -1
|
|
2999
2981
|
}))
|
|
3000
2982
|
]);
|
|
3001
2983
|
const ids = (items) => new Set(items.map((item) => String(item.id)));
|
|
3002
|
-
const
|
|
3003
|
-
const outputIds = ids(outputProperties);
|
|
2984
|
+
const routePropertyIds = ids(routeProperties);
|
|
3004
2985
|
const backendIds = ids(backendProperties);
|
|
3005
|
-
return {
|
|
3006
|
-
input: inputLinks.filter((link) => !inputIds.has(String(link.route_input_properties_id)) || !backendIds.has(String(link.backend_properties_id))),
|
|
3007
|
-
output: outputLinks.filter((link) => !outputIds.has(String(link.route_output_properties_id)) || !backendIds.has(String(link.backend_properties_id)))
|
|
3008
|
-
};
|
|
2986
|
+
return { links: links.filter((link) => !routePropertyIds.has(String(link.route_properties_id)) || !backendIds.has(String(link.backend_properties_id))) };
|
|
3009
2987
|
}
|
|
3010
2988
|
|
|
3011
2989
|
//#endregion
|
|
@@ -3015,7 +2993,7 @@ async function cleanDirectusOrphanedPropertyLinks(options) {
|
|
|
3015
2993
|
const client = await createClient();
|
|
3016
2994
|
taskProgressService.report("Finding orphaned property links");
|
|
3017
2995
|
const orphanedLinks = await findOrphanedPropertyLinks(client);
|
|
3018
|
-
const orphanedCount = orphanedLinks.
|
|
2996
|
+
const orphanedCount = orphanedLinks.links.length;
|
|
3019
2997
|
if (options.dryRun) {
|
|
3020
2998
|
taskProgressService.report(`${orphanedCount} orphaned property links found (dry-run)`);
|
|
3021
2999
|
return {
|
|
@@ -3050,17 +3028,17 @@ async function cleanupOrphanedPropertyLinks(client) {
|
|
|
3050
3028
|
//#endregion
|
|
3051
3029
|
//#region src/services/directus/queries/ensureInputLink.ts
|
|
3052
3030
|
async function ensureInputLink(client, inputPropertyId, backendPropertyId) {
|
|
3053
|
-
const [existing] = await client.request(n$1("
|
|
3031
|
+
const [existing] = await client.request(n$1("route_properties_backend_properties", {
|
|
3054
3032
|
filter: {
|
|
3055
|
-
|
|
3033
|
+
route_properties_id: { _eq: inputPropertyId },
|
|
3056
3034
|
backend_properties_id: { _eq: backendPropertyId }
|
|
3057
3035
|
},
|
|
3058
3036
|
fields: ["id"],
|
|
3059
3037
|
limit: 1
|
|
3060
3038
|
}));
|
|
3061
3039
|
if (existing) return false;
|
|
3062
|
-
await client.request(n$2("
|
|
3063
|
-
|
|
3040
|
+
await client.request(n$2("route_properties_backend_properties", {
|
|
3041
|
+
route_properties_id: inputPropertyId,
|
|
3064
3042
|
backend_properties_id: backendPropertyId
|
|
3065
3043
|
}));
|
|
3066
3044
|
return true;
|
|
@@ -3069,17 +3047,17 @@ async function ensureInputLink(client, inputPropertyId, backendPropertyId) {
|
|
|
3069
3047
|
//#endregion
|
|
3070
3048
|
//#region src/services/directus/queries/ensureOutputLink.ts
|
|
3071
3049
|
async function ensureOutputLink(client, outputPropertyId, backendPropertyId) {
|
|
3072
|
-
const [existing] = await client.request(n$1("
|
|
3050
|
+
const [existing] = await client.request(n$1("route_properties_backend_properties", {
|
|
3073
3051
|
filter: {
|
|
3074
|
-
|
|
3052
|
+
route_properties_id: { _eq: outputPropertyId },
|
|
3075
3053
|
backend_properties_id: { _eq: backendPropertyId }
|
|
3076
3054
|
},
|
|
3077
3055
|
fields: ["id"],
|
|
3078
3056
|
limit: 1
|
|
3079
3057
|
}));
|
|
3080
3058
|
if (existing) return false;
|
|
3081
|
-
await client.request(n$2("
|
|
3082
|
-
|
|
3059
|
+
await client.request(n$2("route_properties_backend_properties", {
|
|
3060
|
+
route_properties_id: outputPropertyId,
|
|
3083
3061
|
backend_properties_id: backendPropertyId
|
|
3084
3062
|
}));
|
|
3085
3063
|
return true;
|
|
@@ -3092,7 +3070,8 @@ async function loadDirectusReferenceData(client) {
|
|
|
3092
3070
|
filter: { type: { _in: [
|
|
3093
3071
|
"backend",
|
|
3094
3072
|
"in_type",
|
|
3095
|
-
"out_type"
|
|
3073
|
+
"out_type",
|
|
3074
|
+
"data_type"
|
|
3096
3075
|
] } },
|
|
3097
3076
|
fields: [
|
|
3098
3077
|
"id",
|
|
@@ -3113,9 +3092,10 @@ async function loadDirectusReferenceData(client) {
|
|
|
3113
3092
|
const inTypeIds = /* @__PURE__ */ new Map();
|
|
3114
3093
|
const outTypeIds = /* @__PURE__ */ new Map();
|
|
3115
3094
|
const documentIds = /* @__PURE__ */ new Map();
|
|
3095
|
+
const dataTypeIds = /* @__PURE__ */ new Map();
|
|
3116
3096
|
for (const value of values) {
|
|
3117
3097
|
const normalizedKeys = [normalizeLookupKey(value.id), normalizeLookupKey(value.label)];
|
|
3118
|
-
const target = value.type === "backend" ? backendIds : value.type === "in_type" ? inTypeIds : outTypeIds;
|
|
3098
|
+
const target = value.type === "backend" ? backendIds : value.type === "in_type" ? inTypeIds : value.type === "out_type" ? outTypeIds : dataTypeIds;
|
|
3119
3099
|
for (const key of normalizedKeys) target.set(key, value.id);
|
|
3120
3100
|
}
|
|
3121
3101
|
for (const value of documentValues) {
|
|
@@ -3126,7 +3106,8 @@ async function loadDirectusReferenceData(client) {
|
|
|
3126
3106
|
backendIds,
|
|
3127
3107
|
inTypeIds,
|
|
3128
3108
|
outTypeIds,
|
|
3129
|
-
documentIds
|
|
3109
|
+
documentIds,
|
|
3110
|
+
dataTypeIds
|
|
3130
3111
|
};
|
|
3131
3112
|
}
|
|
3132
3113
|
|
|
@@ -3354,6 +3335,13 @@ function dedupeByKey(items, keyFn) {
|
|
|
3354
3335
|
return [...map.values()];
|
|
3355
3336
|
}
|
|
3356
3337
|
|
|
3338
|
+
//#endregion
|
|
3339
|
+
//#region src/utils/path/isArrayPath.ts
|
|
3340
|
+
/** Whether a property path denotes an array element (e.g. `offers[].id`). */
|
|
3341
|
+
function isArrayPath(path) {
|
|
3342
|
+
return path.includes("[]");
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3357
3345
|
//#endregion
|
|
3358
3346
|
//#region src/services/codeAnalysisService.ts
|
|
3359
3347
|
const userConfig = new Proxy({}, { get: (_target, property) => Reflect.get(getUserConfig(), property) });
|
|
@@ -4457,15 +4445,26 @@ function resolveApiPropertySource(document, property, direction, matches = []) {
|
|
|
4457
4445
|
return match ? `${match.sourceFile}:${match.line}` : matches[0] ? backendFieldSource(matches[0]) : document.routeFile || null;
|
|
4458
4446
|
}
|
|
4459
4447
|
function ensureBackendRouteRecord(backendRoutesByKey, document, candidate) {
|
|
4460
|
-
const
|
|
4448
|
+
const isDocument = "document" in candidate;
|
|
4449
|
+
const sourceId = isDocument ? candidate.document : candidate.route;
|
|
4450
|
+
const key = stableKey(document.key, candidate.backend, sourceId);
|
|
4461
4451
|
const existing = backendRoutesByKey.get(key);
|
|
4462
4452
|
if (existing) return existing;
|
|
4463
|
-
const created = {
|
|
4453
|
+
const created = isDocument ? {
|
|
4454
|
+
key,
|
|
4455
|
+
backend: candidate.backend,
|
|
4456
|
+
route_key: document.key,
|
|
4457
|
+
resource_type: "document",
|
|
4458
|
+
document: candidate.document,
|
|
4459
|
+
source_file: candidate.sourceFile,
|
|
4460
|
+
provenance: "code_analysis"
|
|
4461
|
+
} : {
|
|
4464
4462
|
key,
|
|
4465
4463
|
backend: candidate.backend,
|
|
4466
4464
|
route_key: document.key,
|
|
4467
4465
|
resource_type: "http",
|
|
4468
|
-
|
|
4466
|
+
method: candidate.method || void 0,
|
|
4467
|
+
route: candidate.route,
|
|
4469
4468
|
source_file: candidate.sourceFile,
|
|
4470
4469
|
provenance: "code_analysis"
|
|
4471
4470
|
};
|
|
@@ -4483,6 +4482,7 @@ function toBackendMapping(document, match) {
|
|
|
4483
4482
|
document: resolved.document,
|
|
4484
4483
|
field: resolved.field,
|
|
4485
4484
|
description: resolved.description,
|
|
4485
|
+
...pickPropertyMetadata(resolved),
|
|
4486
4486
|
source_file: backendFieldSource(match),
|
|
4487
4487
|
confidence: match.confidence,
|
|
4488
4488
|
mapper_type: match.mapperType,
|
|
@@ -4492,15 +4492,20 @@ function toBackendMapping(document, match) {
|
|
|
4492
4492
|
return {
|
|
4493
4493
|
backend: match.backend,
|
|
4494
4494
|
method: backendRouteCandidate?.method || null,
|
|
4495
|
-
route: backendRouteCandidate?.route || "
|
|
4495
|
+
route: backendRouteCandidate?.route || "",
|
|
4496
4496
|
field: resolved?.field || match.backendField,
|
|
4497
4497
|
description: resolved?.description,
|
|
4498
|
+
...pickPropertyMetadata(resolved),
|
|
4498
4499
|
source_file: backendFieldSource(match),
|
|
4499
4500
|
confidence: match.confidence,
|
|
4500
4501
|
mapper_type: match.mapperType,
|
|
4501
4502
|
reason: match.reviewReason
|
|
4502
4503
|
};
|
|
4503
4504
|
}
|
|
4505
|
+
function toApiPropertyDataType(property) {
|
|
4506
|
+
if (!property.data_type || property.data_type === "unknow" || property.data_type.endsWith("[]")) return property.data_type;
|
|
4507
|
+
return isArrayPath(property.path) ? `${property.data_type}[]` : property.data_type;
|
|
4508
|
+
}
|
|
4504
4509
|
async function buildCatalogue(documents) {
|
|
4505
4510
|
const routes = documents.map((document) => ({
|
|
4506
4511
|
key: document.key,
|
|
@@ -4550,6 +4555,8 @@ async function buildCatalogue(documents) {
|
|
|
4550
4555
|
field: property.path,
|
|
4551
4556
|
domain_field: apiSource?.domainField,
|
|
4552
4557
|
transversal: isTransversalInput(property) || void 0,
|
|
4558
|
+
...pickPropertyMetadata(property),
|
|
4559
|
+
data_type: toApiPropertyDataType(property),
|
|
4553
4560
|
backend_names: backendNames,
|
|
4554
4561
|
backend_mappings: backendMappings,
|
|
4555
4562
|
description: normalizeDescription(property.description),
|
|
@@ -4568,9 +4575,14 @@ async function buildCatalogue(documents) {
|
|
|
4568
4575
|
source_file: document.routeFile || null
|
|
4569
4576
|
});
|
|
4570
4577
|
for (const match of matches) {
|
|
4571
|
-
const
|
|
4578
|
+
const resolvedDocument = match.resolvedProperty && "document" in match.resolvedProperty ? match.resolvedProperty.document : void 0;
|
|
4579
|
+
const backendRouteKey = ensureBackendRouteRecord(backendRoutesByKey, document, resolvedDocument ? {
|
|
4572
4580
|
backend: match.backend,
|
|
4573
|
-
|
|
4581
|
+
document: resolvedDocument,
|
|
4582
|
+
sourceFile: match.sourceFile
|
|
4583
|
+
} : resolveBackendRouteCandidate(document, match) || {
|
|
4584
|
+
backend: match.backend,
|
|
4585
|
+
route: "",
|
|
4574
4586
|
sourceFile: match.sourceFile
|
|
4575
4587
|
}).key;
|
|
4576
4588
|
const backendPropertyKey = stableKey(backendRouteKey, "input", match.resolvedProperty?.field || match.backendField);
|
|
@@ -4581,6 +4593,7 @@ async function buildCatalogue(documents) {
|
|
|
4581
4593
|
field: match.resolvedProperty?.field || match.backendField,
|
|
4582
4594
|
document: match.resolvedProperty && "document" in match.resolvedProperty ? match.resolvedProperty.document : void 0,
|
|
4583
4595
|
description: match.resolvedProperty?.description,
|
|
4596
|
+
...pickPropertyMetadata(match.resolvedProperty),
|
|
4584
4597
|
direction: "input",
|
|
4585
4598
|
source_file: backendFieldSource(match),
|
|
4586
4599
|
provenance: "code_analysis"
|
|
@@ -4611,6 +4624,8 @@ async function buildCatalogue(documents) {
|
|
|
4611
4624
|
direction: "output",
|
|
4612
4625
|
field: property.path,
|
|
4613
4626
|
domain_field: apiSource?.domainField,
|
|
4627
|
+
...pickPropertyMetadata(property),
|
|
4628
|
+
data_type: toApiPropertyDataType(property),
|
|
4614
4629
|
backend_names: backendNames,
|
|
4615
4630
|
backend_mappings: backendMappings,
|
|
4616
4631
|
description: normalizeDescription(property.description),
|
|
@@ -4630,9 +4645,14 @@ async function buildCatalogue(documents) {
|
|
|
4630
4645
|
source_file: document.routeFile || null
|
|
4631
4646
|
});
|
|
4632
4647
|
for (const match of matches) {
|
|
4633
|
-
const
|
|
4648
|
+
const resolvedDocument = match.resolvedProperty && "document" in match.resolvedProperty ? match.resolvedProperty.document : void 0;
|
|
4649
|
+
const backendRouteKey = ensureBackendRouteRecord(backendRoutesByKey, document, resolvedDocument ? {
|
|
4650
|
+
backend: match.backend,
|
|
4651
|
+
document: resolvedDocument,
|
|
4652
|
+
sourceFile: match.sourceFile
|
|
4653
|
+
} : resolveBackendRouteCandidate(document, match) || {
|
|
4634
4654
|
backend: match.backend,
|
|
4635
|
-
route: "
|
|
4655
|
+
route: "",
|
|
4636
4656
|
sourceFile: match.sourceFile
|
|
4637
4657
|
}).key;
|
|
4638
4658
|
const backendPropertyKey = stableKey(backendRouteKey, "output", match.resolvedProperty?.field || match.backendField);
|
|
@@ -4643,6 +4663,7 @@ async function buildCatalogue(documents) {
|
|
|
4643
4663
|
field: match.resolvedProperty?.field || match.backendField,
|
|
4644
4664
|
document: match.resolvedProperty && "document" in match.resolvedProperty ? match.resolvedProperty.document : void 0,
|
|
4645
4665
|
description: match.resolvedProperty?.description,
|
|
4666
|
+
...pickPropertyMetadata(match.resolvedProperty),
|
|
4646
4667
|
direction: "output",
|
|
4647
4668
|
source_file: backendFieldSource(match),
|
|
4648
4669
|
provenance: "code_analysis"
|
|
@@ -4692,6 +4713,20 @@ function toPascalCase(value) {
|
|
|
4692
4713
|
return value.toLowerCase().replace(/(^|[^a-z0-9]+)([a-z0-9])/g, (_match, _separator, character) => character.toUpperCase());
|
|
4693
4714
|
}
|
|
4694
4715
|
|
|
4716
|
+
//#endregion
|
|
4717
|
+
//#region src/services/directus/queries/createPredefinedValue.ts
|
|
4718
|
+
/**
|
|
4719
|
+
* Creates a Directus predefined value while retaining the attempted identity in
|
|
4720
|
+
* any error reported by the push command.
|
|
4721
|
+
*/
|
|
4722
|
+
async function createPredefinedValue(client, payload) {
|
|
4723
|
+
try {
|
|
4724
|
+
return await client.request(n$2("predefined_values", payload));
|
|
4725
|
+
} catch (error) {
|
|
4726
|
+
throw new Error(`Unable to create predefined_values entry (type=${JSON.stringify(payload.type)}, id=${JSON.stringify(payload.id)}, label=${JSON.stringify(payload.label)})`, { cause: error });
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
|
|
4695
4730
|
//#endregion
|
|
4696
4731
|
//#region src/services/directus/queries/resolveBackendReference.ts
|
|
4697
4732
|
async function resolveBackendReference(client, references, backend) {
|
|
@@ -4702,11 +4737,11 @@ async function resolveBackendReference(client, references, backend) {
|
|
|
4702
4737
|
created: false
|
|
4703
4738
|
};
|
|
4704
4739
|
if (!isKnownBackendType(backend)) return { created: false };
|
|
4705
|
-
const created = await client
|
|
4740
|
+
const created = await createPredefinedValue(client, {
|
|
4706
4741
|
id: backend,
|
|
4707
4742
|
label: toPascalCase(backend),
|
|
4708
4743
|
type: "backend"
|
|
4709
|
-
})
|
|
4744
|
+
});
|
|
4710
4745
|
const id = typeof created === "string" ? created : created.id;
|
|
4711
4746
|
references.backendIds.set(lookupKey, id);
|
|
4712
4747
|
return {
|
|
@@ -4715,15 +4750,56 @@ async function resolveBackendReference(client, references, backend) {
|
|
|
4715
4750
|
};
|
|
4716
4751
|
}
|
|
4717
4752
|
|
|
4753
|
+
//#endregion
|
|
4754
|
+
//#region src/services/directus/queries/resolveDataTypeReference.ts
|
|
4755
|
+
async function resolveDataTypeReference(client, references, dataType) {
|
|
4756
|
+
const { id, label } = transformTypeFrom(dataType);
|
|
4757
|
+
const lookupKey = normalizeLookupKey(id);
|
|
4758
|
+
const existingId = references.dataTypeIds.get(lookupKey);
|
|
4759
|
+
if (existingId) return {
|
|
4760
|
+
id: existingId,
|
|
4761
|
+
created: false
|
|
4762
|
+
};
|
|
4763
|
+
const created = await createPredefinedValue(client, {
|
|
4764
|
+
id,
|
|
4765
|
+
label,
|
|
4766
|
+
type: "data_type"
|
|
4767
|
+
});
|
|
4768
|
+
const createdId = typeof created === "string" ? created : created.id;
|
|
4769
|
+
references.dataTypeIds.set(lookupKey, createdId);
|
|
4770
|
+
return {
|
|
4771
|
+
id: createdId,
|
|
4772
|
+
created: true
|
|
4773
|
+
};
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4718
4776
|
//#endregion
|
|
4719
4777
|
//#region src/services/directus/utils/normalizeDirectusPath.ts
|
|
4720
4778
|
function normalizeDirectusPath(value) {
|
|
4721
4779
|
return value.replace(/\?\.\[/g, "[").replace(/\?\./g, ".");
|
|
4722
4780
|
}
|
|
4723
4781
|
|
|
4782
|
+
//#endregion
|
|
4783
|
+
//#region src/services/directus/utils/toDirectusPropertyMetadata.ts
|
|
4784
|
+
/**
|
|
4785
|
+
* Converts Atlas' property metadata to the nullable shape expected by Directus.
|
|
4786
|
+
* The data type relation is deliberately excluded: it is resolved separately as
|
|
4787
|
+
* a predefined-value id before a property is upserted.
|
|
4788
|
+
*/
|
|
4789
|
+
function toDirectusPropertyMetadata(property) {
|
|
4790
|
+
return {
|
|
4791
|
+
original_type: property.original_type ?? null,
|
|
4792
|
+
format: property.format ?? null,
|
|
4793
|
+
pattern: property.pattern ?? null,
|
|
4794
|
+
is_nullable: property.is_nullable ?? null,
|
|
4795
|
+
enum_values: property.enum_values?.length ? property.enum_values : null,
|
|
4796
|
+
description: property.description ?? null
|
|
4797
|
+
};
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4724
4800
|
//#endregion
|
|
4725
4801
|
//#region src/services/directus/queries/upsertBackendProperty.ts
|
|
4726
|
-
async function upsertBackendProperty(client, property, backendRouteId, typeId) {
|
|
4802
|
+
async function upsertBackendProperty(client, property, backendRouteId, typeId, dataTypeId) {
|
|
4727
4803
|
const path = normalizeDirectusPath(property.field);
|
|
4728
4804
|
const [existing] = await client.request(n$1("backend_properties", {
|
|
4729
4805
|
filter: {
|
|
@@ -4734,16 +4810,21 @@ async function upsertBackendProperty(client, property, backendRouteId, typeId) {
|
|
|
4734
4810
|
fields: ["id"],
|
|
4735
4811
|
limit: 1
|
|
4736
4812
|
}));
|
|
4737
|
-
|
|
4738
|
-
const created = await client.request(n$2("backend_properties", {
|
|
4813
|
+
const payload = {
|
|
4739
4814
|
backend: backendRouteId,
|
|
4740
4815
|
path: path || null,
|
|
4741
4816
|
type: typeId,
|
|
4817
|
+
data_type: dataTypeId ?? null,
|
|
4818
|
+
...toDirectusPropertyMetadata(property),
|
|
4742
4819
|
source_file: property.source_file || null,
|
|
4743
4820
|
provenance: property.provenance,
|
|
4744
|
-
comments: property.provenance === "ai" ? "Inferred with AI" : null
|
|
4745
|
-
|
|
4746
|
-
|
|
4821
|
+
comments: property.provenance === "ai" ? "Inferred with AI" : null
|
|
4822
|
+
};
|
|
4823
|
+
if (existing) {
|
|
4824
|
+
await client.request(i("backend_properties", existing.id, payload));
|
|
4825
|
+
return existing.id;
|
|
4826
|
+
}
|
|
4827
|
+
const created = await client.request(n$2("backend_properties", payload));
|
|
4747
4828
|
return typeof created === "string" ? created : created.id;
|
|
4748
4829
|
}
|
|
4749
4830
|
|
|
@@ -4754,10 +4835,12 @@ async function upsertBackendSource(client, backendRoute, backendValueId, refs) {
|
|
|
4754
4835
|
let documentId = isDocument ? refs.documentIds.get(normalizeLookupKey(backendRoute.document || "")) : void 0;
|
|
4755
4836
|
if (isDocument && !documentId && backendRoute.document) {
|
|
4756
4837
|
const type = `document_${backendRoute.backend.toLowerCase()}`;
|
|
4757
|
-
const
|
|
4838
|
+
const id = `${type}_${backendRoute.document}`.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
4839
|
+
const created = await createPredefinedValue(client, {
|
|
4840
|
+
id,
|
|
4758
4841
|
label: backendRoute.document,
|
|
4759
4842
|
type
|
|
4760
|
-
})
|
|
4843
|
+
});
|
|
4761
4844
|
documentId = typeof created === "string" ? created : created.id;
|
|
4762
4845
|
refs.documentIds.set(normalizeLookupKey(backendRoute.document), documentId);
|
|
4763
4846
|
}
|
|
@@ -4780,6 +4863,8 @@ async function upsertBackendSource(client, backendRoute, backendValueId, refs) {
|
|
|
4780
4863
|
const payload = isDocument ? {
|
|
4781
4864
|
backend: backendValueId,
|
|
4782
4865
|
resource_type: "document",
|
|
4866
|
+
method: null,
|
|
4867
|
+
route: null,
|
|
4783
4868
|
document: documentId ?? null,
|
|
4784
4869
|
source_file: backendRoute.source_file || null,
|
|
4785
4870
|
provenance: backendRoute.provenance
|
|
@@ -4788,26 +4873,29 @@ async function upsertBackendSource(client, backendRoute, backendValueId, refs) {
|
|
|
4788
4873
|
resource_type: "http",
|
|
4789
4874
|
method: backendRoute.method ?? null,
|
|
4790
4875
|
route: backendRoute.route ?? null,
|
|
4876
|
+
document: null,
|
|
4791
4877
|
source_file: backendRoute.source_file || null,
|
|
4792
4878
|
provenance: backendRoute.provenance
|
|
4793
4879
|
};
|
|
4794
|
-
const created = await client.request(n$2("backend_sources",
|
|
4880
|
+
const created = await client.request(n$2("backend_sources", {
|
|
4881
|
+
id: randomUUID(),
|
|
4882
|
+
...payload
|
|
4883
|
+
}));
|
|
4795
4884
|
return typeof created === "string" ? created : created.id;
|
|
4796
4885
|
}
|
|
4797
4886
|
|
|
4798
4887
|
//#endregion
|
|
4799
4888
|
//#region src/services/directus/queries/upsertMappingEvidence.ts
|
|
4800
4889
|
async function upsertMappingEvidence(client, evidence, params) {
|
|
4801
|
-
const [existing] = await client.request(n$1("
|
|
4890
|
+
const [existing] = await client.request(n$1("mapping_evidences", {
|
|
4802
4891
|
filter: { atlas_key: { _eq: evidence.key } },
|
|
4803
4892
|
fields: ["id"],
|
|
4804
4893
|
limit: 1
|
|
4805
4894
|
}));
|
|
4806
4895
|
const payload = {
|
|
4807
4896
|
atlas_key: evidence.key,
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
backend_property_id: params.backendPropertyId,
|
|
4897
|
+
route_property_id: params.routePropertyId ?? null,
|
|
4898
|
+
backend_property_id: params.backendPropertyId ?? null,
|
|
4811
4899
|
evidence_type: evidence.evidence_type,
|
|
4812
4900
|
status: evidence.status,
|
|
4813
4901
|
confidence_score: evidence.confidence_score,
|
|
@@ -4816,70 +4904,57 @@ async function upsertMappingEvidence(client, evidence, params) {
|
|
|
4816
4904
|
last_seen_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4817
4905
|
};
|
|
4818
4906
|
if (existing) {
|
|
4819
|
-
await client.request(i("
|
|
4907
|
+
await client.request(i("mapping_evidences", existing.id, payload));
|
|
4820
4908
|
return false;
|
|
4821
4909
|
}
|
|
4822
|
-
await client.request(n$2("
|
|
4910
|
+
await client.request(n$2("mapping_evidences", {
|
|
4911
|
+
id: randomUUID(),
|
|
4912
|
+
...payload
|
|
4913
|
+
}));
|
|
4823
4914
|
return true;
|
|
4824
4915
|
}
|
|
4825
4916
|
|
|
4826
4917
|
//#endregion
|
|
4827
|
-
//#region src/services/directus/queries/
|
|
4828
|
-
async function
|
|
4829
|
-
const
|
|
4830
|
-
const [existing] = await client.request(n$1("
|
|
4918
|
+
//#region src/services/directus/queries/upsertRouteProperty.ts
|
|
4919
|
+
async function upsertRouteProperty(client, property, routeId, type, dataTypeId) {
|
|
4920
|
+
const path = normalizeDirectusPath(property.field);
|
|
4921
|
+
const [existing] = await client.request(n$1("route_properties", {
|
|
4831
4922
|
filter: {
|
|
4832
4923
|
route_id: { _eq: routeId },
|
|
4833
|
-
path: { _eq:
|
|
4834
|
-
|
|
4924
|
+
path: { _eq: path },
|
|
4925
|
+
type: { _eq: type }
|
|
4835
4926
|
},
|
|
4836
4927
|
fields: ["id"],
|
|
4837
4928
|
limit: 1
|
|
4838
4929
|
}));
|
|
4839
4930
|
const payload = {
|
|
4840
4931
|
route_id: routeId,
|
|
4841
|
-
path
|
|
4842
|
-
|
|
4843
|
-
|
|
4932
|
+
path,
|
|
4933
|
+
type,
|
|
4934
|
+
data_type: dataTypeId ?? null,
|
|
4935
|
+
...toDirectusPropertyMetadata(property),
|
|
4844
4936
|
source_file: property.source_file || null,
|
|
4845
|
-
deprecated: false
|
|
4937
|
+
deprecated: false,
|
|
4938
|
+
is_dynamic: isArrayPath(path) || path.includes("{")
|
|
4846
4939
|
};
|
|
4847
4940
|
if (!existing) {
|
|
4848
|
-
const created = await client.request(n$2("
|
|
4941
|
+
const created = await client.request(n$2("route_properties", payload));
|
|
4849
4942
|
return typeof created === "string" ? created : created.id;
|
|
4850
4943
|
}
|
|
4851
|
-
await client.request(i("
|
|
4944
|
+
await client.request(i("route_properties", existing.id, payload));
|
|
4852
4945
|
return existing.id;
|
|
4853
4946
|
}
|
|
4854
4947
|
|
|
4948
|
+
//#endregion
|
|
4949
|
+
//#region src/services/directus/queries/upsertInputProperty.ts
|
|
4950
|
+
async function upsertInputProperty(client, property, routeId, inType, dataTypeId) {
|
|
4951
|
+
return upsertRouteProperty(client, property, routeId, inType, dataTypeId);
|
|
4952
|
+
}
|
|
4953
|
+
|
|
4855
4954
|
//#endregion
|
|
4856
4955
|
//#region src/services/directus/queries/upsertOutputProperty.ts
|
|
4857
|
-
async function upsertOutputProperty(client, property, routeId, outType) {
|
|
4858
|
-
|
|
4859
|
-
const [existing] = await client.request(n$1("route_output_properties", {
|
|
4860
|
-
filter: {
|
|
4861
|
-
route_id: { _eq: routeId },
|
|
4862
|
-
path: { _eq: field },
|
|
4863
|
-
out_type: { _eq: outType }
|
|
4864
|
-
},
|
|
4865
|
-
fields: ["id"],
|
|
4866
|
-
limit: 1
|
|
4867
|
-
}));
|
|
4868
|
-
const payload = {
|
|
4869
|
-
route_id: routeId,
|
|
4870
|
-
path: field,
|
|
4871
|
-
out_type: outType,
|
|
4872
|
-
description: property.description || null,
|
|
4873
|
-
source_file: property.source_file || null,
|
|
4874
|
-
deprecated: false,
|
|
4875
|
-
is_dynamic: field.includes("[]") || field.includes("{")
|
|
4876
|
-
};
|
|
4877
|
-
if (!existing) {
|
|
4878
|
-
const created = await client.request(n$2("route_output_properties", payload));
|
|
4879
|
-
return typeof created === "string" ? created : created.id;
|
|
4880
|
-
}
|
|
4881
|
-
await client.request(i("route_output_properties", existing.id, payload));
|
|
4882
|
-
return existing.id;
|
|
4956
|
+
async function upsertOutputProperty(client, property, routeId, outType, dataTypeId) {
|
|
4957
|
+
return upsertRouteProperty(client, property, routeId, outType, dataTypeId);
|
|
4883
4958
|
}
|
|
4884
4959
|
|
|
4885
4960
|
//#endregion
|
|
@@ -4930,7 +5005,7 @@ async function upsertRoute(client, route) {
|
|
|
4930
5005
|
function groupBackendRoutesForDirectusSync(backendRoutes) {
|
|
4931
5006
|
const groups = /* @__PURE__ */ new Map();
|
|
4932
5007
|
for (const backendRoute of backendRoutes) {
|
|
4933
|
-
const key = backendRoute.resource_type === "document" ? `${backendRoute.backend}\0document\0${backendRoute.document || ""}` : `${backendRoute.backend}\0http\0${backendRoute.method || ""}\0${backendRoute.route || ""}`;
|
|
5008
|
+
const key = backendRoute.resource_type === "document" ? `${backendRoute.route_key}\0${backendRoute.backend}\0document\0${backendRoute.document || ""}` : `${backendRoute.route_key}\0${backendRoute.backend}\0http\0${backendRoute.method || ""}\0${backendRoute.route || ""}`;
|
|
4934
5009
|
const group = groups.get(key);
|
|
4935
5010
|
if (group) group.keys.push(backendRoute.key);
|
|
4936
5011
|
else groups.set(key, {
|
|
@@ -4963,7 +5038,6 @@ function selectCatalogueForDirectusPush(catalogue, routeSelector) {
|
|
|
4963
5038
|
const backendRouteKeys = new Set(backendRoutes.map((route) => route.key));
|
|
4964
5039
|
const backendProperties = catalogue.backend_properties.filter((property) => backendRouteKeys.has(property.backend_route_key));
|
|
4965
5040
|
const apiPropertyKeys = new Set([...routeInputProperties, ...routeOutputProperties].map((property) => property.key));
|
|
4966
|
-
const backendPropertyKeys = new Set(backendProperties.map((property) => property.key));
|
|
4967
5041
|
return {
|
|
4968
5042
|
...catalogue,
|
|
4969
5043
|
routes,
|
|
@@ -4971,7 +5045,7 @@ function selectCatalogueForDirectusPush(catalogue, routeSelector) {
|
|
|
4971
5045
|
route_output_properties: routeOutputProperties,
|
|
4972
5046
|
backend_routes: backendRoutes,
|
|
4973
5047
|
backend_properties: backendProperties,
|
|
4974
|
-
mapping_evidence: catalogue.mapping_evidence.filter((evidence) =>
|
|
5048
|
+
mapping_evidence: catalogue.mapping_evidence.filter((evidence) => apiPropertyKeys.has(evidence.input_property_key || "") || apiPropertyKeys.has(evidence.output_property_key || "")),
|
|
4975
5049
|
rules: catalogue.rules.filter((rule) => routeKeys.has(rule.route_key)),
|
|
4976
5050
|
aggregations: catalogue.aggregations.filter((aggregation) => routeKeys.has(aggregation.route_key))
|
|
4977
5051
|
};
|
|
@@ -4983,13 +5057,11 @@ async function pushCatalogueToDirectus(catalogue, options) {
|
|
|
4983
5057
|
const pushedCollections = [
|
|
4984
5058
|
"predefined_values",
|
|
4985
5059
|
"routes",
|
|
4986
|
-
"
|
|
4987
|
-
"route_output_properties",
|
|
5060
|
+
"route_properties",
|
|
4988
5061
|
"backend_sources",
|
|
4989
5062
|
"backend_properties",
|
|
4990
|
-
"
|
|
4991
|
-
"
|
|
4992
|
-
"route_output_properties_backend_properties"
|
|
5063
|
+
"mapping_evidences",
|
|
5064
|
+
"route_properties_backend_properties"
|
|
4993
5065
|
];
|
|
4994
5066
|
const skippedCollections = [];
|
|
4995
5067
|
const catalogueToPush = selectCatalogueForDirectusPush(catalogue, options.routeSelector);
|
|
@@ -5055,7 +5127,13 @@ async function pushCatalogueToDirectus(catalogue, options) {
|
|
|
5055
5127
|
warnings.add(`UNKNOWN_BACKEND_PROPERTY_TYPE: ${backendProperty.direction} ${backendProperty.field}`);
|
|
5056
5128
|
continue;
|
|
5057
5129
|
}
|
|
5058
|
-
|
|
5130
|
+
let dataTypeId;
|
|
5131
|
+
if (backendProperty.data_type) {
|
|
5132
|
+
const dataTypeReference = await resolveDataTypeReference(client, refs, backendProperty.data_type);
|
|
5133
|
+
dataTypeId = dataTypeReference.id;
|
|
5134
|
+
if (dataTypeReference.created) pushedItems += 1;
|
|
5135
|
+
}
|
|
5136
|
+
const backendPropertyId = await upsertBackendProperty(client, backendProperty, backendRouteId, typeId, dataTypeId);
|
|
5059
5137
|
backendPropertyIds.set(backendProperty.key, backendPropertyId);
|
|
5060
5138
|
pushedItems += 1;
|
|
5061
5139
|
}
|
|
@@ -5067,18 +5145,18 @@ async function pushCatalogueToDirectus(catalogue, options) {
|
|
|
5067
5145
|
warnings.add(`UNKNOWN_IN_TYPE: ${property.field}`);
|
|
5068
5146
|
continue;
|
|
5069
5147
|
}
|
|
5070
|
-
const
|
|
5148
|
+
const dataTypeReference = property.data_type ? await resolveDataTypeReference(client, refs, property.data_type) : void 0;
|
|
5149
|
+
if (dataTypeReference?.created) pushedItems += 1;
|
|
5150
|
+
const inputPropertyId = await upsertInputProperty(client, property, routeId, inType, dataTypeReference?.id);
|
|
5071
5151
|
pushedItems += 1;
|
|
5072
5152
|
for (const evidence of catalogueToPush.mapping_evidence.filter((item) => item.input_property_key === property.key)) {
|
|
5073
5153
|
const backendPropertyId = backendPropertyIds.get(evidence.backend_property_key);
|
|
5074
|
-
if (backendPropertyId)
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
pushedItems += 1;
|
|
5081
|
-
}
|
|
5154
|
+
if (backendPropertyId && await ensureInputLink(client, inputPropertyId, backendPropertyId)) pushedItems += 1;
|
|
5155
|
+
await upsertMappingEvidence(client, evidence, {
|
|
5156
|
+
routePropertyId: inputPropertyId,
|
|
5157
|
+
backendPropertyId
|
|
5158
|
+
});
|
|
5159
|
+
pushedItems += 1;
|
|
5082
5160
|
}
|
|
5083
5161
|
}
|
|
5084
5162
|
const routeOutputProperties = catalogueToPush.route_output_properties.filter((property) => property.route_key === route.key);
|
|
@@ -5089,18 +5167,18 @@ async function pushCatalogueToDirectus(catalogue, options) {
|
|
|
5089
5167
|
warnings.add("UNKNOWN_OUT_TYPE: RESPONSE_BODY");
|
|
5090
5168
|
continue;
|
|
5091
5169
|
}
|
|
5092
|
-
const
|
|
5170
|
+
const dataTypeReference = property.data_type ? await resolveDataTypeReference(client, refs, property.data_type) : void 0;
|
|
5171
|
+
if (dataTypeReference?.created) pushedItems += 1;
|
|
5172
|
+
const outputPropertyId = await upsertOutputProperty(client, property, routeId, outType, dataTypeReference?.id);
|
|
5093
5173
|
pushedItems += 1;
|
|
5094
5174
|
for (const evidence of catalogueToPush.mapping_evidence.filter((item) => item.output_property_key === property.key)) {
|
|
5095
5175
|
const backendPropertyId = backendPropertyIds.get(evidence.backend_property_key);
|
|
5096
|
-
if (backendPropertyId)
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
pushedItems += 1;
|
|
5103
|
-
}
|
|
5176
|
+
if (backendPropertyId && await ensureOutputLink(client, outputPropertyId, backendPropertyId)) pushedItems += 1;
|
|
5177
|
+
await upsertMappingEvidence(client, evidence, {
|
|
5178
|
+
routePropertyId: outputPropertyId,
|
|
5179
|
+
backendPropertyId
|
|
5180
|
+
});
|
|
5181
|
+
pushedItems += 1;
|
|
5104
5182
|
}
|
|
5105
5183
|
}
|
|
5106
5184
|
}
|
|
@@ -5141,12 +5219,11 @@ function buildRouteReviewRelativePath(method, routePath) {
|
|
|
5141
5219
|
];
|
|
5142
5220
|
return path.join(resourceDir, versionDir, `${fileNameParts.join("_")}.yaml`);
|
|
5143
5221
|
}
|
|
5144
|
-
function
|
|
5145
|
-
|
|
5146
|
-
if (!match || match[1] === "CALL" && match[2] === "unknown") return;
|
|
5222
|
+
function toHttpOperation(backendRoute) {
|
|
5223
|
+
if (!backendRoute.route) return;
|
|
5147
5224
|
return {
|
|
5148
|
-
method:
|
|
5149
|
-
route:
|
|
5225
|
+
method: backendRoute.method || null,
|
|
5226
|
+
route: backendRoute.route
|
|
5150
5227
|
};
|
|
5151
5228
|
}
|
|
5152
5229
|
function buildReviewProperty(property) {
|
|
@@ -5155,6 +5232,7 @@ function buildReviewProperty(property) {
|
|
|
5155
5232
|
field: mapping.field,
|
|
5156
5233
|
document: mapping.document,
|
|
5157
5234
|
description: mapping.description,
|
|
5235
|
+
...pickPropertyMetadata(mapping),
|
|
5158
5236
|
source: mapping.source_file,
|
|
5159
5237
|
...mapping.route && (mapping.route !== "unknown" || mapping.method) ? { operation: {
|
|
5160
5238
|
method: mapping.method || null,
|
|
@@ -5195,6 +5273,7 @@ function buildReviewProperty(property) {
|
|
|
5195
5273
|
source: property.source_file,
|
|
5196
5274
|
evidence_status: property.evidence_status,
|
|
5197
5275
|
transversal: property.transversal,
|
|
5276
|
+
...pickPropertyMetadata(property),
|
|
5198
5277
|
...hasMapping ? { mapping } : {},
|
|
5199
5278
|
...suggestions?.length || unresolvedBackendCandidates?.length ? { review: {
|
|
5200
5279
|
...suggestions?.length ? { suggestions } : {},
|
|
@@ -5211,7 +5290,7 @@ function buildRouteReviewDocument(catalogue, routeKey) {
|
|
|
5211
5290
|
const datasources = backendRoutes.map((backendRoute) => ({
|
|
5212
5291
|
type: backendRoute.backend,
|
|
5213
5292
|
source: backendRoute.source_file,
|
|
5214
|
-
...
|
|
5293
|
+
...backendRoute.resource_type === "document" ? { document: backendRoute.document } : toHttpOperation(backendRoute) ? { operation: toHttpOperation(backendRoute) } : {},
|
|
5215
5294
|
...backendRoute.provenance === "ai" ? { provenance: backendRoute.provenance } : {}
|
|
5216
5295
|
}));
|
|
5217
5296
|
for (const backend of route.backends) if (!datasources.some((datasource) => datasource.type === backend) && !mappedBackendTypes.has(backend)) datasources.push({
|
|
@@ -5327,14 +5406,16 @@ async function writeCatalogueArtifacts(catalogue, outputDir, repoRoot = process.
|
|
|
5327
5406
|
};
|
|
5328
5407
|
}
|
|
5329
5408
|
function addBackendMapping(routeKey, direction, apiPropertyKey, mapping, backendRoutesByKey, backendPropertiesByKey, mappingEvidence) {
|
|
5330
|
-
const
|
|
5331
|
-
const backendRouteKey = stableKey(routeKey, mapping.backend,
|
|
5409
|
+
const backendSourceId = mapping.document || mapping.route || "";
|
|
5410
|
+
const backendRouteKey = stableKey(routeKey, mapping.backend, backendSourceId);
|
|
5332
5411
|
const backendRouteRecord = backendRoutesByKey.get(backendRouteKey) || {
|
|
5333
5412
|
key: backendRouteKey,
|
|
5334
5413
|
backend: mapping.backend,
|
|
5335
5414
|
route_key: routeKey,
|
|
5336
|
-
resource_type: "http",
|
|
5337
|
-
|
|
5415
|
+
resource_type: mapping.document ? "document" : "http",
|
|
5416
|
+
method: mapping.document ? void 0 : mapping.method || void 0,
|
|
5417
|
+
route: mapping.document ? void 0 : mapping.route || void 0,
|
|
5418
|
+
document: mapping.document || void 0,
|
|
5338
5419
|
source_file: mapping.source_file,
|
|
5339
5420
|
provenance: "code_analysis"
|
|
5340
5421
|
};
|
|
@@ -5345,6 +5426,8 @@ function addBackendMapping(routeKey, direction, apiPropertyKey, mapping, backend
|
|
|
5345
5426
|
backend_route_key: backendRouteKey,
|
|
5346
5427
|
backend: mapping.backend,
|
|
5347
5428
|
field: mapping.field,
|
|
5429
|
+
description: mapping.description,
|
|
5430
|
+
...pickPropertyMetadata(mapping),
|
|
5348
5431
|
direction,
|
|
5349
5432
|
source_file: mapping.source_file,
|
|
5350
5433
|
provenance: mapping.provenance || "code_analysis"
|
|
@@ -5368,6 +5451,7 @@ function toCatalogueBackendMapping(mapping) {
|
|
|
5368
5451
|
field: mapping.field,
|
|
5369
5452
|
document: mapping.document,
|
|
5370
5453
|
description: mapping.description,
|
|
5454
|
+
...pickPropertyMetadata(mapping),
|
|
5371
5455
|
source_file: mapping.source,
|
|
5372
5456
|
confidence: mapping.confidence,
|
|
5373
5457
|
mapper_type: mapping.mapper_type,
|
|
@@ -5376,14 +5460,25 @@ function toCatalogueBackendMapping(mapping) {
|
|
|
5376
5460
|
};
|
|
5377
5461
|
}
|
|
5378
5462
|
function addDatasourceRoute(routeKey, datasource, backendRoutesByKey) {
|
|
5379
|
-
const
|
|
5380
|
-
|
|
5381
|
-
|
|
5463
|
+
const isDocument = datasource.document !== void 0;
|
|
5464
|
+
if (!isDocument && !datasource.operation) return;
|
|
5465
|
+
const sourceId = isDocument ? datasource.document : datasource.operation?.route || "";
|
|
5466
|
+
const backendRouteKey = stableKey(routeKey, datasource.type, sourceId);
|
|
5467
|
+
backendRoutesByKey.set(backendRouteKey, isDocument ? {
|
|
5468
|
+
key: backendRouteKey,
|
|
5469
|
+
backend: datasource.type,
|
|
5470
|
+
route_key: routeKey,
|
|
5471
|
+
resource_type: "document",
|
|
5472
|
+
document: datasource.document,
|
|
5473
|
+
source_file: datasource.source,
|
|
5474
|
+
provenance: datasource.provenance || "code_analysis"
|
|
5475
|
+
} : {
|
|
5382
5476
|
key: backendRouteKey,
|
|
5383
5477
|
backend: datasource.type,
|
|
5384
5478
|
route_key: routeKey,
|
|
5385
5479
|
resource_type: "http",
|
|
5386
|
-
|
|
5480
|
+
method: datasource.operation?.method || void 0,
|
|
5481
|
+
route: datasource.operation?.route || void 0,
|
|
5387
5482
|
source_file: datasource.source,
|
|
5388
5483
|
provenance: datasource.provenance || "code_analysis"
|
|
5389
5484
|
});
|
|
@@ -5422,12 +5517,13 @@ function mergeRouteReviewDocuments(documents) {
|
|
|
5422
5517
|
field: property.field,
|
|
5423
5518
|
domain_field: property.mapping?.domain?.field,
|
|
5424
5519
|
transversal: property.transversal,
|
|
5520
|
+
...pickPropertyMetadata(property),
|
|
5425
5521
|
backend_names: [...new Set(backendMappings.map((mapping) => mapping.backend))],
|
|
5426
5522
|
backend_mappings: backendMappings,
|
|
5427
5523
|
inference_suggestions: property.review?.suggestions?.map((suggestion) => ({
|
|
5428
5524
|
backend: suggestion.type,
|
|
5429
5525
|
method: suggestion.operation?.method || null,
|
|
5430
|
-
route: suggestion.operation?.route || "
|
|
5526
|
+
route: suggestion.operation?.route || "",
|
|
5431
5527
|
field: suggestion.field,
|
|
5432
5528
|
source_file: suggestion.source,
|
|
5433
5529
|
confidence: suggestion.confidence,
|
|
@@ -5550,7 +5646,10 @@ function parseRouteSelector(value) {
|
|
|
5550
5646
|
//#endregion
|
|
5551
5647
|
//#region src/commands/push.ts
|
|
5552
5648
|
function formatPushError(error) {
|
|
5553
|
-
if (error instanceof Error)
|
|
5649
|
+
if (error instanceof Error) {
|
|
5650
|
+
const cause = isRecord$1(error) ? error.cause : void 0;
|
|
5651
|
+
return cause === void 0 ? error.message : `${error.message}; ${formatPushError(cause)}`;
|
|
5652
|
+
}
|
|
5554
5653
|
if (!isRecord$1(error)) return String(error);
|
|
5555
5654
|
const details = (Array.isArray(error.errors) ? error.errors : []).flatMap((item) => {
|
|
5556
5655
|
if (!isRecord$1(item) || typeof item.message !== "string") return [];
|
|
@@ -23166,16 +23265,20 @@ function findBackendRoute(document, suggestion) {
|
|
|
23166
23265
|
}
|
|
23167
23266
|
function ensureBackendRoute(catalogue, document, suggestion) {
|
|
23168
23267
|
const candidate = findBackendRoute(document, suggestion);
|
|
23169
|
-
const
|
|
23170
|
-
const
|
|
23268
|
+
const resolvedProp = suggestion.candidate.resolvedProperty;
|
|
23269
|
+
const isDocument = resolvedProp !== void 0 && "document" in resolvedProp;
|
|
23270
|
+
const sourceId = isDocument ? resolvedProp.document : candidate?.route || "";
|
|
23271
|
+
const key = stableKey(document.key, suggestion.candidate.backend, sourceId);
|
|
23171
23272
|
const existing = catalogue.backend_routes.find((route) => route.key === key);
|
|
23172
23273
|
if (existing) return existing;
|
|
23173
23274
|
const created = {
|
|
23174
23275
|
key,
|
|
23175
23276
|
backend: suggestion.candidate.backend,
|
|
23176
23277
|
route_key: document.key,
|
|
23177
|
-
resource_type: "http",
|
|
23178
|
-
|
|
23278
|
+
resource_type: isDocument ? "document" : "http",
|
|
23279
|
+
method: isDocument ? void 0 : candidate?.method || void 0,
|
|
23280
|
+
route: isDocument ? void 0 : candidate?.route || void 0,
|
|
23281
|
+
document: isDocument ? resolvedProp.document : void 0,
|
|
23179
23282
|
source_file: candidate?.sourceFile || suggestion.candidate.sourceFile,
|
|
23180
23283
|
provenance: "ai"
|
|
23181
23284
|
};
|
|
@@ -23207,20 +23310,28 @@ function applySuggestion(catalogue, document, property, suggestion) {
|
|
|
23207
23310
|
const backendRouteCandidate = findBackendRoute(document, suggestion);
|
|
23208
23311
|
const backendRoute = ensureBackendRoute(catalogue, document, suggestion);
|
|
23209
23312
|
const backendPropertyKey = stableKey(backendRoute.key, property.direction, suggestion.candidate.backendField);
|
|
23313
|
+
const resolvedProp = suggestion.candidate.resolvedProperty;
|
|
23314
|
+
const resolvedDocument = resolvedProp && "document" in resolvedProp ? resolvedProp.document : void 0;
|
|
23210
23315
|
if (!catalogue.backend_properties.some((item) => item.key === backendPropertyKey)) catalogue.backend_properties.push({
|
|
23211
23316
|
key: backendPropertyKey,
|
|
23212
23317
|
backend_route_key: backendRoute.key,
|
|
23213
23318
|
backend: suggestion.candidate.backend,
|
|
23214
23319
|
field: suggestion.candidate.backendField,
|
|
23320
|
+
description: resolvedProp?.description,
|
|
23321
|
+
...pickPropertyMetadata(resolvedProp),
|
|
23215
23322
|
direction: property.direction,
|
|
23216
23323
|
source_file: candidateSource(suggestion.candidate),
|
|
23217
23324
|
provenance: "ai"
|
|
23218
23325
|
});
|
|
23219
23326
|
if (!property.backend_mappings.some((mapping) => mapping.backend === suggestion.candidate.backend && mapping.field === suggestion.candidate.backendField)) property.backend_mappings.push({
|
|
23220
23327
|
backend: suggestion.candidate.backend,
|
|
23221
|
-
|
|
23222
|
-
|
|
23328
|
+
...resolvedDocument ? { document: resolvedDocument } : {
|
|
23329
|
+
method: backendRouteCandidate?.method || null,
|
|
23330
|
+
route: backendRouteCandidate?.route || ""
|
|
23331
|
+
},
|
|
23223
23332
|
field: suggestion.candidate.backendField,
|
|
23333
|
+
description: resolvedProp?.description,
|
|
23334
|
+
...pickPropertyMetadata(resolvedProp),
|
|
23224
23335
|
source_file: candidateSource(suggestion.candidate),
|
|
23225
23336
|
confidence: suggestion.confidence,
|
|
23226
23337
|
mapper_type: suggestion.candidate.mapperType,
|
|
@@ -23247,7 +23358,7 @@ function recordReviewSuggestion(document, property, suggestion) {
|
|
|
23247
23358
|
property.inference_suggestions.push({
|
|
23248
23359
|
backend: suggestion.candidate.backend,
|
|
23249
23360
|
method: backendRouteCandidate?.method || null,
|
|
23250
|
-
route: backendRouteCandidate?.route || "
|
|
23361
|
+
route: backendRouteCandidate?.route || "",
|
|
23251
23362
|
field: suggestion.candidate.backendField,
|
|
23252
23363
|
source_file: candidateSource(suggestion.candidate),
|
|
23253
23364
|
confidence: suggestion.confidence,
|
|
@@ -23379,11 +23490,13 @@ async function inferCatalogueDirectory(params) {
|
|
|
23379
23490
|
input: catalogue.route_input_properties.filter((property) => property.route_key === routeKey).map((property) => ({
|
|
23380
23491
|
path: property.field,
|
|
23381
23492
|
description: property.description,
|
|
23493
|
+
type: property.data_type,
|
|
23382
23494
|
location: "body"
|
|
23383
23495
|
})),
|
|
23384
23496
|
output: catalogue.route_output_properties.filter((property) => property.route_key === routeKey).map((property) => ({
|
|
23385
23497
|
path: property.field,
|
|
23386
23498
|
description: property.description,
|
|
23499
|
+
type: property.data_type,
|
|
23387
23500
|
location: "body"
|
|
23388
23501
|
}))
|
|
23389
23502
|
}]]);
|