@uipath/maestro-builder-sdk 6.3.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.
- package/dist/api-index.md +6 -6
- 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,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `## Example`: a compilable `connector(...)` call — or, for an event, an
|
|
3
|
+
* `onEvent(...)` / `waitForEvent(...)` call — for the operation.
|
|
4
|
+
*
|
|
5
|
+
* Required inputs only, nested the way the descriptor's `Inputs` type is
|
|
6
|
+
* nested, with the import path DERIVED: a schema-dynamic operation's
|
|
7
|
+
* descriptor lives in `./connectors-local/` after a `prepare`. When a
|
|
8
|
+
* descriptor exists the example is type-checked against its `Inputs`, so the
|
|
9
|
+
* required set is the descriptor generator's, not this module's; the two
|
|
10
|
+
* vocabularies disagree about required-ness on most operations, and that
|
|
11
|
+
* disagreement is pre-existing. Ported from `example_lines`,
|
|
12
|
+
* `event_example_lines`, `nest_inputs`, `example_value`, `leaf_name` and
|
|
13
|
+
* `pascal_step`.
|
|
14
|
+
*/
|
|
15
|
+
import { PACKAGE_NAME } from "../../../../package-name.js";
|
|
16
|
+
import { pyJsonString } from "../../../codecs/pyjson.js";
|
|
17
|
+
import { sortedStrings } from "../../../compat/compare.js";
|
|
18
|
+
import { afterLast, pyStr, upperFirst } from "../../../compat/pystr.js";
|
|
19
|
+
import { classify, referenceOf } from "../../../lookup-specs.js";
|
|
20
|
+
import { isEventNodeType, TRIGGER_PREFIX } from "../../../model/library.js";
|
|
21
|
+
import { byAliases } from "../../../naming.js";
|
|
22
|
+
import { descriptorInputFields, markLookupFields } from "../../fields.js";
|
|
23
|
+
import { authoringField, enumValue } from "../common.js";
|
|
24
|
+
import { dictOf, firstValue, getStr, IDENT, listOf, pyFloatAccepts, pyOr, pyTruthy, strList, } from "../pyvalue.js";
|
|
25
|
+
/** `fields.project.key` → `projectKey`: a readable input name, not a path. */
|
|
26
|
+
export function leafName(fieldName) {
|
|
27
|
+
const parts = fieldName.replaceAll("[*]", "").split(".").filter((p) => p);
|
|
28
|
+
if (!parts.length)
|
|
29
|
+
return "value";
|
|
30
|
+
if (parts.length === 1)
|
|
31
|
+
return parts[0];
|
|
32
|
+
const [head, ...rest] = parts.slice(-2);
|
|
33
|
+
return head + rest.map(upperFirst).join("");
|
|
34
|
+
}
|
|
35
|
+
/** `send-message-to-user` → `sendMessageToUser`, a usable step name. */
|
|
36
|
+
export function pascalStep(action) {
|
|
37
|
+
const words = action.replaceAll("_", "-").split("-").filter((w) => w);
|
|
38
|
+
if (!words.length)
|
|
39
|
+
return "step";
|
|
40
|
+
const [head, ...rest] = words;
|
|
41
|
+
return head + rest.map(upperFirst).join("");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One level of the example's input literal. A segment can be BOTH an array
|
|
45
|
+
* and an object (`contacts[*].name` is a list of objects), so array-ness is a
|
|
46
|
+
* flag on the node. `children` is insertion-ordered, like the Python dict.
|
|
47
|
+
*/
|
|
48
|
+
class Node {
|
|
49
|
+
children = new Map();
|
|
50
|
+
isArray = false;
|
|
51
|
+
leaf;
|
|
52
|
+
}
|
|
53
|
+
/** Render `[name, value]` pairs as the nested object literal an author writes. */
|
|
54
|
+
export function nestInputs(pairs) {
|
|
55
|
+
const root = new Node();
|
|
56
|
+
for (const [name, value] of pairs) {
|
|
57
|
+
let node = root;
|
|
58
|
+
for (const segment of pyStr(name).split(".").filter((p) => p)) {
|
|
59
|
+
const isArray = segment.endsWith("[*]");
|
|
60
|
+
const key = isArray ? segment.slice(0, -3) : segment;
|
|
61
|
+
let child = node.children.get(key);
|
|
62
|
+
if (child === undefined) {
|
|
63
|
+
child = new Node();
|
|
64
|
+
node.children.set(key, child);
|
|
65
|
+
}
|
|
66
|
+
child.isArray = child.isArray || isArray;
|
|
67
|
+
node = child;
|
|
68
|
+
}
|
|
69
|
+
node.leaf = value;
|
|
70
|
+
}
|
|
71
|
+
const render = (node, indent) => {
|
|
72
|
+
const pad = " ".repeat(indent);
|
|
73
|
+
const lines = [];
|
|
74
|
+
for (const [key, child] of node.children) {
|
|
75
|
+
const safe = IDENT.test(key) ? key : pyJsonString(key);
|
|
76
|
+
if (child.children.size) {
|
|
77
|
+
const [openBrace, closeBrace] = child.isArray ? ["[{", "}],"] : ["{", "},"];
|
|
78
|
+
lines.push(`${pad}${safe}: ${openBrace}`);
|
|
79
|
+
lines.push(...render(child, indent + 1));
|
|
80
|
+
lines.push(`${pad}${closeBrace}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const value = child.leaf !== undefined ? child.leaf : "undefined";
|
|
84
|
+
lines.push(child.isArray ? `${pad}${safe}: [${value}],` : `${pad}${safe}: ${value},`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return lines;
|
|
88
|
+
};
|
|
89
|
+
return render(root, 1);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The value to show for one required input: a resolvable lookup shows its
|
|
93
|
+
* helper; an enum shows its FIRST DECLARED CHOICE, typed to the declaration
|
|
94
|
+
* where it can be; anything else shows `input('<name>')`.
|
|
95
|
+
*/
|
|
96
|
+
export function exampleValue(f, symbol, invariant, connectorKey = "", action = "") {
|
|
97
|
+
const [name] = authoringField(f);
|
|
98
|
+
// The lookup table is keyed by the WIRE name (`addLabelIds[*]`), which is
|
|
99
|
+
// what `--resolve` and `buildConnectorInputs` both match on.
|
|
100
|
+
const wire = pyStr(pyOr(f.name, name));
|
|
101
|
+
const kind = classify(f, invariant);
|
|
102
|
+
if (kind === "lookup") {
|
|
103
|
+
const reference = referenceOf(f);
|
|
104
|
+
const names = strList(reference.lookupNames);
|
|
105
|
+
const aliases = byAliases(names);
|
|
106
|
+
const first = names.length ? names[0] : "id";
|
|
107
|
+
if (symbol) {
|
|
108
|
+
if (aliases.size)
|
|
109
|
+
return `lookup(${symbol}, '${wire}').${firstValue(aliases)}('…')`;
|
|
110
|
+
return `lookup(${symbol}, '${wire}').by('${first}', '…')`;
|
|
111
|
+
}
|
|
112
|
+
// NO DESCRIPTOR — a Generic CRUD expansion: the string form, generic `.by` only.
|
|
113
|
+
return `lookup('${connectorKey}', '${action}', '${wire}').by('${first}', '…')`;
|
|
114
|
+
}
|
|
115
|
+
const type = getStr(f, "type", "").toLowerCase();
|
|
116
|
+
const enumeration = f.enum;
|
|
117
|
+
if (pyTruthy(enumeration)) {
|
|
118
|
+
// The choice list is strings even when the field is not; fall back rather
|
|
119
|
+
// than emit something that does not compile.
|
|
120
|
+
const choice = enumValue(listOf(enumeration)[0]);
|
|
121
|
+
if (type === "boolean" || type === "bool") {
|
|
122
|
+
const lowered = choice.toLowerCase();
|
|
123
|
+
if (lowered === "true" || lowered === "false")
|
|
124
|
+
return lowered;
|
|
125
|
+
}
|
|
126
|
+
else if (type === "number" || type === "integer" || type === "float" || type === "double" || type === "long") {
|
|
127
|
+
if (pyFloatAccepts(choice))
|
|
128
|
+
return choice;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return pyJsonString(choice);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return `input('${leafName(name)}')`;
|
|
135
|
+
}
|
|
136
|
+
/** A compilable `connector(...)` call for this operation; events go to {@link eventExampleLines}. */
|
|
137
|
+
export function exampleLines(j, fields, symbol, invariant, v1def) {
|
|
138
|
+
const connectorKey = pyStr(pyOr(dictOf(j.connector).key, "<connector>"));
|
|
139
|
+
const operation = dictOf(j.operation);
|
|
140
|
+
const runtime = dictOf(j.runtime);
|
|
141
|
+
const nodeType = pyStr(pyOr(j.nodeType, ""));
|
|
142
|
+
const action = afterLast(nodeType, ".");
|
|
143
|
+
const step = pascalStep(action);
|
|
144
|
+
if (isEventNodeType(nodeType))
|
|
145
|
+
return eventExampleLines(j, symbol, connectorKey, action, step, v1def);
|
|
146
|
+
// WHICH REQUIRED SET: the descriptor's `Inputs` when a descriptor exists,
|
|
147
|
+
// marked with the SAME call the descriptor generator uses; else this
|
|
148
|
+
// module's own vocabulary, which the string form cannot fail on.
|
|
149
|
+
let exampleFields;
|
|
150
|
+
if (symbol) {
|
|
151
|
+
const entry = j;
|
|
152
|
+
const raw = (v1def ?? {});
|
|
153
|
+
// Marked with the SAME call the descriptor generator uses — it also merges
|
|
154
|
+
// the catalog's `reference` into a field whose authoring vocabulary lacks
|
|
155
|
+
// one — so the example puts a helper on exactly the fields that have one.
|
|
156
|
+
exampleFields = markLookupFields(entry, descriptorInputFields(entry, raw), invariant);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
exampleFields = fields;
|
|
160
|
+
}
|
|
161
|
+
const required = exampleFields.filter((f) => pyTruthy(f.required));
|
|
162
|
+
const schemaDynamic = pyTruthy(operation.objectFromDiscovery) ||
|
|
163
|
+
pyTruthy(dictOf(operation.schemaAction).parents) ||
|
|
164
|
+
pyTruthy(runtime.requiresConnectionForSchema);
|
|
165
|
+
const out = ["## Example", ""];
|
|
166
|
+
const pairs = required.map((f) => {
|
|
167
|
+
const [name, , wireName] = authoringField(f);
|
|
168
|
+
return [wireName ? f.name : name, exampleValue(f, symbol, invariant, connectorKey, action)];
|
|
169
|
+
});
|
|
170
|
+
// Import exactly what the rendered body uses.
|
|
171
|
+
const bodyUses = new Set(["connector"]);
|
|
172
|
+
if (pairs.some(([, v]) => v.includes("lookup(")))
|
|
173
|
+
bodyUses.add("lookup");
|
|
174
|
+
if (pairs.some(([, v]) => v.includes("input(")))
|
|
175
|
+
bodyUses.add("input");
|
|
176
|
+
const imported = sortedStrings(bodyUses).join(", ");
|
|
177
|
+
out.push("```ts");
|
|
178
|
+
// THE PACKAGE, not a relative path.
|
|
179
|
+
out.push(`import { ${imported} } from '${PACKAGE_NAME}';`);
|
|
180
|
+
let head;
|
|
181
|
+
if (symbol) {
|
|
182
|
+
const directory = schemaDynamic ? "connectors-local" : "connectors";
|
|
183
|
+
out.push(`import { ${symbol} } from './${directory}/${connectorKey}.ts';`);
|
|
184
|
+
out.push("");
|
|
185
|
+
head = `.step('${step}', connector(${symbol}, {`;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
out.push("");
|
|
189
|
+
head = `.step('${step}', connector('${connectorKey}', '${action}', {`;
|
|
190
|
+
}
|
|
191
|
+
out.push(head);
|
|
192
|
+
if (pairs.length)
|
|
193
|
+
out.push(...nestInputs(pairs));
|
|
194
|
+
const opts = [];
|
|
195
|
+
if (pyTruthy(runtime.requiresConnection))
|
|
196
|
+
opts.push(`connection: '${afterLast(connectorKey, "-")}'`);
|
|
197
|
+
if (pyTruthy(runtime.requiresFolderKey))
|
|
198
|
+
opts.push("folder: 'shared'");
|
|
199
|
+
if (!symbol && (operation.activityType === "Generic" || operation.activityType === "GenericExpanded")) {
|
|
200
|
+
opts.push(`object: '${pyStr(pyOr(operation.objectName, "<object>"))}'`);
|
|
201
|
+
}
|
|
202
|
+
const tail = "}" + (opts.length ? `, { ${opts.join(", ")} }` : "") + "))";
|
|
203
|
+
out.push(tail);
|
|
204
|
+
out.push("```");
|
|
205
|
+
out.push("");
|
|
206
|
+
if (schemaDynamic && symbol) {
|
|
207
|
+
// ONE ordering per page: the import fact stays; authoring comes first.
|
|
208
|
+
if (pyTruthy(operation.objectFromDiscovery)) {
|
|
209
|
+
out.push("The descriptor comes from `./connectors-local/` and this " +
|
|
210
|
+
"import resolves only after " +
|
|
211
|
+
`\`npx flow-sdk registry prepare ${connectorKey} ${action} ` +
|
|
212
|
+
"--object <name>` runs. That never blocks authoring: write " +
|
|
213
|
+
"the step first with the string form and " +
|
|
214
|
+
"`{ object: '<name-as-the-task-said-it>' }` — `check` " +
|
|
215
|
+
"names this exact prepare — then switch to this import.");
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
out.push("The descriptor comes from `./connectors-local/` and this " +
|
|
219
|
+
"import resolves only after " +
|
|
220
|
+
`\`npx flow-sdk registry prepare ${connectorKey} ${action}\` ` +
|
|
221
|
+
"runs. That never blocks authoring: the fields in this " +
|
|
222
|
+
"catalog are authorable immediately, and `check` flags any " +
|
|
223
|
+
"input outside them with this same command.");
|
|
224
|
+
}
|
|
225
|
+
out.push("");
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A compilable `onEvent(...)` / `waitForEvent(...)` call for a connector
|
|
231
|
+
* EVENT. A GENERIC event (`GenericTrigger`) watches ONE object the entry does
|
|
232
|
+
* not name, so the example shows the `object` option; a curated event shows
|
|
233
|
+
* `where` with the sidecar's event parameters.
|
|
234
|
+
*/
|
|
235
|
+
export function eventExampleLines(j, symbol, connectorKey, action, step, v1def) {
|
|
236
|
+
const operation = dictOf(j.operation);
|
|
237
|
+
const generic = operation.activityType === "GenericTrigger";
|
|
238
|
+
const start = getStr(j, "nodeType", "").startsWith(TRIGGER_PREFIX);
|
|
239
|
+
// The SIDECAR's event parameters: the raw input definition's names are not
|
|
240
|
+
// even legal object keys. No parameters, no `where`.
|
|
241
|
+
const params = listOf(pyOr(dictOf(pyOr(dictOf(v1def).eventParameters, {})).fields, []))
|
|
242
|
+
.map(dictOf)
|
|
243
|
+
.filter((f) => typeof f.name === "string" && !pyTruthy(f.hidden))
|
|
244
|
+
.map((f) => f.name);
|
|
245
|
+
const factory = start ? "onEvent" : "waitForEvent";
|
|
246
|
+
const out = ["## Example", "", "```ts"];
|
|
247
|
+
out.push(`import { ${factory} } from '${PACKAGE_NAME}';`);
|
|
248
|
+
if (symbol)
|
|
249
|
+
out.push(`import { ${symbol} } from './connectors/${connectorKey}.ts';`);
|
|
250
|
+
out.push("");
|
|
251
|
+
const opts = [];
|
|
252
|
+
let whereLines = [];
|
|
253
|
+
if (generic)
|
|
254
|
+
opts.push("object: '<Object>'");
|
|
255
|
+
else if (params.length) {
|
|
256
|
+
// NESTED, exactly as inputs are: the generated `…Where` interface splits a
|
|
257
|
+
// dotted parameter into an object (`channelData.channel.id` becomes
|
|
258
|
+
// `channelData: ConnectorValue<ChannelDataInput>`), so a flat key — quoted
|
|
259
|
+
// or not — is not a member of the type. Unnested, Teams'
|
|
260
|
+
// `channelData.channel.id` made the only two event examples in the library
|
|
261
|
+
// the only `## Example` fences in ~8,000 that did not parse.
|
|
262
|
+
whereLines = nestInputs(params.map((p) => [p, `'<${p}>'`])).map((line) => ` ${line}`);
|
|
263
|
+
}
|
|
264
|
+
opts.push(`connection: '${afterLast(connectorKey, "-")}'`);
|
|
265
|
+
opts.push("folder: 'shared'");
|
|
266
|
+
const lead = symbol
|
|
267
|
+
? `${factory}(${symbol}, {`
|
|
268
|
+
: `${factory}({ connector: '${connectorKey}', event: '${action}',`;
|
|
269
|
+
if (whereLines.length > 0) {
|
|
270
|
+
// Multi-line, like the action example, because the nested `where` is.
|
|
271
|
+
out.push(start ? `.trigger(${lead}` : `.step('${step}', ${lead}`);
|
|
272
|
+
out.push(" where: {");
|
|
273
|
+
out.push(...whereLines);
|
|
274
|
+
out.push(" },");
|
|
275
|
+
for (const option of opts)
|
|
276
|
+
out.push(` ${option},`);
|
|
277
|
+
out.push("}))");
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const call = symbol
|
|
281
|
+
? `${factory}(${symbol}, { ${opts.join(", ")} })`
|
|
282
|
+
: `${factory}({ connector: '${connectorKey}', event: '${action}', ${opts.join(", ")} })`;
|
|
283
|
+
out.push(start ? `.trigger(${call})` : `.step('${step}', ${call})`);
|
|
284
|
+
}
|
|
285
|
+
out.push("```");
|
|
286
|
+
out.push("");
|
|
287
|
+
if (generic) {
|
|
288
|
+
out.push("A GENERIC event: it fires for ONE object of the connection, so `object` " +
|
|
289
|
+
`names it. \`uip is triggers objects ${connectorKey} ` +
|
|
290
|
+
`${pyStr(pyOr(operation.eventOperation, operation.name, "<EVENT>"))} ` +
|
|
291
|
+
"--connection-id <id>` lists the objects the bound connection exposes.");
|
|
292
|
+
out.push("");
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
@@ -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,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[];
|