@uipath/maestro-builder-sdk 6.4.0 → 6.5.1
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/bpmn/uipath-moddle.v1.json +21 -0
- package/dist/cli/commands/registry.js +68 -12
- package/dist/registry/archive/entry-policy.d.ts +36 -0
- package/dist/registry/archive/entry-policy.js +60 -0
- package/dist/registry/archive/extract.d.ts +31 -0
- package/dist/registry/archive/extract.js +92 -0
- package/dist/registry/archive/zip-reader.d.ts +38 -0
- package/dist/registry/archive/zip-reader.js +256 -0
- package/dist/registry/codecs/pyjson.d.ts +62 -0
- package/dist/registry/codecs/pyjson.js +208 -0
- package/dist/registry/compat/compare.d.ts +18 -0
- package/dist/registry/compat/compare.js +32 -0
- package/dist/registry/compat/paths.d.ts +4 -0
- package/dist/registry/compat/paths.js +17 -0
- package/dist/registry/compat/pystr.d.ts +50 -0
- package/dist/registry/compat/pystr.js +221 -0
- package/dist/registry/concurrency.d.ts +10 -0
- package/dist/registry/concurrency.js +34 -0
- package/dist/registry/curated-overlay.d.ts +36 -4
- package/dist/registry/curated-overlay.js +87 -14
- package/dist/registry/errors.d.ts +26 -0
- package/dist/registry/errors.js +38 -0
- package/dist/registry/extractor.d.ts +9 -10
- package/dist/registry/extractor.js +5 -15
- package/dist/registry/files.d.ts +26 -0
- package/dist/registry/files.js +160 -0
- package/dist/registry/generators/descriptors.d.ts +81 -0
- package/dist/registry/generators/descriptors.js +405 -0
- package/dist/registry/generators/fields.d.ts +46 -0
- package/dist/registry/generators/fields.js +111 -0
- package/dist/registry/generators/markdown/common.d.ts +21 -0
- package/dist/registry/generators/markdown/common.js +55 -0
- package/dist/registry/generators/markdown/index.d.ts +33 -0
- package/dist/registry/generators/markdown/index.js +37 -0
- package/dist/registry/generators/markdown/page.d.ts +8 -0
- package/dist/registry/generators/markdown/page.js +52 -0
- package/dist/registry/generators/markdown/pyvalue.d.ts +34 -0
- package/dist/registry/generators/markdown/pyvalue.js +106 -0
- package/dist/registry/generators/markdown/sections/choosing-object.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/choosing-object.js +52 -0
- package/dist/registry/generators/markdown/sections/example.d.ts +22 -0
- package/dist/registry/generators/markdown/sections/example.js +295 -0
- package/dist/registry/generators/markdown/sections/filtering.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/filtering.js +76 -0
- package/dist/registry/generators/markdown/sections/header.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/header.js +37 -0
- package/dist/registry/generators/markdown/sections/inputs.d.ts +30 -0
- package/dist/registry/generators/markdown/sections/inputs.js +151 -0
- package/dist/registry/generators/markdown/sections/lookups.d.ts +12 -0
- package/dist/registry/generators/markdown/sections/lookups.js +150 -0
- package/dist/registry/generators/markdown/sections/outputs.d.ts +3 -0
- package/dist/registry/generators/markdown/sections/outputs.js +9 -0
- package/dist/registry/generators/markdown/sections/resolving-fields.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/resolving-fields.js +139 -0
- package/dist/registry/generators/markdown/sections/schema-dynamic.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/schema-dynamic.js +86 -0
- package/dist/registry/generators/materialize.d.ts +30 -0
- package/dist/registry/generators/materialize.js +132 -0
- package/dist/registry/generators/md-symbols.d.ts +22 -0
- package/dist/registry/generators/md-symbols.js +58 -0
- package/dist/registry/generators/triggers.d.ts +15 -0
- package/dist/registry/generators/triggers.js +85 -0
- package/dist/registry/generators/type-registry.d.ts +50 -0
- package/dist/registry/generators/type-registry.js +154 -0
- package/dist/registry/generators/type-tree.d.ts +65 -0
- package/dist/registry/generators/type-tree.js +179 -0
- package/dist/registry/library-build/build.d.ts +57 -0
- package/dist/registry/library-build/build.js +286 -0
- package/dist/registry/library-build/canonical.d.ts +119 -0
- package/dist/registry/library-build/canonical.js +512 -0
- package/dist/registry/library-build/cli.d.ts +45 -0
- package/dist/registry/library-build/cli.js +182 -0
- package/dist/registry/library-build/context.d.ts +107 -0
- package/dist/registry/library-build/context.js +267 -0
- package/dist/registry/library-build/enrich.d.ts +36 -0
- package/dist/registry/library-build/enrich.js +158 -0
- package/dist/registry/library-build/events.d.ts +108 -0
- package/dist/registry/library-build/events.js +476 -0
- package/dist/registry/library-build/generic-expand.d.ts +77 -0
- package/dist/registry/library-build/generic-expand.js +363 -0
- package/dist/registry/library-build/plan.d.ts +71 -0
- package/dist/registry/library-build/plan.js +270 -0
- package/dist/registry/library-build/py.d.ts +45 -0
- package/dist/registry/library-build/py.js +167 -0
- package/dist/registry/library-build/schema-action.d.ts +38 -0
- package/dist/registry/library-build/schema-action.js +107 -0
- package/dist/registry/library-build/write.d.ts +6 -0
- package/dist/registry/library-build/write.js +26 -0
- package/dist/registry/library-reader.d.ts +20 -0
- package/dist/registry/library-reader.js +50 -0
- package/dist/registry/lookup-specs.d.ts +55 -0
- package/dist/registry/lookup-specs.js +140 -0
- package/dist/registry/materialize-cli.js +28 -14
- package/dist/registry/materializer.d.ts +25 -3
- package/dist/registry/materializer.js +45 -29
- package/dist/registry/model/library.d.ts +254 -0
- package/dist/registry/model/library.js +23 -0
- package/dist/registry/naming.d.ts +54 -0
- package/dist/registry/naming.js +142 -0
- package/dist/registry/orphans.d.ts +4 -0
- package/dist/registry/orphans.js +86 -0
- package/dist/registry/prepare/actions.d.ts +26 -0
- package/dist/registry/prepare/actions.js +94 -0
- package/dist/registry/prepare/connections.d.ts +181 -0
- package/dist/registry/prepare/connections.js +399 -0
- package/dist/registry/prepare/event.d.ts +96 -0
- package/dist/registry/prepare/event.js +268 -0
- package/dist/registry/prepare/handoff.d.ts +21 -0
- package/dist/registry/prepare/handoff.js +91 -0
- package/dist/registry/prepare/ledger.d.ts +104 -0
- package/dist/registry/prepare/ledger.js +216 -0
- package/dist/registry/prepare/messages.d.ts +190 -0
- package/dist/registry/prepare/messages.js +472 -0
- package/dist/registry/prepare/objects.d.ts +130 -0
- package/dist/registry/prepare/objects.js +318 -0
- package/dist/registry/prepare/overlay.d.ts +149 -0
- package/dist/registry/prepare/overlay.js +487 -0
- package/dist/registry/prepare/parents.d.ts +41 -0
- package/dist/registry/prepare/parents.js +122 -0
- package/dist/registry/prepare/pipeline.d.ts +91 -0
- package/dist/registry/prepare/pipeline.js +376 -0
- package/dist/registry/prepare/regenerate.d.ts +9 -0
- package/dist/registry/prepare/regenerate.js +50 -0
- package/dist/registry/prepare/resolve.d.ts +199 -0
- package/dist/registry/prepare/resolve.js +470 -0
- package/dist/registry/prepare/retry.d.ts +83 -0
- package/dist/registry/prepare/retry.js +109 -0
- package/dist/registry/prepare/source-import.d.ts +54 -0
- package/dist/registry/prepare/source-import.js +192 -0
- package/dist/registry/prepare/support.d.ts +41 -0
- package/dist/registry/prepare/support.js +178 -0
- package/dist/registry/prepare-cli.d.ts +16 -5
- package/dist/registry/prepare-cli.js +60 -53
- package/dist/registry/pull-cli.js +8 -7
- package/dist/registry/reporter.d.ts +26 -0
- package/dist/registry/reporter.js +41 -0
- package/dist/registry/uip/client.d.ts +99 -0
- package/dist/registry/uip/client.js +226 -0
- package/dist/registry/uip/commands.d.ts +40 -0
- package/dist/registry/uip/commands.js +80 -0
- package/dist/registry/uip/envelope.d.ts +37 -0
- package/dist/registry/uip/envelope.js +84 -0
- package/dist/registry/uip/response-cache.d.ts +28 -0
- package/dist/registry/uip/response-cache.js +57 -0
- package/lib/README.md +10 -8
- package/package.json +3 -3
- package/dist/generators/_connections.py +0 -331
- package/dist/generators/_events.py +0 -355
- package/dist/generators/_lookups.py +0 -114
- package/dist/generators/_naming.py +0 -185
- package/dist/generators/_objects.py +0 -299
- package/dist/generators/_resolve.py +0 -319
- package/dist/generators/convert_library_to_md.py +0 -1441
- package/dist/generators/extract_library.py +0 -125
- package/dist/generators/generate_connectors_ts.py +0 -936
- package/dist/generators/generate_library_json.py +0 -2527
- package/dist/generators/generate_triggers_ts.py +0 -110
- package/dist/generators/materialize_registry.py +0 -155
- package/dist/generators/prepare_connector.py +0 -1860
- package/dist/registry/python.d.ts +0 -26
- package/dist/registry/python.js +0 -46
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `main()` of `generate_library_json.py`, as a function of its options and
|
|
3
|
+
* ports: search → scope → trigger side-file → fetch → extract → enrich →
|
|
4
|
+
* connector records → generic expansion → events → curated overrides → plan →
|
|
5
|
+
* write.
|
|
6
|
+
*
|
|
7
|
+
* Every remote call goes through the {@link BuildContext} built from the ports,
|
|
8
|
+
* so a build against a `--keep-temp` cache the Python left behind makes no call
|
|
9
|
+
* at all — which is how the port is proven byte-for-byte. The two `sys.exit(
|
|
10
|
+
* "<message>")` gates are thrown as {@link Refusal}s carrying the same text.
|
|
11
|
+
*/
|
|
12
|
+
import { dirname, join, normalize } from "node:path";
|
|
13
|
+
import { sortedStrings } from "../compat/compare.js";
|
|
14
|
+
import { pyStr } from "../compat/pystr.js";
|
|
15
|
+
import { mapConcurrent } from "../concurrency.js";
|
|
16
|
+
import { Refusal, messageOf } from "../errors.js";
|
|
17
|
+
import { registrySearchConnectors } from "../uip/commands.js";
|
|
18
|
+
import { applyCuratedOverrides, extractCanonical, filterNodeTypesByTier, mergeConnectorRecord, nodeOf, scopedConnectorKey, selectPublishedConnectors, } from "./canonical.js";
|
|
19
|
+
import { SEARCH_RESULTS_NAME, createBuildContext, isConnectorGet, registryCacheName, registryGet, } from "./context.js";
|
|
20
|
+
import { enrichAll } from "./enrich.js";
|
|
21
|
+
import { resolveConnectorEvents } from "./events.js";
|
|
22
|
+
import { expandAllGenerics, sortExpandedEntries } from "./generic-expand.js";
|
|
23
|
+
import { orphanCheck, planLibrary, triggerRows } from "./plan.js";
|
|
24
|
+
import { get, item, pyIter, pyOr, pyReprStrList, truthy } from "./py.js";
|
|
25
|
+
import { writePlan, writeTriggerSideFile } from "./write.js";
|
|
26
|
+
/** The Python's default: beside the output directory. */
|
|
27
|
+
export function defaultTriggersOutput(outputDir) {
|
|
28
|
+
return join(dirname(normalize(outputDir)) || ".", "registry-triggers.json");
|
|
29
|
+
}
|
|
30
|
+
/** `{c.strip() for c in text.split(",") if c.strip()}`, in first-seen order. */
|
|
31
|
+
export function parseConnectorsFlag(text) {
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
for (const part of text.split(",")) {
|
|
34
|
+
const key = part.trim();
|
|
35
|
+
if (key)
|
|
36
|
+
seen.add(key);
|
|
37
|
+
}
|
|
38
|
+
return [...seen];
|
|
39
|
+
}
|
|
40
|
+
/** `", ".join(missing[:10])` plus ` (+N more)` past ten. */
|
|
41
|
+
function missingPreview(missing) {
|
|
42
|
+
const preview = missing.slice(0, 10).join(", ");
|
|
43
|
+
const remainder = missing.length > 10 ? ` (+${missing.length - 10} more)` : "";
|
|
44
|
+
return `${preview}${remainder}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `registry_search`: the connector node types the registry lists, from the
|
|
48
|
+
* cached raw stdout of `flow registry search --filter tags:in=connector` —
|
|
49
|
+
* fetched once when the cache has no `_search_results.json`.
|
|
50
|
+
*/
|
|
51
|
+
export async function registrySearch(ctx) {
|
|
52
|
+
if (!ctx.caches.registry.has(SEARCH_RESULTS_NAME)) {
|
|
53
|
+
ctx.reporter.info("Running registry search...");
|
|
54
|
+
const result = await ctx.client.run(registrySearchConnectors(), ctx.timeoutMs === undefined ? undefined : { timeoutMs: ctx.timeoutMs });
|
|
55
|
+
if (result.code !== 0)
|
|
56
|
+
throw new Refusal(`Registry search failed: ${result.stderr}`, "REGISTRY_SEARCH_FAILED");
|
|
57
|
+
ctx.caches.registry.write(SEARCH_RESULTS_NAME, undefined, result.stdout);
|
|
58
|
+
}
|
|
59
|
+
const data = ctx.caches.registry.read(SEARCH_RESULTS_NAME);
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const entry of pyIter(get(data, "Data", []))) {
|
|
62
|
+
const nodeType = item(entry, "NodeType");
|
|
63
|
+
if (typeof nodeType === "string" && nodeType.startsWith("uipath.connector."))
|
|
64
|
+
out.push(nodeType);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `fetch_all`: the registry response of every node type, from the cache or
|
|
70
|
+
* fetched in parallel. `nodeType → cache name`; a node type whose fetch failed
|
|
71
|
+
* is absent (and was reported by `registryGet`).
|
|
72
|
+
*/
|
|
73
|
+
export async function fetchAll(ctx, nodeTypes) {
|
|
74
|
+
const results = new Map();
|
|
75
|
+
const toFetch = [];
|
|
76
|
+
let alreadyCached = 0;
|
|
77
|
+
for (const nt of nodeTypes) {
|
|
78
|
+
const name = registryCacheName(nt);
|
|
79
|
+
if (ctx.caches.registry.has(name)) {
|
|
80
|
+
results.set(nt, name);
|
|
81
|
+
alreadyCached += 1;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
toFetch.push(nt);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (alreadyCached)
|
|
88
|
+
ctx.reporter.info(` ${alreadyCached} connectors already cached, ${toFetch.length} to fetch`);
|
|
89
|
+
if (toFetch.length > 0) {
|
|
90
|
+
let done = 0;
|
|
91
|
+
const names = await mapConcurrent(toFetch, ctx.concurrency, async (nt) => {
|
|
92
|
+
const name = await registryGet(ctx, nt);
|
|
93
|
+
done += 1;
|
|
94
|
+
if (done % 50 === 0 || done === toFetch.length)
|
|
95
|
+
ctx.reporter.info(` Fetched ${done}/${toFetch.length}`);
|
|
96
|
+
return name;
|
|
97
|
+
});
|
|
98
|
+
toFetch.forEach((nt, i) => {
|
|
99
|
+
const name = names[i];
|
|
100
|
+
if (name)
|
|
101
|
+
results.set(nt, name);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return results;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* `fetch_connector_records_for_keys`: one `is connectors metadata` per key,
|
|
108
|
+
* sorted and deduplicated; `key → record`, `null` where the lookup failed.
|
|
109
|
+
*/
|
|
110
|
+
export async function fetchConnectorRecordsForKeys(ctx, keys) {
|
|
111
|
+
const sorted = sortedStrings(new Set([...keys].filter((key) => truthy(key))));
|
|
112
|
+
ctx.reporter.info(` Looking up ${sorted.length} connector records...`);
|
|
113
|
+
let done = 0;
|
|
114
|
+
const records = await mapConcurrent(sorted, ctx.concurrency, async (key) => {
|
|
115
|
+
let record;
|
|
116
|
+
try {
|
|
117
|
+
record = await isConnectorGet(ctx, key);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
record = undefined;
|
|
121
|
+
}
|
|
122
|
+
done += 1;
|
|
123
|
+
if (done % 50 === 0 || done === sorted.length)
|
|
124
|
+
ctx.reporter.info(` Fetched ${done}/${sorted.length} connector records`);
|
|
125
|
+
return record ?? null;
|
|
126
|
+
});
|
|
127
|
+
return new Map(sorted.map((key, i) => [key, records[i]]));
|
|
128
|
+
}
|
|
129
|
+
/** `fetch_connector_records`: one record per unique connector key in `entries`. */
|
|
130
|
+
export function fetchConnectorRecords(ctx, entries) {
|
|
131
|
+
const keys = entries.map((e) => item(item(e, "connector"), "key")).filter((key) => truthy(key));
|
|
132
|
+
return fetchConnectorRecordsForKeys(ctx, keys);
|
|
133
|
+
}
|
|
134
|
+
/** The whole generator, `main()` minus argument parsing and cache cleanup. */
|
|
135
|
+
export async function buildLibrary(options, ports) {
|
|
136
|
+
const ctx = createBuildContext(ports);
|
|
137
|
+
const info = (line) => ctx.reporter.info(line);
|
|
138
|
+
const warn = (line) => ctx.reporter.warn(line);
|
|
139
|
+
const concurrency = ctx.concurrency;
|
|
140
|
+
let nodeTypes = await registrySearch(ctx);
|
|
141
|
+
info(`Found ${nodeTypes.length} connector node types`);
|
|
142
|
+
let connectorRecords;
|
|
143
|
+
if (options.connectors !== undefined) {
|
|
144
|
+
// Curated subset: the requested connectors' action AND connector-event
|
|
145
|
+
// node types. The START form stays out — `registry get` refuses it
|
|
146
|
+
// without a --connection-id.
|
|
147
|
+
const allow = new Set(options.connectors);
|
|
148
|
+
const before = nodeTypes.length;
|
|
149
|
+
nodeTypes = nodeTypes.filter((nt) => {
|
|
150
|
+
const key = scopedConnectorKey(nt);
|
|
151
|
+
return key !== null && allow.has(key);
|
|
152
|
+
});
|
|
153
|
+
const matched = new Set([...allow].filter((key) => nodeTypes.some((nt) => `${nt}.`.includes(`.${key}.`))));
|
|
154
|
+
info(`Curated subset: kept ${nodeTypes.length}/${before} node types for ${matched.size}/${allow.size} connectors ` +
|
|
155
|
+
pyReprStrList(sortedStrings(matched)));
|
|
156
|
+
const missing = [...allow].filter((key) => !matched.has(key));
|
|
157
|
+
if (missing.length > 0) {
|
|
158
|
+
warn(` WARN: no registry nodes matched these connector keys: ${pyReprStrList(sortedStrings(missing))}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// A full build ships the PUBLISHED catalog, not everything the build
|
|
163
|
+
// tenant happens to see.
|
|
164
|
+
const before = nodeTypes.length;
|
|
165
|
+
const [kept, dropped] = selectPublishedConnectors(nodeTypes);
|
|
166
|
+
nodeTypes = kept;
|
|
167
|
+
if (dropped.length > 0) {
|
|
168
|
+
info(`Published catalog: kept ${nodeTypes.length}/${before} node types, dropped ${dropped.length} ` +
|
|
169
|
+
`tenant-local connector(s) ${pyReprStrList(dropped)}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const catalogScope = options.catalogScope ?? "all";
|
|
173
|
+
if (catalogScope === "tier1" || catalogScope === "tier2") {
|
|
174
|
+
const tierNumber = catalogScope.slice(-1);
|
|
175
|
+
const scopeKeys = new Set(nodeTypes.map((nt) => scopedConnectorKey(nt)).filter((key) => Boolean(key)));
|
|
176
|
+
info(`Resolving Tier ${tierNumber} scope from metadata for ${scopeKeys.size} connector keys...`);
|
|
177
|
+
connectorRecords = await fetchConnectorRecordsForKeys(ctx, scopeKeys);
|
|
178
|
+
const missingMetadata = sortedStrings([...connectorRecords].filter(([, record]) => record === null).map(([key]) => key));
|
|
179
|
+
if (missingMetadata.length > 0) {
|
|
180
|
+
throw new Refusal(`Tier ${tierNumber} filtering requires connector metadata for every candidate connector, but lookup ` +
|
|
181
|
+
`failed for: ${missingPreview(missingMetadata)}`, "TIER_METADATA_MISSING");
|
|
182
|
+
}
|
|
183
|
+
const before = nodeTypes.length;
|
|
184
|
+
const [kept, matchingKeys] = filterNodeTypesByTier(nodeTypes, connectorRecords, catalogScope);
|
|
185
|
+
nodeTypes = kept;
|
|
186
|
+
if (matchingKeys.size === 0) {
|
|
187
|
+
throw new Refusal(`Tier ${tierNumber} filtering selected no connectors. Expected the Tier field from ` +
|
|
188
|
+
`\`uip is connectors metadata\` to contain '${tierNumber}'.`, "TIER_EMPTY");
|
|
189
|
+
}
|
|
190
|
+
info(`Tier ${tierNumber} scope: kept ${nodeTypes.length}/${before} action node types for ${matchingKeys.size} connectors`);
|
|
191
|
+
}
|
|
192
|
+
// Side-file: every trigger nodeType the registry search exposed.
|
|
193
|
+
const triggersOutput = options.triggersOutput || defaultTriggersOutput(options.outputDir);
|
|
194
|
+
info(`Writing trigger side-file → ${triggersOutput}`);
|
|
195
|
+
let triggerCount = 0;
|
|
196
|
+
if (!ctx.caches.registry.has(SEARCH_RESULTS_NAME)) {
|
|
197
|
+
warn(` WARN: search cache missing at ${SEARCH_RESULTS_NAME}; can't write triggers side-file`);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const rows = triggerRows(ctx.caches.registry.read(SEARCH_RESULTS_NAME));
|
|
201
|
+
triggerCount = writeTriggerSideFile(rows, triggersOutput);
|
|
202
|
+
info(` wrote ${triggerCount} triggers to ${triggersOutput}`);
|
|
203
|
+
}
|
|
204
|
+
info(`Fetching connector details (concurrency=${concurrency})...`);
|
|
205
|
+
const cacheFiles = await fetchAll(ctx, nodeTypes);
|
|
206
|
+
info(`Successfully fetched ${cacheFiles.size} connectors`);
|
|
207
|
+
info("Extracting connector entries (Curated + Generic)...");
|
|
208
|
+
let entries = [];
|
|
209
|
+
const v1defSources = new Map();
|
|
210
|
+
const byActivity = new Map();
|
|
211
|
+
for (const nt of sortedStrings(cacheFiles.keys())) {
|
|
212
|
+
const name = cacheFiles.get(nt);
|
|
213
|
+
try {
|
|
214
|
+
const entry = extractCanonical(nodeOf(ctx.caches.registry.read(name)));
|
|
215
|
+
if (truthy(entry)) {
|
|
216
|
+
entries.push(entry);
|
|
217
|
+
v1defSources.set(item(entry, "nodeType"), name);
|
|
218
|
+
// `entry["operation"].get("activityType", "") or "(empty)"`, printed
|
|
219
|
+
// with `str()`: a `True` stays `True`, not `true`, in the count line.
|
|
220
|
+
const at = pyStr(pyOr(get(item(entry, "operation"), "activityType", ""), "(empty)"));
|
|
221
|
+
byActivity.set(at, (byActivity.get(at) ?? 0) + 1);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
warn(` WARN: error processing ${nt}: ${messageOf(e)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
info(`Found ${entries.length} entries total: ` +
|
|
229
|
+
sortedStrings(byActivity.keys())
|
|
230
|
+
.map((k) => `${k}=${byActivity.get(k)}`)
|
|
231
|
+
.join(", "));
|
|
232
|
+
if (!options.skipEnrichment) {
|
|
233
|
+
info(`Enriching via \`is resources describe\` (concurrency=${concurrency})...`);
|
|
234
|
+
entries = await enrichAll(ctx, entries);
|
|
235
|
+
}
|
|
236
|
+
if (!options.skipConnectorEnrichment) {
|
|
237
|
+
info(`Enriching via \`is connectors metadata\` (concurrency=${concurrency})...`);
|
|
238
|
+
if (connectorRecords === undefined)
|
|
239
|
+
connectorRecords = await fetchConnectorRecords(ctx, entries);
|
|
240
|
+
const missingMetadata = sortedStrings([...connectorRecords].filter(([, record]) => record === null).map(([key]) => key));
|
|
241
|
+
if (missingMetadata.length > 0) {
|
|
242
|
+
throw new Refusal("Connector metadata is required to classify schema discovery, but `uip is connectors metadata` " +
|
|
243
|
+
`failed for: ${missingPreview(missingMetadata)}. Upgrade the UiPath CLI or rerun after checking authentication.`, "CONNECTOR_METADATA_MISSING");
|
|
244
|
+
}
|
|
245
|
+
let named = 0;
|
|
246
|
+
for (const e of entries) {
|
|
247
|
+
const key = item(item(e, "connector"), "key");
|
|
248
|
+
mergeConnectorRecord(e, connectorRecords.get(key) ?? null);
|
|
249
|
+
if (truthy(get(item(e, "connector"), "name")))
|
|
250
|
+
named += 1;
|
|
251
|
+
}
|
|
252
|
+
const schemaDynamic = entries.filter((e) => truthy(get(item(e, "runtime"), "requiresConnectionForSchema"))).length;
|
|
253
|
+
info(` Named ${named}/${entries.length} entries from connector records`);
|
|
254
|
+
info(` schema-dynamic from connector capabilities: ${schemaDynamic}/${entries.length}`);
|
|
255
|
+
}
|
|
256
|
+
if (!options.skipGenericExpansion) {
|
|
257
|
+
info(`Expanding Generic CRUD by (object, operation) (concurrency=${concurrency})...`);
|
|
258
|
+
const [kept, expanded] = await expandAllGenerics(ctx, entries);
|
|
259
|
+
// DELIBERATE FIX: the Python appended expansions in thread-completion
|
|
260
|
+
// order; sorted, a build is a function of its inputs (see
|
|
261
|
+
// `sortExpandedEntries`).
|
|
262
|
+
entries = [...kept, ...sortExpandedEntries(expanded)];
|
|
263
|
+
}
|
|
264
|
+
info(`Resolving connector events (concurrency=${concurrency})...`);
|
|
265
|
+
const [described, expandedEvents] = await resolveConnectorEvents(ctx, entries);
|
|
266
|
+
entries = [...described, ...sortExpandedEntries(expandedEvents)];
|
|
267
|
+
// Curated op remaps — applied last so they override anything enrichment or
|
|
268
|
+
// expansion produced.
|
|
269
|
+
const overridden = applyCuratedOverrides(entries);
|
|
270
|
+
if (overridden)
|
|
271
|
+
info(` Applied ${overridden} curated op override(s)`);
|
|
272
|
+
info("Writing canonical library...");
|
|
273
|
+
const loadNode = (nodeType) => {
|
|
274
|
+
const name = v1defSources.get(nodeType);
|
|
275
|
+
return name ? nodeOf(ctx.caches.registry.read(name)) : undefined;
|
|
276
|
+
};
|
|
277
|
+
const plan = planLibrary(entries, loadNode);
|
|
278
|
+
for (const line of plan.warnings)
|
|
279
|
+
warn(line);
|
|
280
|
+
const orphans = orphanCheck(plan.files, plan.index);
|
|
281
|
+
if (orphans.length > 0)
|
|
282
|
+
warn(` WARN: ${orphans.length} entry file(s) have no index row: ${orphans.slice(0, 5).join(", ")}`);
|
|
283
|
+
const written = writePlan(plan, options.outputDir);
|
|
284
|
+
info(`Wrote ${written} library entries + index.json`);
|
|
285
|
+
return { nodeTypes, entries, plan, written, triggersOutput, triggerCount };
|
|
286
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { LibraryEntry } from "../model/library.js";
|
|
2
|
+
import { type Dict } from "./py.js";
|
|
3
|
+
export declare const SCHEMA_VERSION = "1";
|
|
4
|
+
/**
|
|
5
|
+
* Ops the IS CLI exposes as a POST whose inputs are query-string params with a
|
|
6
|
+
* required (often empty) body. A dispatcher reads
|
|
7
|
+
* `operation.dispatchStyle == "query-post"` and dispatches
|
|
8
|
+
* `run create <obj> --query <inputs> --body '{}'` instead of the default
|
|
9
|
+
* create→--body. The registry does not expose per-parameter location, so this
|
|
10
|
+
* is a small explicit list rather than derived.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CURATED_DISPATCH_STYLE: ReadonlyMap<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* Per-parameter value-grammar tags. A dispatcher validates the COMPUTED input
|
|
15
|
+
* against `operation.paramGrammars` at every dispatch boundary. "sql-where":
|
|
16
|
+
* Data Service query expressions (RHS string literals must be single-quoted).
|
|
17
|
+
*/
|
|
18
|
+
export declare const CURATED_PARAM_GRAMMARS: ReadonlyMap<string, Dict>;
|
|
19
|
+
/**
|
|
20
|
+
* A few connector ops the registry enumerates only in a form `uip is resources
|
|
21
|
+
* run` can't dispatch. The Outlook reply op is enumerated as the MULTIPART
|
|
22
|
+
* `ReplyToEmailV2`; the connector also exposes the non-multipart sibling
|
|
23
|
+
* `ReplyToEmail` that Flow v1 uses. Keyed by (connectorKey, registry
|
|
24
|
+
* objectName); deep-merged into `operation` AFTER enrichment so it wins over
|
|
25
|
+
* the `is resources describe` params.
|
|
26
|
+
*/
|
|
27
|
+
export declare const CURATED_OP_OVERRIDE: ReadonlyMap<string, Record<string, Dict>>;
|
|
28
|
+
/** The curated tables `extractCanonical` consults; tests can hand in their own. */
|
|
29
|
+
export interface CanonicalContext {
|
|
30
|
+
schemaVersion?: string;
|
|
31
|
+
dispatchStyles?: ReadonlyMap<string, string>;
|
|
32
|
+
paramGrammars?: ReadonlyMap<string, Dict>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* `apply_curated_overrides`: deep-merge CURATED_OP_OVERRIDE into matching
|
|
36
|
+
* entries, AFTER enrichment, so the curated shape wins over the registry-
|
|
37
|
+
* described one. Matches on (connectorKey, objectName) using the entry's
|
|
38
|
+
* current (registry) objectName. Returns how many entries were touched.
|
|
39
|
+
*/
|
|
40
|
+
export declare function applyCuratedOverrides(entries: LibraryEntry[], overrides?: ReadonlyMap<string, Record<string, Dict>>): number;
|
|
41
|
+
/** The `value` of the context entry named `name`, or `null`. */
|
|
42
|
+
export declare function contextValue(context: unknown, name: string): unknown;
|
|
43
|
+
export declare function hasContext(context: unknown, name: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* `_parameter_metadata`: field-shaped metadata carried by each method
|
|
46
|
+
* parameter, keyed by name.
|
|
47
|
+
*
|
|
48
|
+
* A method parameter and a node field describe the same input in two
|
|
49
|
+
* different schemas. `displayName`, `reference` and the choice list exist on
|
|
50
|
+
* both sides, so they are the only ones worth moving across. A parameter's
|
|
51
|
+
* `enum` is deprecated in favour of `enhancedEnum`, whose `{name, value}`
|
|
52
|
+
* pairs flatten to the literals a field's `enum` holds.
|
|
53
|
+
*/
|
|
54
|
+
export declare function parameterMetadata(connectorMethodInfo: unknown): Map<string, Dict>;
|
|
55
|
+
/** `Data.Node` from a parsed `flow registry get` response, or `null`. */
|
|
56
|
+
export declare function nodeOf(payload: unknown): unknown;
|
|
57
|
+
/**
|
|
58
|
+
* `extract_canonical`: the library entry for one registry `Data.Node`, or
|
|
59
|
+
* `undefined` when the node is filtered out (not enabled, not cross-platform,
|
|
60
|
+
* experimental, or without a `connectorDetail` block).
|
|
61
|
+
*/
|
|
62
|
+
export declare function extractCanonical(nodeData: unknown, ctx?: CanonicalContext): LibraryEntry | undefined;
|
|
63
|
+
/** Accept the boolean JSON contract and older Yes/No cache rows. */
|
|
64
|
+
export declare function asBool(value: unknown): boolean;
|
|
65
|
+
/** Read the connector tier across CLI response casing variants. */
|
|
66
|
+
export declare function connectorTier(record: unknown): string | null;
|
|
67
|
+
/** Normalize current and legacy connector tier spellings to `tier1`/`tier2`. */
|
|
68
|
+
export declare function normalizedConnectorTier(record: unknown): "tier1" | "tier2" | null;
|
|
69
|
+
/**
|
|
70
|
+
* Keep the node types whose connector metadata declares `tier` — actions and
|
|
71
|
+
* connector events both, per `scopedConnectorKey`. Returns the kept node types
|
|
72
|
+
* and the connector keys that matched.
|
|
73
|
+
*/
|
|
74
|
+
export declare function filterNodeTypesByTier(nodeTypes: readonly string[], connectorRecords: ReadonlyMap<string, unknown>, tier: string): [string[], Set<string>];
|
|
75
|
+
/** `merge_connector_record`: stamp connector discovery metadata and its derived flag. */
|
|
76
|
+
export declare function mergeConnectorRecord(entry: LibraryEntry, record: unknown): LibraryEntry;
|
|
77
|
+
/**
|
|
78
|
+
* The connector key for an ACTION node type, `uipath.connector.<key>.<op>`, or
|
|
79
|
+
* `null`. The event forms carry an extra segment and are answered by
|
|
80
|
+
* `eventConnectorKey` instead.
|
|
81
|
+
*/
|
|
82
|
+
export declare function actionConnectorKey(nodeType: string): string | null;
|
|
83
|
+
/**
|
|
84
|
+
* The connector key for a WAIT-form event node type,
|
|
85
|
+
* `uipath.connector.event.<key>.<event>`, or `null`. Only the wait form is
|
|
86
|
+
* generated: `registry get` refuses the start form without a connection, and
|
|
87
|
+
* the SDK derives the start form from its wait sibling.
|
|
88
|
+
*/
|
|
89
|
+
export declare function eventConnectorKey(nodeType: string): string | null;
|
|
90
|
+
/** The connector a node type belongs to, for SCOPE filtering: action or wait event. */
|
|
91
|
+
export declare function scopedConnectorKey(nodeType: string): string | null;
|
|
92
|
+
/** The connector a node type belongs to, in ANY of its three forms — trigger included. */
|
|
93
|
+
export declare function catalogConnectorKey(nodeType: unknown): string | null;
|
|
94
|
+
export declare const FIRST_PARTY_PREFIX = "uipath-";
|
|
95
|
+
export declare const MOCK_MARKER = "mock";
|
|
96
|
+
/**
|
|
97
|
+
* Does this connector key belong in the PUBLISHED catalog? `custom-<org>-*` are
|
|
98
|
+
* one tenant's own connectors and `uipath-mock-*` are eval fixtures; neither
|
|
99
|
+
* resolves for another user.
|
|
100
|
+
*/
|
|
101
|
+
export declare function isFirstPartyConnector(key: unknown): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* `(kept node types, dropped connector keys)` for a FULL build. A node type
|
|
104
|
+
* with no connector key at all is not a connector node and is kept.
|
|
105
|
+
*/
|
|
106
|
+
export declare function selectPublishedConnectors(nodeTypes: readonly string[]): [string[], string[]];
|
|
107
|
+
/** The action segment of a `uipath.connector.<key>.<action>` node type. */
|
|
108
|
+
export declare function actionIdFromNodeType(nodeType: string): string;
|
|
109
|
+
export declare function isHttpPassthrough(entry: LibraryEntry): boolean;
|
|
110
|
+
/** Map a PascalCase key to camelCase (first character lowered). */
|
|
111
|
+
export declare function toLowerCamel<T>(s: T): T;
|
|
112
|
+
/**
|
|
113
|
+
* Recursively lower-camel-case every dict key in `value`. The IS CLI started
|
|
114
|
+
* returning PascalCase keys for parameters, fields and references; the library
|
|
115
|
+
* uses camelCase, so the on-disk schema stays stable across CLI versions.
|
|
116
|
+
*/
|
|
117
|
+
export declare function normalizeFieldKeys(value: unknown): unknown;
|
|
118
|
+
/** `_pick`: the first non-None value among `d[k]` for the given keys, else `null`. */
|
|
119
|
+
export declare function pick(d: unknown, ...keys: string[]): unknown;
|