@uipath/maestro-builder-sdk 6.4.0 → 6.5.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.
Files changed (160) hide show
  1. package/dist/cli/commands/registry.js +68 -12
  2. package/dist/registry/archive/entry-policy.d.ts +36 -0
  3. package/dist/registry/archive/entry-policy.js +60 -0
  4. package/dist/registry/archive/extract.d.ts +31 -0
  5. package/dist/registry/archive/extract.js +92 -0
  6. package/dist/registry/archive/zip-reader.d.ts +38 -0
  7. package/dist/registry/archive/zip-reader.js +256 -0
  8. package/dist/registry/codecs/pyjson.d.ts +62 -0
  9. package/dist/registry/codecs/pyjson.js +208 -0
  10. package/dist/registry/compat/compare.d.ts +18 -0
  11. package/dist/registry/compat/compare.js +32 -0
  12. package/dist/registry/compat/paths.d.ts +4 -0
  13. package/dist/registry/compat/paths.js +17 -0
  14. package/dist/registry/compat/pystr.d.ts +50 -0
  15. package/dist/registry/compat/pystr.js +221 -0
  16. package/dist/registry/concurrency.d.ts +10 -0
  17. package/dist/registry/concurrency.js +34 -0
  18. package/dist/registry/curated-overlay.d.ts +36 -4
  19. package/dist/registry/curated-overlay.js +87 -14
  20. package/dist/registry/errors.d.ts +26 -0
  21. package/dist/registry/errors.js +38 -0
  22. package/dist/registry/extractor.d.ts +9 -10
  23. package/dist/registry/extractor.js +5 -15
  24. package/dist/registry/files.d.ts +26 -0
  25. package/dist/registry/files.js +160 -0
  26. package/dist/registry/generators/descriptors.d.ts +81 -0
  27. package/dist/registry/generators/descriptors.js +405 -0
  28. package/dist/registry/generators/fields.d.ts +46 -0
  29. package/dist/registry/generators/fields.js +111 -0
  30. package/dist/registry/generators/markdown/common.d.ts +21 -0
  31. package/dist/registry/generators/markdown/common.js +55 -0
  32. package/dist/registry/generators/markdown/index.d.ts +33 -0
  33. package/dist/registry/generators/markdown/index.js +37 -0
  34. package/dist/registry/generators/markdown/page.d.ts +8 -0
  35. package/dist/registry/generators/markdown/page.js +52 -0
  36. package/dist/registry/generators/markdown/pyvalue.d.ts +34 -0
  37. package/dist/registry/generators/markdown/pyvalue.js +106 -0
  38. package/dist/registry/generators/markdown/sections/choosing-object.d.ts +2 -0
  39. package/dist/registry/generators/markdown/sections/choosing-object.js +52 -0
  40. package/dist/registry/generators/markdown/sections/example.d.ts +22 -0
  41. package/dist/registry/generators/markdown/sections/example.js +295 -0
  42. package/dist/registry/generators/markdown/sections/filtering.d.ts +2 -0
  43. package/dist/registry/generators/markdown/sections/filtering.js +76 -0
  44. package/dist/registry/generators/markdown/sections/header.d.ts +2 -0
  45. package/dist/registry/generators/markdown/sections/header.js +37 -0
  46. package/dist/registry/generators/markdown/sections/inputs.d.ts +30 -0
  47. package/dist/registry/generators/markdown/sections/inputs.js +151 -0
  48. package/dist/registry/generators/markdown/sections/lookups.d.ts +12 -0
  49. package/dist/registry/generators/markdown/sections/lookups.js +150 -0
  50. package/dist/registry/generators/markdown/sections/outputs.d.ts +3 -0
  51. package/dist/registry/generators/markdown/sections/outputs.js +9 -0
  52. package/dist/registry/generators/markdown/sections/resolving-fields.d.ts +2 -0
  53. package/dist/registry/generators/markdown/sections/resolving-fields.js +139 -0
  54. package/dist/registry/generators/markdown/sections/schema-dynamic.d.ts +2 -0
  55. package/dist/registry/generators/markdown/sections/schema-dynamic.js +86 -0
  56. package/dist/registry/generators/materialize.d.ts +30 -0
  57. package/dist/registry/generators/materialize.js +132 -0
  58. package/dist/registry/generators/md-symbols.d.ts +22 -0
  59. package/dist/registry/generators/md-symbols.js +58 -0
  60. package/dist/registry/generators/triggers.d.ts +15 -0
  61. package/dist/registry/generators/triggers.js +85 -0
  62. package/dist/registry/generators/type-registry.d.ts +50 -0
  63. package/dist/registry/generators/type-registry.js +154 -0
  64. package/dist/registry/generators/type-tree.d.ts +65 -0
  65. package/dist/registry/generators/type-tree.js +179 -0
  66. package/dist/registry/library-build/build.d.ts +57 -0
  67. package/dist/registry/library-build/build.js +286 -0
  68. package/dist/registry/library-build/canonical.d.ts +119 -0
  69. package/dist/registry/library-build/canonical.js +512 -0
  70. package/dist/registry/library-build/cli.d.ts +45 -0
  71. package/dist/registry/library-build/cli.js +182 -0
  72. package/dist/registry/library-build/context.d.ts +107 -0
  73. package/dist/registry/library-build/context.js +267 -0
  74. package/dist/registry/library-build/enrich.d.ts +36 -0
  75. package/dist/registry/library-build/enrich.js +158 -0
  76. package/dist/registry/library-build/events.d.ts +108 -0
  77. package/dist/registry/library-build/events.js +476 -0
  78. package/dist/registry/library-build/generic-expand.d.ts +77 -0
  79. package/dist/registry/library-build/generic-expand.js +363 -0
  80. package/dist/registry/library-build/plan.d.ts +71 -0
  81. package/dist/registry/library-build/plan.js +270 -0
  82. package/dist/registry/library-build/py.d.ts +45 -0
  83. package/dist/registry/library-build/py.js +167 -0
  84. package/dist/registry/library-build/schema-action.d.ts +38 -0
  85. package/dist/registry/library-build/schema-action.js +107 -0
  86. package/dist/registry/library-build/write.d.ts +6 -0
  87. package/dist/registry/library-build/write.js +26 -0
  88. package/dist/registry/library-reader.d.ts +20 -0
  89. package/dist/registry/library-reader.js +50 -0
  90. package/dist/registry/lookup-specs.d.ts +55 -0
  91. package/dist/registry/lookup-specs.js +140 -0
  92. package/dist/registry/materialize-cli.js +28 -14
  93. package/dist/registry/materializer.d.ts +25 -3
  94. package/dist/registry/materializer.js +45 -29
  95. package/dist/registry/model/library.d.ts +254 -0
  96. package/dist/registry/model/library.js +23 -0
  97. package/dist/registry/naming.d.ts +54 -0
  98. package/dist/registry/naming.js +142 -0
  99. package/dist/registry/orphans.d.ts +4 -0
  100. package/dist/registry/orphans.js +86 -0
  101. package/dist/registry/prepare/actions.d.ts +26 -0
  102. package/dist/registry/prepare/actions.js +94 -0
  103. package/dist/registry/prepare/connections.d.ts +181 -0
  104. package/dist/registry/prepare/connections.js +399 -0
  105. package/dist/registry/prepare/event.d.ts +96 -0
  106. package/dist/registry/prepare/event.js +268 -0
  107. package/dist/registry/prepare/handoff.d.ts +21 -0
  108. package/dist/registry/prepare/handoff.js +91 -0
  109. package/dist/registry/prepare/ledger.d.ts +104 -0
  110. package/dist/registry/prepare/ledger.js +216 -0
  111. package/dist/registry/prepare/messages.d.ts +190 -0
  112. package/dist/registry/prepare/messages.js +472 -0
  113. package/dist/registry/prepare/objects.d.ts +130 -0
  114. package/dist/registry/prepare/objects.js +318 -0
  115. package/dist/registry/prepare/overlay.d.ts +149 -0
  116. package/dist/registry/prepare/overlay.js +487 -0
  117. package/dist/registry/prepare/parents.d.ts +41 -0
  118. package/dist/registry/prepare/parents.js +122 -0
  119. package/dist/registry/prepare/pipeline.d.ts +91 -0
  120. package/dist/registry/prepare/pipeline.js +376 -0
  121. package/dist/registry/prepare/regenerate.d.ts +9 -0
  122. package/dist/registry/prepare/regenerate.js +50 -0
  123. package/dist/registry/prepare/resolve.d.ts +199 -0
  124. package/dist/registry/prepare/resolve.js +470 -0
  125. package/dist/registry/prepare/retry.d.ts +83 -0
  126. package/dist/registry/prepare/retry.js +109 -0
  127. package/dist/registry/prepare/source-import.d.ts +54 -0
  128. package/dist/registry/prepare/source-import.js +192 -0
  129. package/dist/registry/prepare/support.d.ts +41 -0
  130. package/dist/registry/prepare/support.js +178 -0
  131. package/dist/registry/prepare-cli.d.ts +16 -5
  132. package/dist/registry/prepare-cli.js +60 -53
  133. package/dist/registry/pull-cli.js +8 -7
  134. package/dist/registry/reporter.d.ts +26 -0
  135. package/dist/registry/reporter.js +41 -0
  136. package/dist/registry/uip/client.d.ts +99 -0
  137. package/dist/registry/uip/client.js +226 -0
  138. package/dist/registry/uip/commands.d.ts +40 -0
  139. package/dist/registry/uip/commands.js +80 -0
  140. package/dist/registry/uip/envelope.d.ts +37 -0
  141. package/dist/registry/uip/envelope.js +84 -0
  142. package/dist/registry/uip/response-cache.d.ts +28 -0
  143. package/dist/registry/uip/response-cache.js +57 -0
  144. package/lib/README.md +10 -8
  145. package/package.json +3 -3
  146. package/dist/generators/_connections.py +0 -331
  147. package/dist/generators/_events.py +0 -355
  148. package/dist/generators/_lookups.py +0 -114
  149. package/dist/generators/_naming.py +0 -185
  150. package/dist/generators/_objects.py +0 -299
  151. package/dist/generators/_resolve.py +0 -319
  152. package/dist/generators/convert_library_to_md.py +0 -1441
  153. package/dist/generators/extract_library.py +0 -125
  154. package/dist/generators/generate_connectors_ts.py +0 -936
  155. package/dist/generators/generate_library_json.py +0 -2527
  156. package/dist/generators/generate_triggers_ts.py +0 -110
  157. package/dist/generators/materialize_registry.py +0 -155
  158. package/dist/generators/prepare_connector.py +0 -1860
  159. package/dist/registry/python.d.ts +0 -26
  160. package/dist/registry/python.js +0 -46
@@ -0,0 +1,76 @@
1
+ /**
2
+ * `## Filtering`: the fields a subscription may filter on, and how complete
3
+ * that list is. Two sources, matching how the platform builds each list and
4
+ * what `Library.eventFilterFields` reads: a CURATED event filters on the
5
+ * fields its definition marks (`v1def.filterFields`); a GENERIC event filters
6
+ * on every field the object supports GET on (the entry's `outputSchema`).
7
+ * Ported from `event_filter_lines`.
8
+ */
9
+ import { pyStr } from "../../../compat/pystr.js";
10
+ import { isEventNodeType } from "../../../model/library.js";
11
+ import { dictOf, getStr, listOf, pyOr, pyTruthy } from "../pyvalue.js";
12
+ export function eventFilterLines(j, v1def) {
13
+ const nodeType = getStr(j, "nodeType", "");
14
+ if (!isEventNodeType(nodeType))
15
+ return [];
16
+ const generic = dictOf(j.operation).activityType === "GenericTrigger";
17
+ const fields = [...listOf(pyOr(dictOf(pyOr(dictOf(v1def).filterFields, {})).fields, []))];
18
+ if (generic)
19
+ fields.push(...listOf(pyOr(dictOf(j.outputSchema).fields, [])));
20
+ const names = [];
21
+ for (const raw of fields) {
22
+ const name = dictOf(raw).name;
23
+ if (typeof name === "string" && name && !names.includes(name))
24
+ names.push(name);
25
+ }
26
+ if (!names.length)
27
+ return [];
28
+ const selectors = listOf(pyOr(dictOf(pyOr(dictOf(v1def).eventParameters, {})).fields, []))
29
+ .map(dictOf)
30
+ .filter((f) => pyTruthy(f.required) && (f.bucket === "query" || f.bucket === "path"))
31
+ .map((f) => pyStr(f.name));
32
+ const out = ["## Filtering", ""];
33
+ out.push("Narrow which records fire the subscription with `filters`. Each leaf is " +
34
+ "`{ field, <operator>: value }` with exactly ONE operator " +
35
+ "(`contains`, `startsWith`, `endsWith`, `equals`, `notEquals`, " +
36
+ "`lessThan`, `lessThanOrEqual`, `greaterThan`, `greaterThanOrEqual`):");
37
+ out.push("");
38
+ out.push("```ts");
39
+ out.push(`filters: [{ field: '${names[0]}', contains: '<value>' }]`);
40
+ out.push("```");
41
+ out.push("");
42
+ out.push("Field names are CASE-SENSITIVE and only these are filterable — the " +
43
+ "platform drops a leaf it does not recognise and the trigger then fires " +
44
+ "on records the filter should have excluded, so `check` reports one that " +
45
+ "is not here.");
46
+ out.push("");
47
+ const shown = names
48
+ .slice(0, 40)
49
+ .map((n) => `\`${n}\``)
50
+ .join(", ");
51
+ const more = names.length > 40 ? ` …and ${names.length - 40} more` : "";
52
+ out.push(`${shown}${more}`);
53
+ out.push("");
54
+ if (selectors.length) {
55
+ const listed = selectors.map((n) => `\`${n}\``).join(", ");
56
+ out.push(`> **This list is a baseline, not the whole vocabulary.** ${listed} ` +
57
+ "select this event's schema, and the connector derives its filter " +
58
+ "and output fields from their VALUES — which no discovery call " +
59
+ "accepts, so the fields above are the ones reported with none " +
60
+ "supplied. A name outside them may still be legal, which is why " +
61
+ "`check` warns rather than refuses here. Confirm it against the " +
62
+ "trigger in the designer before deploying.");
63
+ out.push("");
64
+ }
65
+ else if (Object.entries(dictOf(pyOr(dictOf(j.connector).discovery, {}))).some(([name, value]) => name !== "type" && pyTruthy(value))) {
66
+ // Keyed on ANY discovery flag to match `Library.eventParameterFields.filtersPartial`.
67
+ out.push("> **This list is a subset no `prepare` can complete.** This connector " +
68
+ "reads its schema from the connection, and the trigger metadata call " +
69
+ "takes no parent values — `uip is triggers describe` has no `-f`, the " +
70
+ "flag that materializes an ACTIVITY's connection-scoped fields. So a " +
71
+ "name outside the list above may be a real field of yours; `check` warns " +
72
+ "rather than refuses, and the designer is where to confirm it.");
73
+ out.push("");
74
+ }
75
+ return out;
76
+ }
@@ -0,0 +1,2 @@
1
+ import { type Dict } from "../pyvalue.js";
2
+ export declare function headerLines(j: Dict, nodeType: string): string[];
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The page header: `# <nodeType>@<version>` and the connector / operation /
3
+ * object / label / description / HTTP lines. Curated and Generic entries share
4
+ * the shape; only the values differ.
5
+ */
6
+ import { pyStr, pyStrip } from "../../../compat/pystr.js";
7
+ import { dictOf, getStr, pyOr, pyTruthy } from "../pyvalue.js";
8
+ export function headerLines(j, nodeType) {
9
+ const version = getStr(j, "version", "?");
10
+ const conn = dictOf(j.connector);
11
+ const op = dictOf(j.operation);
12
+ const display = dictOf(j.display);
13
+ const out = [`# ${nodeType}@${version}`, ""];
14
+ let connLabel = getStr(conn, "key", "?");
15
+ if (pyTruthy(conn.name))
16
+ connLabel += ` (${pyStr(conn.name)})`;
17
+ out.push(`**Connector:** ${connLabel}`);
18
+ const verb = pyOr(op.name, "");
19
+ if (pyTruthy(verb))
20
+ out.push(`**Operation:** ${pyStr(verb)}`);
21
+ const objectName = pyOr(op.objectName, "");
22
+ if (pyTruthy(objectName))
23
+ out.push(`**Object:** \`${pyStr(objectName)}\``);
24
+ // Only shown when it adds information beyond `<verb> <object>`.
25
+ const label = pyStrip(pyStr(pyOr(display.label, "")));
26
+ if (label)
27
+ out.push(`**Label:** ${label}`);
28
+ const desc = pyStrip(pyStr(pyOr(display.description, "")));
29
+ if (desc)
30
+ out.push(`**Description:** ${desc}`);
31
+ const httpMethod = pyOr(op.httpMethod, "");
32
+ const httpPath = pyOr(op.pathTemplate, op.path, "");
33
+ if (pyTruthy(httpMethod) && pyTruthy(httpPath))
34
+ out.push(`**HTTP:** ${pyStr(httpMethod)} ${pyStr(httpPath)}`);
35
+ out.push("");
36
+ return out;
37
+ }
@@ -0,0 +1,30 @@
1
+ import { type Dict } from "../pyvalue.js";
2
+ export declare function scalarType(dataType: unknown): string;
3
+ /**
4
+ * The op's QUERY, PATH and file MULTIPART parameters as body-shaped fields,
5
+ * each tagged with its `location`. A string-typed multipart part is the
6
+ * transport container the runtime composes, not an input.
7
+ */
8
+ export declare function paramFields(j: Dict): Dict[];
9
+ /** File fields whose older catalog entry omitted the multipart parameter. */
10
+ export declare function catalogMultipartFields(j: Dict): Dict[];
11
+ /**
12
+ * The op's body fields: the sidecar's `inputDefinition.fields` whenever that
13
+ * key is present (an empty list stays empty), else the catalog's
14
+ * `inputSchema.fields`. This is the markdown generator's own rule, distinct
15
+ * from the descriptor generator's `inputFields`.
16
+ */
17
+ export declare function inputFields(j: Dict, v1def: Dict | undefined): unknown[];
18
+ /**
19
+ * Body fields, catalog-only file fields, then declared parameters. A
20
+ * parameter is authoritative on location, so it fills a same-named field in
21
+ * place — keeping any `reference`, `enum` or `displayName` the entry's field
22
+ * already carries — or is appended when the name is new.
23
+ */
24
+ export declare function assembleFields(j: Dict, v1def: Dict | undefined): Dict[];
25
+ /** One `- \`name\` (type, …) — description` bullet. */
26
+ export declare function fieldLine(f: Dict): string;
27
+ /** `## Required inputs`, always present; `_(none)_` when empty. */
28
+ export declare function requiredInputsLines(required: readonly Dict[]): string[];
29
+ /** `## Optional inputs`, only when there are any. */
30
+ export declare function optionalInputsLines(optional: readonly Dict[]): string[];
@@ -0,0 +1,151 @@
1
+ /**
2
+ * The input field set a page documents, and the line each field prints as.
3
+ *
4
+ * The set is the sidecar's `inputDefinition.fields` (what the compiler
5
+ * validates), falling back to the catalog's `inputSchema.fields` when an
6
+ * operation ships no sidecar; then the catalog's file fields as multipart
7
+ * parts; then the operation's QUERY, PATH and file MULTIPART parameters, a
8
+ * parameter filling gaps in a same-named body field rather than replacing it.
9
+ * Ported from `input_fields`, `catalog_multipart_fields`, `param_fields`,
10
+ * `field_line` and the assembly in `render_op`.
11
+ */
12
+ import { pyStr, pyStrip } from "../../../compat/pystr.js";
13
+ import { isContainerPart } from "../../fields.js";
14
+ import { authoringField, enumValue, referenceCollection } from "../common.js";
15
+ import { dictOf, listOf, pyOr, pyTruthy } from "../pyvalue.js";
16
+ /** `operation.parameters[].type` → the wire slot, mirroring `core/library.ts`'s PARAM_LOCATIONS. */
17
+ const PARAM_LOCATIONS = { query: "query", path: "path", multipart: "multipart" };
18
+ /** A parameter's `dataType` → the scalar names `compile`'s literal type-check understands. */
19
+ const SCALARS = {
20
+ integer: "number",
21
+ number: "number",
22
+ double: "number",
23
+ float: "number",
24
+ long: "number",
25
+ boolean: "boolean",
26
+ string: "string",
27
+ };
28
+ export function scalarType(dataType) {
29
+ if (typeof dataType !== "string")
30
+ return "?";
31
+ return Object.hasOwn(SCALARS, dataType) ? SCALARS[dataType] : dataType;
32
+ }
33
+ /**
34
+ * The op's QUERY, PATH and file MULTIPART parameters as body-shaped fields,
35
+ * each tagged with its `location`. A string-typed multipart part is the
36
+ * transport container the runtime composes, not an input.
37
+ */
38
+ export function paramFields(j) {
39
+ const out = [];
40
+ for (const raw of listOf(pyOr(dictOf(j.operation).parameters, []))) {
41
+ const p = dictOf(raw);
42
+ const name = p.name;
43
+ const type = p.type;
44
+ const loc = typeof type === "string" && Object.hasOwn(PARAM_LOCATIONS, type) ? PARAM_LOCATIONS[type] : undefined;
45
+ if (typeof name !== "string" || !name || !loc)
46
+ continue;
47
+ if (isContainerPart(p))
48
+ continue;
49
+ const f = { name, type: scalarType(p.dataType), required: p.required === true, location: loc };
50
+ if (pyTruthy(p.description))
51
+ f.description = p.description;
52
+ if (pyTruthy(p.displayName))
53
+ f.displayName = p.displayName;
54
+ // `reference` says the value is an id resolved from a collection, not free text.
55
+ if (pyTruthy(p.reference))
56
+ f.reference = p.reference;
57
+ // A parameter's `enum` is deprecated in favour of `enhancedEnum`.
58
+ if (pyTruthy(p.enum))
59
+ f.enum = p.enum;
60
+ else if (pyTruthy(p.enhancedEnum))
61
+ f.enum = p.enhancedEnum;
62
+ out.push(f);
63
+ }
64
+ return out;
65
+ }
66
+ /** File fields whose older catalog entry omitted the multipart parameter. */
67
+ export function catalogMultipartFields(j) {
68
+ const out = [];
69
+ for (const raw of listOf(pyOr(dictOf(j.inputSchema).fields, []))) {
70
+ const field = dictOf(raw);
71
+ if (!pyTruthy(field.name) || pyStr(pyOr(field.type, "")).toLowerCase() !== "file")
72
+ continue;
73
+ out.push({ ...field, location: "multipart" });
74
+ }
75
+ return out;
76
+ }
77
+ /**
78
+ * The op's body fields: the sidecar's `inputDefinition.fields` whenever that
79
+ * key is present (an empty list stays empty), else the catalog's
80
+ * `inputSchema.fields`. This is the markdown generator's own rule, distinct
81
+ * from the descriptor generator's `inputFields`.
82
+ */
83
+ export function inputFields(j, v1def) {
84
+ const fields = dictOf(pyOr(dictOf(v1def).inputDefinition, {})).fields;
85
+ if (fields === undefined || fields === null)
86
+ return listOf(pyOr(dictOf(j.inputSchema).fields, []));
87
+ return listOf(fields);
88
+ }
89
+ /**
90
+ * Body fields, catalog-only file fields, then declared parameters. A
91
+ * parameter is authoritative on location, so it fills a same-named field in
92
+ * place — keeping any `reference`, `enum` or `displayName` the entry's field
93
+ * already carries — or is appended when the name is new.
94
+ */
95
+ export function assembleFields(j, v1def) {
96
+ const fields = inputFields(j, v1def).map((f) => ({ ...dictOf(f) }));
97
+ for (const p of [...catalogMultipartFields(j), ...paramFields(j)]) {
98
+ const at = fields.findIndex((f) => f.name === p.name);
99
+ if (at >= 0) {
100
+ const merged = { ...fields[at] };
101
+ for (const [k, v] of Object.entries(p)) {
102
+ if (v !== null && v !== undefined && v !== "")
103
+ merged[k] = v;
104
+ }
105
+ for (const key of ["reference", "enum", "displayName"]) {
106
+ if (key in fields[at] && !(key in p))
107
+ merged[key] = fields[at][key];
108
+ }
109
+ fields[at] = merged;
110
+ }
111
+ else {
112
+ fields.push(p);
113
+ }
114
+ }
115
+ return fields;
116
+ }
117
+ /** One `- \`name\` (type, …) — description` bullet. */
118
+ export function fieldLine(f) {
119
+ const [name, type, wireName] = authoringField(f);
120
+ const desc = pyStrip(pyStr(pyOr(f.description, "")).replaceAll("\n", " "));
121
+ const enumeration = f.enum;
122
+ let suffix = pyTruthy(enumeration) ? `, enum: ${listOf(enumeration).map(enumValue).join(" | ")}` : "";
123
+ if (wireName)
124
+ suffix += `, wire field: \`${wireName}\``;
125
+ // The wire slot for a QUERY, PATH or MULTIPART parameter; body fields stay untagged.
126
+ const loc = f.location;
127
+ if (loc === "query" || loc === "path" || loc === "multipart")
128
+ suffix += `, ${loc}`;
129
+ // Name the collection so the line itself says "this is a lookup, not free text".
130
+ const collection = referenceCollection(f);
131
+ if (collection)
132
+ suffix += `, lookup: ${collection}`;
133
+ const head = `- \`${name}\` (${type}${suffix})`;
134
+ return desc ? `${head} — ${desc}` : head;
135
+ }
136
+ /** `## Required inputs`, always present; `_(none)_` when empty. */
137
+ export function requiredInputsLines(required) {
138
+ const out = ["## Required inputs", ""];
139
+ if (required.length)
140
+ out.push(...required.map(fieldLine));
141
+ else
142
+ out.push("_(none)_");
143
+ out.push("");
144
+ return out;
145
+ }
146
+ /** `## Optional inputs`, only when there are any. */
147
+ export function optionalInputsLines(optional) {
148
+ if (!optional.length)
149
+ return [];
150
+ return ["## Optional inputs", "", ...optional.map(fieldLine), ""];
151
+ }
@@ -0,0 +1,12 @@
1
+ import { type Dict } from "../pyvalue.js";
2
+ /** The `resources run list` call that shows what an identity-lookup field accepts. */
3
+ export declare function enumerationCommand(connectorKey: string, f: Dict): string;
4
+ /** Prose for how `prepare` will retrieve this collection. */
5
+ export declare function referenceStrategy(reference: Dict): string;
6
+ /**
7
+ * The section body, or `[]` when no field is a lookup. `symbol` is the
8
+ * generated descriptor's exported name, or `undefined` when the operation has
9
+ * no descriptor (a Generic CRUD expansion), in which case the string form of
10
+ * `lookup()` carries the real key and action.
11
+ */
12
+ export declare function lookupLines(connectorKey: string, action: string, fields: readonly Dict[], symbol: string | undefined, invariant: ReadonlySet<string>): string[];
@@ -0,0 +1,150 @@
1
+ /**
2
+ * `## Resolving lookups`: helpers first, enumeration commands only where owed.
3
+ *
4
+ * A field holding an id is resolved late through `lookup(...)` and one
5
+ * `prepare`; the `resources run list` command survives only for IDENTITY
6
+ * lookups, which have no helper and no offline vocabulary. Ported from
7
+ * `lookup_lines`, `enumeration_command` and `reference_strategy`.
8
+ */
9
+ import { pyJsonString } from "../../../codecs/pyjson.js";
10
+ import { sortedStrings } from "../../../compat/compare.js";
11
+ import { pyStr, splitOnce } from "../../../compat/pystr.js";
12
+ import { classify, referenceOf } from "../../../lookup-specs.js";
13
+ import { byAliases } from "../../../naming.js";
14
+ import { authoringField, referenceCollection, referenceQuery } from "../common.js";
15
+ import { firstValue, IDENT, pyOr, pyTruthy, strList } from "../pyvalue.js";
16
+ /** The `resources run list` call that shows what an identity-lookup field accepts. */
17
+ export function enumerationCommand(connectorKey, f) {
18
+ const collection = referenceCollection(f);
19
+ const query = referenceQuery(f);
20
+ let command = `uip is resources run list ${connectorKey} ${collection} --connection-id <id>`;
21
+ if (query)
22
+ command += ` --query "${query}"`;
23
+ return command;
24
+ }
25
+ /** Prose for how `prepare` will retrieve this collection. */
26
+ export function referenceStrategy(reference) {
27
+ if (pyTruthy(reference.dependsOn)) {
28
+ const depends = strList(reference.dependsOn)
29
+ .map((d) => `\`${d}\``)
30
+ .join(", ");
31
+ return `dependent — resolve ${depends} first`;
32
+ }
33
+ if (pyTruthy(reference.filterPattern))
34
+ return "one request (server-side filter)";
35
+ if (pyTruthy(reference.childPath))
36
+ return "hierarchical walk";
37
+ return "paged scan (no server-side filter declared)";
38
+ }
39
+ /**
40
+ * The section body, or `[]` when no field is a lookup. `symbol` is the
41
+ * generated descriptor's exported name, or `undefined` when the operation has
42
+ * no descriptor (a Generic CRUD expansion), in which case the string form of
43
+ * `lookup()` carries the real key and action.
44
+ */
45
+ export function lookupLines(connectorKey, action, fields, symbol, invariant) {
46
+ const resolvable = [];
47
+ const identity = [];
48
+ for (const f of fields) {
49
+ const kind = classify(f, invariant);
50
+ if (kind === "lookup")
51
+ resolvable.push([f, referenceOf(f)]);
52
+ else if (kind === "identity")
53
+ identity.push(f);
54
+ }
55
+ if (!resolvable.length && !identity.length)
56
+ return [];
57
+ const out = [];
58
+ if (resolvable.length) {
59
+ const [firstField, firstReference] = resolvable[0];
60
+ // Keyed by the WIRE name (`users[*]`), the string `--resolve` and
61
+ // buildConnectorInputs match on; the table's `field` column keeps the
62
+ // authoring name the reader writes as an object key.
63
+ const firstName = pyStr(pyOr(firstField.name, authoringField(firstField)[0]));
64
+ const firstNames = strList(firstReference.lookupNames);
65
+ const firstAliases = byAliases(firstNames);
66
+ const holder = symbol || `'${connectorKey}', '${action}'`;
67
+ const call = `lookup(${holder}, '${firstName}')`;
68
+ const sample = firstAliases.size
69
+ ? `.${firstValue(firstAliases)}('…')`
70
+ : firstNames.length
71
+ ? `.by('${firstNames[0]}', '…')`
72
+ : ".by('id', '…')";
73
+ // The MECHANISM — resolve, never hand-write the wire value — is true of
74
+ // every lookup. The old JUSTIFICATION was not: it asserted the value is an
75
+ // opaque, connection-specific id, which is false for 320 of the library's
76
+ // 2,563 rows and, on `uipath-salesforce-slack` `send-message-to-user`, for
77
+ // a row printed three lines below the claim (`send_as` sends the word
78
+ // `bot`) — #706. Nothing in the metadata says which case a field is in, so
79
+ // the id claim is stated as the CONDITION it always was, and the `sends`
80
+ // column — already printed below — answers which case this page is.
81
+ out.push("These fields send a value the connector defines, not the label you " +
82
+ "know it by — the `sends` column says which. Do not write that value " +
83
+ "by hand: where it is an opaque id it is also connection-specific, so " +
84
+ "a pasted one resolves to nobody (or to somebody else) against a " +
85
+ "different connection. Resolve it late:");
86
+ out.push("");
87
+ out.push("```ts");
88
+ // A dotted wire name is a legal object key only when quoted.
89
+ const key = IDENT.test(firstName) ? firstName : pyJsonString(firstName);
90
+ out.push(`${key}: ${call}${sample}`);
91
+ out.push("```");
92
+ out.push("");
93
+ out.push("| field | helpers | matches on | sends |");
94
+ out.push("| --- | --- | --- | --- |");
95
+ for (const [f, reference] of resolvable) {
96
+ const [name] = authoringField(f);
97
+ const names = strList(reference.lookupNames);
98
+ const aliases = byAliases(names);
99
+ const helperCell = aliases.size
100
+ ? [...aliases.values()].map((a) => `\`.${a}(v)\``).join(" ")
101
+ : "_(generic form only)_";
102
+ // `objectName` can carry a query string; show the collection.
103
+ const target = pyOr(splitOnce(pyStr(pyOr(reference.objectName, "")), "?")[0], referenceCollection(f));
104
+ out.push(`| \`${name}\` | ${helperCell} | ` +
105
+ names.map((n) => `\`${n}\``).join(" ") +
106
+ ` | \`${target}.${pyStr(reference.lookupValue)}\` |`);
107
+ }
108
+ out.push("");
109
+ out.push("Any field also takes the generic form: `.by('<name>', value)`.");
110
+ out.push("");
111
+ // ORDERING, not just the command: author the token, let check name the command, run it once.
112
+ out.push("Author the `lookup()` call and finish the flow — `check` reports " +
113
+ "each token still unresolved with exactly this command; run it " +
114
+ "once before compiling (`compile` refuses an unresolved lookup):");
115
+ out.push("");
116
+ // ONE command carrying every --resolve, and no `--connection-id`.
117
+ out.push("```bash");
118
+ out.push(`npx flow-sdk registry prepare ${connectorKey} ${action} \\`);
119
+ const resolves = resolvable.map(([f, reference]) => {
120
+ const [name] = authoringField(f);
121
+ const names = pyOr(strList(reference.lookupNames), ["id"]);
122
+ return ` --resolve ${name}:${names[0]}=<value>`;
123
+ });
124
+ for (const line of resolves.slice(0, -1))
125
+ out.push(`${line} \\`);
126
+ out.push(resolves[resolves.length - 1]);
127
+ out.push("```");
128
+ out.push("");
129
+ const strategies = new Set(resolvable.map(([, r]) => referenceStrategy(r)));
130
+ out.push(`Strategy: ${sortedStrings(strategies).join("; ")}.`);
131
+ out.push("");
132
+ }
133
+ if (identity.length) {
134
+ out.push("**These fields take a plain string.** Their `reference` enumerates " +
135
+ "the legal values rather than mapping a name to an id — what you " +
136
+ "send back is what you searched for — so there is no helper and " +
137
+ "nothing to resolve. The values exist only behind the connection, " +
138
+ "so this is how to see what is accepted:");
139
+ out.push("");
140
+ out.push("```bash");
141
+ for (const f of identity) {
142
+ const [name] = authoringField(f);
143
+ out.push(`# ${name}`);
144
+ out.push(enumerationCommand(connectorKey, f));
145
+ }
146
+ out.push("```");
147
+ out.push("");
148
+ }
149
+ return out;
150
+ }
@@ -0,0 +1,3 @@
1
+ /** `## Outputs`: the entry's `outputSchema.fields`, one bullet each. The sidecar carries no output fields. */
2
+ import { type Dict } from "../pyvalue.js";
3
+ export declare function outputsLines(j: Dict): string[];
@@ -0,0 +1,9 @@
1
+ /** `## Outputs`: the entry's `outputSchema.fields`, one bullet each. The sidecar carries no output fields. */
2
+ import { dictOf, listOf, pyOr } from "../pyvalue.js";
3
+ import { fieldLine } from "./inputs.js";
4
+ export function outputsLines(j) {
5
+ const outFields = listOf(pyOr(dictOf(j.outputSchema).fields, []));
6
+ if (!outFields.length)
7
+ return [];
8
+ return ["## Outputs", "", ...outFields.map((f) => fieldLine(dictOf(f))), ""];
9
+ }
@@ -0,0 +1,2 @@
1
+ import { type Dict } from "../pyvalue.js";
2
+ export declare function schemaActionLines(connectorKey: string, objectName: string, verb: string, action: Dict, fields: readonly Dict[]): string[];
@@ -0,0 +1,139 @@
1
+ /**
2
+ * `## Resolving the field set`: how to get an operation's real field set when
3
+ * parent VALUES select it (Jira `create-issue` describes to 2 fields with
4
+ * nothing supplied and 32 once a project and an issue type are given).
5
+ * Ported from `schema_action_lines`.
6
+ */
7
+ import { pyStr, splitOnce } from "../../../compat/pystr.js";
8
+ import { referenceCollection, referenceQuery } from "../common.js";
9
+ import { dictOf, listOf, pyOr, pyTruthy } from "../pyvalue.js";
10
+ export function schemaActionLines(connectorKey, objectName, verb, action, fields) {
11
+ const parents = listOf(pyOr(action.parents, []));
12
+ if (!parents.length)
13
+ return [];
14
+ const byName = new Map();
15
+ for (const f of fields)
16
+ byName.set(f.name, f);
17
+ const trigger = action.trigger;
18
+ const replaces = action.replaces;
19
+ const obj = pyOr(objectName, "<object>");
20
+ const out = ["## Resolving the field set", ""];
21
+ out.push("The inputs listed below are only the ones that SELECT the field set. " +
22
+ "The real set depends on the values of " +
23
+ parents.map((p) => `\`${pyStr(p)}\``).join(", ") +
24
+ " — a different value gives a different set, so there is no single " +
25
+ "field list for this operation.");
26
+ out.push("");
27
+ if (pyTruthy(trigger)) {
28
+ out.push(`It is not automatic: \`${pyStr(trigger)}\` is a trigger rather than data, ` +
29
+ "so the schema has to be requested once the values are in place.");
30
+ out.push("");
31
+ }
32
+ out.push("Resolve the parents in this order, then describe again:");
33
+ out.push("");
34
+ parents.forEach((parentRaw, i) => {
35
+ const position = i + 1;
36
+ const parent = pyStr(parentRaw);
37
+ const field = dictOf(byName.get(parentRaw));
38
+ const reference = dictOf(pyOr(field.reference, {}));
39
+ const collection = referenceCollection(field);
40
+ if (!collection) {
41
+ out.push(`${position}. \`${parent}\` — supply the value; it is not chosen from a list.`);
42
+ out.push("");
43
+ return;
44
+ }
45
+ const query = referenceQuery(field);
46
+ const pattern = pyStr(pyOr(reference.filterPattern, ""));
47
+ const names = listOf(pyOr(reference.lookupNames, []));
48
+ const send = pyStr(pyOr(reference.lookupValue, "id"));
49
+ out.push(`${position}. \`${parent}\` — from \`${collection}\`` +
50
+ (names.length ? `, match on ${names.map((n) => `\`${pyStr(n)}\``).join(" or ")}` : "") +
51
+ `, send \`${send}\`.`);
52
+ // A placeholder means an earlier parent's value goes here.
53
+ if (collection.includes("{")) {
54
+ out.push(" Substitute the value resolved above for the `{…}` part of the collection.");
55
+ }
56
+ out.push("");
57
+ out.push(" ```bash");
58
+ out.push(` uip is resources run list ${connectorKey} ${collection} --connection-id <id> \\`);
59
+ if (pattern) {
60
+ // The connector declares its own search; substituting the term narrows server-side.
61
+ out.push(` --query "${pattern.replaceAll("{filter}", "<search-term>")}" \\`);
62
+ }
63
+ else if (query) {
64
+ out.push(` --query "${query}" \\`);
65
+ }
66
+ const projection = pyOr(names.slice(0, 2), ["name"])
67
+ .map((n) => `${splitOnce(pyStr(n), "[")[0]}:${pyStr(n)}`)
68
+ .join(",");
69
+ out.push(` --output-filter "{items: items[*].{${projection},` +
70
+ `send:${send}}, page: Pagination.{h:HasMore,t:NextPageToken}}" \\`);
71
+ out.push(" --output json");
72
+ out.push(" ```");
73
+ out.push("");
74
+ if (pattern) {
75
+ out.push(" The connector declares its own search, so narrow with " +
76
+ "the term the user gave rather than reading pages: one " +
77
+ "call usually returns a handful, and `page` comes back " +
78
+ "either absent or with `h` as `\"false\"`. Page only if " +
79
+ "the term matches nothing.");
80
+ }
81
+ else {
82
+ out.push(" Page it: `page.h` is the `elements-has-more` response " +
83
+ "header verbatim, so it is the string `\"true\"` rather " +
84
+ "than a boolean, and `page` is absent altogether when the " +
85
+ "connector sends no pagination headers. While it reads " +
86
+ "`\"true\"` and the value has not appeared, pass `page.t` " +
87
+ "back as `--query \"nextPage=<token>\"` and read the next " +
88
+ "page. Stop on the match. The projection keeps each page " +
89
+ "small but does not reduce the call count.");
90
+ out.push("");
91
+ out.push(" Before paging, check this field's `Reference` in the " +
92
+ "`describe` output for a `FilterPattern`: it is " +
93
+ "connection-scoped, so it is not in this catalog, but when " +
94
+ "present it is the connector's own search and removes the " +
95
+ "paging — Jira's project lookup declares `query={filter}`, " +
96
+ "which turns 420-plus rows across pages into two in one call. " +
97
+ "Substitute the wanted term into whatever pattern this field " +
98
+ "declares; the shape is:");
99
+ out.push("");
100
+ out.push(" ```bash");
101
+ out.push(` uip is resources run list ${connectorKey} ${collection} --connection-id <id> \\`);
102
+ out.push(' --query "<filter-pattern with the term substituted>" --output json');
103
+ out.push(" ```");
104
+ }
105
+ out.push("");
106
+ });
107
+ const supplied = parents.map((p) => `-f ${pyStr(p)}=<value>`).join(" ");
108
+ out.push(`${parents.length + 1}. Describe again with the resolved values:`);
109
+ out.push("");
110
+ out.push(" ```bash");
111
+ out.push(` uip is resources describe ${connectorKey} ${pyStr(obj)} --operation ${verb} \\`);
112
+ out.push(` --connection-id <id> ${supplied} --output json`);
113
+ out.push(" ```");
114
+ out.push("");
115
+ if (replaces === "output") {
116
+ out.push(" This replaces the **response** fields — it tells you the shape " +
117
+ "of what comes back, not what to send.");
118
+ }
119
+ else if (replaces === "both") {
120
+ out.push(" This replaces the **request** fields AND the **response** " +
121
+ "fields — both halves of this operation change with the values " +
122
+ "above, so read the response shape from the same call.");
123
+ }
124
+ else {
125
+ out.push(" This replaces the **request** fields.");
126
+ }
127
+ out.push("");
128
+ // Only meaningful where the action rewrites the INPUT (matches the CLI's `isParentOnlyResult` gate).
129
+ if (replaces === "input" || replaces === "both") {
130
+ out.push("If the result contains only the parents again, one of the values " +
131
+ "does not exist on this connection. The call reports `Success` " +
132
+ "either way, so the count alone cannot tell that apart from having " +
133
+ "supplied nothing — check whether anything beyond the parents came " +
134
+ "back. Too FEW parents fails loudly instead, with " +
135
+ "`No api-type ObjectAction matched`.");
136
+ out.push("");
137
+ }
138
+ return out;
139
+ }
@@ -0,0 +1,2 @@
1
+ import { type Dict } from "../pyvalue.js";
2
+ export declare function schemaDynamicLines(j: Dict, nodeType: string): string[];