@uipath/maestro-builder-sdk 6.18.9 → 6.19.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 +185 -184
- package/dist/api-members.md +504 -473
- package/dist/bpmn/uipath-moddle.v1.json +5 -0
- package/dist/case/decompile-cli.js +2 -8
- package/dist/check.js +177 -650
- package/dist/core/actions.d.ts +119 -760
- package/dist/core/actions.js +0 -306
- package/dist/core/error-port.d.ts +6 -0
- package/dist/core/error-port.js +9 -0
- package/dist/core/node-classes.d.ts +4 -63
- package/dist/core/node-classes.js +0 -112
- package/dist/core/nodes/family.d.ts +36 -0
- package/dist/core/nodes/family.js +1 -0
- package/dist/core/nodes/node-type.d.ts +136 -0
- package/dist/core/nodes/node-type.js +1 -0
- package/dist/core/nodes/registry.d.ts +57 -0
- package/dist/core/nodes/registry.js +122 -0
- package/dist/core/nodes/versioned.d.ts +50 -0
- package/dist/core/nodes/versioned.js +46 -0
- package/dist/core/typed-raw-node.d.ts +13 -62
- package/dist/core/typed-raw-node.js +40 -154
- package/dist/decompile-cli.js +2 -9
- package/dist/decompile.js +92 -271
- package/dist/flow-definitions.d.ts +10 -0
- package/dist/flow-definitions.js +35 -0
- package/dist/flow-node-registry.d.ts +13 -0
- package/dist/flow-node-registry.js +19 -0
- package/dist/flow-node-type.d.ts +192 -0
- package/dist/flow-node-type.js +1 -0
- package/dist/flow-sdk.d.ts +7 -0
- package/dist/flow-sdk.js +8 -0
- package/dist/nodes/data-fabric/flow/check.d.ts +13 -0
- package/dist/nodes/data-fabric/flow/check.js +164 -0
- package/dist/nodes/data-fabric/flow/factories.d.ts +113 -0
- package/dist/nodes/data-fabric/flow/factories.js +134 -0
- package/dist/nodes/data-fabric/flow/family.d.ts +7 -0
- package/dist/nodes/data-fabric/flow/family.js +9 -0
- package/dist/nodes/data-fabric/flow/index.d.ts +8 -0
- package/dist/nodes/data-fabric/flow/index.js +8 -0
- package/dist/nodes/data-fabric/flow/raw.d.ts +32 -0
- package/dist/nodes/data-fabric/flow/raw.js +100 -0
- package/dist/nodes/data-fabric/flow/shared.d.ts +77 -0
- package/dist/nodes/data-fabric/flow/shared.js +174 -0
- package/dist/nodes/data-fabric/flow/spec.d.ts +238 -0
- package/dist/nodes/data-fabric/flow/spec.js +1 -0
- package/dist/nodes/data-fabric/flow/verbs.d.ts +29 -0
- package/dist/nodes/data-fabric/flow/verbs.js +239 -0
- package/dist/nodes/delay/flow/check.d.ts +16 -0
- package/dist/nodes/delay/flow/check.js +86 -0
- package/dist/nodes/delay/flow/factories.d.ts +28 -0
- package/dist/nodes/delay/flow/factories.js +38 -0
- package/dist/nodes/delay/flow/family.d.ts +3 -0
- package/dist/nodes/delay/flow/family.js +8 -0
- package/dist/nodes/delay/flow/index.d.ts +3 -0
- package/dist/nodes/delay/flow/index.js +3 -0
- package/dist/nodes/delay/flow/node-type.d.ts +13 -0
- package/dist/nodes/delay/flow/node-type.js +71 -0
- package/dist/nodes/delay/flow/spec.d.ts +43 -0
- package/dist/nodes/delay/flow/spec.js +16 -0
- package/dist/nodes/document/flow/factories.d.ts +27 -0
- package/dist/nodes/document/flow/factories.js +30 -0
- package/dist/nodes/document/flow/family.d.ts +3 -0
- package/dist/nodes/document/flow/family.js +7 -0
- package/dist/nodes/document/flow/index.d.ts +3 -0
- package/dist/nodes/document/flow/index.js +3 -0
- package/dist/nodes/document/flow/node-type.d.ts +14 -0
- package/dist/nodes/document/flow/node-type.js +150 -0
- package/dist/nodes/document/flow/spec.d.ts +65 -0
- package/dist/nodes/document/flow/spec.js +1 -0
- package/dist/nodes/mock/flow/factories.d.ts +51 -0
- package/dist/nodes/mock/flow/factories.js +47 -0
- package/dist/nodes/mock/flow/family.d.ts +3 -0
- package/dist/nodes/mock/flow/family.js +7 -0
- package/dist/nodes/mock/flow/index.d.ts +2 -0
- package/dist/nodes/mock/flow/index.js +2 -0
- package/dist/nodes/mock/flow/node-type.d.ts +11 -0
- package/dist/nodes/mock/flow/node-type.js +51 -0
- package/dist/nodes/script/flow/check.d.ts +19 -0
- package/dist/nodes/script/flow/check.js +49 -0
- package/dist/nodes/script/flow/factories.d.ts +14 -0
- package/dist/nodes/script/flow/factories.js +15 -0
- package/dist/nodes/script/flow/family.d.ts +3 -0
- package/dist/nodes/script/flow/family.js +8 -0
- package/dist/nodes/script/flow/index.d.ts +3 -0
- package/dist/nodes/script/flow/index.js +3 -0
- package/dist/nodes/script/flow/node-type.d.ts +7 -0
- package/dist/nodes/script/flow/node-type.js +125 -0
- package/dist/nodes/script/flow/spec.d.ts +52 -0
- package/dist/nodes/script/flow/spec.js +1 -0
- package/dist/nodes/transform/flow/check.d.ts +6 -0
- package/dist/nodes/transform/flow/check.js +229 -0
- package/dist/nodes/transform/flow/factories.d.ts +52 -0
- package/dist/nodes/transform/flow/factories.js +53 -0
- package/dist/nodes/transform/flow/family.d.ts +3 -0
- package/dist/nodes/transform/flow/family.js +8 -0
- package/dist/nodes/transform/flow/index.d.ts +3 -0
- package/dist/nodes/transform/flow/index.js +3 -0
- package/dist/nodes/transform/flow/node-type.d.ts +7 -0
- package/dist/nodes/transform/flow/node-type.js +244 -0
- package/dist/nodes/transform/flow/spec.d.ts +116 -0
- package/dist/nodes/transform/flow/spec.js +10 -0
- package/dist/raw-node-advice.d.ts +16 -0
- package/dist/raw-node-advice.js +36 -0
- package/dist/raw-node.d.ts +71 -0
- package/dist/raw-node.js +116 -0
- package/dist/registry/uip/launch.d.ts +11 -1
- package/dist/registry/uip/launch.js +50 -43
- package/dist/registry/uip/pipeline-front-door.d.ts +2 -0
- package/dist/registry/uip/pipeline-front-door.js +88 -0
- package/dist/serialize.js +138 -492
- package/package.json +2 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The node-type contract — one implementation per node type, per artifact, per
|
|
3
|
+
* version. docs/NODE_TYPE_ARCHITECTURE_DESIGN.md §4.
|
|
4
|
+
*
|
|
5
|
+
* A node type owns what one placed node means and how it looks in its artifact's
|
|
6
|
+
* file: serializing a spec, deserializing a serialized node back to its spec (the
|
|
7
|
+
* lift `decompile` runs), printing the spec as the factory call an author writes,
|
|
8
|
+
* checking it, and declaring its expressions, output and error port. The artifact
|
|
9
|
+
* keeps everything structural — ids, labels, layout, edges, definition dedupe — and
|
|
10
|
+
* lends the node type a narrow context for each job, never its own internals.
|
|
11
|
+
*
|
|
12
|
+
* The pattern is the one n8n (`INodeType`, `VersionedNodeType`), Jackson
|
|
13
|
+
* (`JsonSerializer` / `JsonDeserializer` with a context) and ESLint (a rule with a
|
|
14
|
+
* reporting `context`) use; §2 of the design maps the names.
|
|
15
|
+
*
|
|
16
|
+
* Generic over the artifact: `Serialized` is what `serialize` returns (Flow's
|
|
17
|
+
* `FlowNodeContribution`), and `Ctx` names the artifact's four contexts. Each
|
|
18
|
+
* artifact exports its own specialization (`FlowNodeType<Spec>` in
|
|
19
|
+
* `flow-node-type.ts`), so a contributor never writes these parameters.
|
|
20
|
+
*/
|
|
21
|
+
import type { TypeDesc } from '../expr.js';
|
|
22
|
+
/**
|
|
23
|
+
* Where a node type's definition comes from. `bundled`: a `<typeName>@<version>`
|
|
24
|
+
* entry the SDK ships, which every answer the definition can give (its error port,
|
|
25
|
+
* its declared inputs) is read from. `per-tenant`: built per tenant or per call —
|
|
26
|
+
* there is no bundled entry to ask, so the node type declares those answers itself.
|
|
27
|
+
*/
|
|
28
|
+
export type DefinitionSource = 'bundled' | 'per-tenant';
|
|
29
|
+
/**
|
|
30
|
+
* One place a spec carries a value the artifact evaluates against its scope.
|
|
31
|
+
* `value` is walked deeply for expressions; `code` is a script body whose
|
|
32
|
+
* references are checked although it is a plain string.
|
|
33
|
+
*/
|
|
34
|
+
export type ExprSite = {
|
|
35
|
+
readonly value: unknown;
|
|
36
|
+
} | {
|
|
37
|
+
readonly code: string;
|
|
38
|
+
};
|
|
39
|
+
/** A read of a node's output, as the output rules see it. */
|
|
40
|
+
export interface OutputRead {
|
|
41
|
+
/** The step name being read. */
|
|
42
|
+
node: string;
|
|
43
|
+
/** The reference as the author wrote it, e.g. `$vars.del.output`. */
|
|
44
|
+
ref: string;
|
|
45
|
+
/** The step whose expression contains the read. */
|
|
46
|
+
reader: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* What reading a node's output yields at run time.
|
|
50
|
+
*
|
|
51
|
+
* `none` keeps the diagnostic code of the rule it replaces
|
|
52
|
+
* (`DATAFABRIC_DELETE_HAS_NO_OUTPUT`, `MOCK_HAS_NO_OUTPUT`, …) and builds the
|
|
53
|
+
* message itself, so a port changes no diagnostic an author sees.
|
|
54
|
+
*/
|
|
55
|
+
export type OutputContract = {
|
|
56
|
+
readonly kind: 'none';
|
|
57
|
+
readonly code: string;
|
|
58
|
+
message(read: OutputRead): string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: 'fields';
|
|
61
|
+
readonly fields: Readonly<Record<string, TypeDesc>>;
|
|
62
|
+
readonly open?: boolean;
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'opaque';
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* A factory call as decompile prints it: the factory's name, its positional
|
|
68
|
+
* arguments, then an options object — every value already rendered as source
|
|
69
|
+
* text. An option whose source is `undefined` is left out, and an options object
|
|
70
|
+
* with nothing in it is not printed. The artifact renders the call
|
|
71
|
+
* (`connector('slack', 'send', { … }, { connection: 'x' })`), owning import
|
|
72
|
+
* tracking and formatting, so output stays byte-identical to the hand-written
|
|
73
|
+
* printers it replaces (design §7).
|
|
74
|
+
*/
|
|
75
|
+
export interface FactoryCall {
|
|
76
|
+
readonly factory: string;
|
|
77
|
+
readonly positional?: readonly string[];
|
|
78
|
+
readonly options?: ReadonlyArray<readonly [name: string, source: string | undefined]>;
|
|
79
|
+
}
|
|
80
|
+
/** The contexts an artifact lends its node types, one per job. */
|
|
81
|
+
export interface ArtifactContexts {
|
|
82
|
+
serialize: unknown;
|
|
83
|
+
deserialize: unknown;
|
|
84
|
+
print: unknown;
|
|
85
|
+
check: unknown;
|
|
86
|
+
familyCheck: unknown;
|
|
87
|
+
}
|
|
88
|
+
/** One node type at one version, for one artifact. See the module header. */
|
|
89
|
+
export interface NodeType<Spec, Serialized, Ctx extends ArtifactContexts> {
|
|
90
|
+
/** The spec discriminator, e.g. `'dataFabricRead'`. Unique within the artifact's registry. */
|
|
91
|
+
readonly kind: string;
|
|
92
|
+
/** The type name in the file, e.g. `'core.datafabric.read'`. Unique within the artifact's registry. */
|
|
93
|
+
readonly typeName: string;
|
|
94
|
+
/** The exact version this implementation serializes and recognizes. */
|
|
95
|
+
readonly version: string;
|
|
96
|
+
/** The public factory that produces this spec, e.g. `'dataFabricRead'`. */
|
|
97
|
+
readonly factory: string;
|
|
98
|
+
/** Where the definition comes from; decides who answers `errorPort` (see below). */
|
|
99
|
+
readonly definition: DefinitionSource;
|
|
100
|
+
/**
|
|
101
|
+
* Whether the node has an error port. A `bundled` type must omit it — the answer
|
|
102
|
+
* is the definition's, at this version. A `per-tenant` type must declare it,
|
|
103
|
+
* because there is no definition to ask. The registry refuses either mistake.
|
|
104
|
+
*/
|
|
105
|
+
readonly errorPort?: boolean | ((spec: Spec) => boolean);
|
|
106
|
+
/** Spec → the node's type-owned fields. The artifact still owns id, label, layout, edges and dedupe. */
|
|
107
|
+
serialize(spec: Spec, ctx: Ctx['serialize']): Serialized;
|
|
108
|
+
/** The lift: one serialized node → the spec it came from, or `undefined` when it is not this type's. */
|
|
109
|
+
deserialize(node: unknown, ctx: Ctx['deserialize']): Spec | undefined;
|
|
110
|
+
/** Spec → the factory call decompile prints. Omit it for the artifact's default, `factory(spec.inputs)`. */
|
|
111
|
+
print?(spec: Spec, ctx: Ctx['print']): FactoryCall;
|
|
112
|
+
/** Node-local rules, reported through `ctx`. Never throws for an authoring mistake. */
|
|
113
|
+
check?(spec: Spec, ctx: Ctx['check']): void;
|
|
114
|
+
/**
|
|
115
|
+
* Rules for an error handler the author attached to this node, run only once the
|
|
116
|
+
* node is known to have an error port (that decision is the artifact's, from the
|
|
117
|
+
* definition or `errorPort`). For a node whose port exists but whose failures a
|
|
118
|
+
* handler cannot usefully catch — Flow's plain HTTP request completes on a
|
|
119
|
+
* 4xx/5xx and publishes no envelope. Reported through `ctx` like `check`.
|
|
120
|
+
*/
|
|
121
|
+
checkErrorHandler?(spec: Spec, ctx: Ctx['check']): void;
|
|
122
|
+
/**
|
|
123
|
+
* Every authored value evaluated against the artifact's scope. Required: a type
|
|
124
|
+
* with none returns `[]`, by decision, because an omitted hook would silently
|
|
125
|
+
* switch off every reference rule for its steps.
|
|
126
|
+
*/
|
|
127
|
+
expressions(spec: Spec): Iterable<ExprSite>;
|
|
128
|
+
/** What reading this node's output yields. */
|
|
129
|
+
output(spec: Spec): OutputContract;
|
|
130
|
+
/**
|
|
131
|
+
* Whether this node type is the one for `spec`, when several share a kind (see
|
|
132
|
+
* VersionedNodeType.matches). On a single-version type only; a versioned type
|
|
133
|
+
* declares it once, on the VersionedNodeType.
|
|
134
|
+
*/
|
|
135
|
+
matches?(spec: Spec): boolean;
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The node-type registry — one per artifact, built from an explicit list of
|
|
3
|
+
* families (design §4.5).
|
|
4
|
+
*
|
|
5
|
+
* There is no registration as a side effect of importing a module: the artifact's
|
|
6
|
+
* registry module names its families, so load order cannot change what is
|
|
7
|
+
* registered and the architecture lint's no-cycle rule (FB003) keeps holding.
|
|
8
|
+
*
|
|
9
|
+
* Construction validates every invariant the pipeline relies on, and refuses with
|
|
10
|
+
* every problem at once rather than the first:
|
|
11
|
+
* - type names and family ids are unique, and so are kinds — except that
|
|
12
|
+
* several node types may share one kind when each declares `matches(spec)`;
|
|
13
|
+
* - each version's implementation agrees with the entry it is listed under
|
|
14
|
+
* (kind, type name, factory, version key) and the default version is listed;
|
|
15
|
+
* - a `bundled` type has the definition the artifact bundles at each version and
|
|
16
|
+
* declares no `errorPort` (the definition answers); a `per-tenant` type
|
|
17
|
+
* declares one (nothing else can);
|
|
18
|
+
* - no diagnostic code is claimed by two families.
|
|
19
|
+
*/
|
|
20
|
+
import type { ArtifactContexts } from './node-type.js';
|
|
21
|
+
import type { NodeFamily } from './family.js';
|
|
22
|
+
import { type VersionedNodeType } from './versioned.js';
|
|
23
|
+
/** A registered node type with the family that owns it. */
|
|
24
|
+
export interface Registered<Ctx extends ArtifactContexts> {
|
|
25
|
+
readonly family: NodeFamily<Ctx>;
|
|
26
|
+
readonly type: VersionedNodeType<unknown, unknown, Ctx>;
|
|
27
|
+
}
|
|
28
|
+
export interface NodeTypeRegistryOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Whether the artifact bundles `<typeName>@<version>`. Required to validate a
|
|
31
|
+
* `bundled` type; an artifact with no bundled definitions passes `() => false`.
|
|
32
|
+
*/
|
|
33
|
+
hasBundledDefinition(typeName: string, version: string): boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare class NodeTypeRegistry<Ctx extends ArtifactContexts> {
|
|
36
|
+
#private;
|
|
37
|
+
readonly artifact: string;
|
|
38
|
+
readonly families: readonly NodeFamily<Ctx>[];
|
|
39
|
+
/**
|
|
40
|
+
* @param artifact - The artifact's name, for messages (`'flow'`).
|
|
41
|
+
* @param families - Every family this artifact supports, in no significant order.
|
|
42
|
+
* @param options - What the artifact knows that the contract does not.
|
|
43
|
+
*/
|
|
44
|
+
constructor(artifact: string, families: readonly NodeFamily<Ctx>[], options: NodeTypeRegistryOptions);
|
|
45
|
+
/**
|
|
46
|
+
* The node type for a spec, by its kind, or undefined when the kind is not
|
|
47
|
+
* registered. When several types share the kind, the one whose `matches(spec)`
|
|
48
|
+
* holds — undefined when none does; two matching is an SDK bug and throws.
|
|
49
|
+
*/
|
|
50
|
+
byKind(kind: string, spec?: unknown): Registered<Ctx> | undefined;
|
|
51
|
+
/** Every node type registered for a kind (several when they share it), in registration order. */
|
|
52
|
+
typesOfKind(kind: string): readonly Registered<Ctx>[];
|
|
53
|
+
/** The node type for a type name in the file, or undefined when it is not registered. */
|
|
54
|
+
byTypeName(typeName: string): Registered<Ctx> | undefined;
|
|
55
|
+
/** Every registered kind, sorted. */
|
|
56
|
+
kinds(): string[];
|
|
57
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { asVersioned } from './versioned.js';
|
|
2
|
+
import { ownEntry } from '../own-entry.js';
|
|
3
|
+
export class NodeTypeRegistry {
|
|
4
|
+
artifact;
|
|
5
|
+
families;
|
|
6
|
+
#byKind = new Map();
|
|
7
|
+
#byTypeName = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* @param artifact - The artifact's name, for messages (`'flow'`).
|
|
10
|
+
* @param families - Every family this artifact supports, in no significant order.
|
|
11
|
+
* @param options - What the artifact knows that the contract does not.
|
|
12
|
+
*/
|
|
13
|
+
constructor(artifact, families, options) {
|
|
14
|
+
this.artifact = artifact;
|
|
15
|
+
this.families = families;
|
|
16
|
+
const problems = [];
|
|
17
|
+
const familyIds = new Set();
|
|
18
|
+
const codeOwner = new Map();
|
|
19
|
+
for (const family of families) {
|
|
20
|
+
if (familyIds.has(family.id))
|
|
21
|
+
problems.push(`family "${family.id}" is listed twice`);
|
|
22
|
+
familyIds.add(family.id);
|
|
23
|
+
for (const code of Object.keys(family.diagnostics)) {
|
|
24
|
+
const owner = codeOwner.get(code);
|
|
25
|
+
if (owner !== undefined && owner !== family.id) {
|
|
26
|
+
problems.push(`diagnostic code ${code} is claimed by both "${owner}" and "${family.id}"`);
|
|
27
|
+
}
|
|
28
|
+
codeOwner.set(code, family.id);
|
|
29
|
+
}
|
|
30
|
+
for (const listed of family.types) {
|
|
31
|
+
const type = asVersioned(listed);
|
|
32
|
+
const where = `${family.id}/${type.kind}`;
|
|
33
|
+
const sharing = this.#byKind.get(type.kind);
|
|
34
|
+
if (sharing && (!type.matches || sharing.some((other) => !other.type.matches))) {
|
|
35
|
+
problems.push(`kind "${type.kind}" is registered twice (${[...sharing, { family, type }].map((e) => `${e.family.id}/${e.type.typeName}`).join(' and ')}); node types that share a kind must each declare matches(spec)`);
|
|
36
|
+
}
|
|
37
|
+
const typeOwner = this.#byTypeName.get(type.typeName);
|
|
38
|
+
if (typeOwner) {
|
|
39
|
+
problems.push(`type name "${type.typeName}" is registered twice (${placeOf(typeOwner)} and ${where}); one VersionedNodeType owns every version of a type`);
|
|
40
|
+
}
|
|
41
|
+
const versions = Object.keys(type.versions);
|
|
42
|
+
if (versions.length === 0)
|
|
43
|
+
problems.push(`${where} registers no versions`);
|
|
44
|
+
if (ownEntry(type.versions, type.defaultVersion) === undefined) {
|
|
45
|
+
problems.push(`${where}: default version ${type.defaultVersion} is not registered (${versions.join(', ')})`);
|
|
46
|
+
}
|
|
47
|
+
for (const [key, impl] of Object.entries(type.versions)) {
|
|
48
|
+
problems.push(...implementationProblems(where, key, impl, type, options));
|
|
49
|
+
}
|
|
50
|
+
const entry = { family, type };
|
|
51
|
+
this.#byKind.set(type.kind, [...(sharing ?? []), entry]);
|
|
52
|
+
this.#byTypeName.set(type.typeName, entry);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (problems.length > 0) {
|
|
56
|
+
throw new Error(`internal SDK error: the ${artifact} node-type registry is inconsistent:\n`
|
|
57
|
+
+ problems.map((p) => ` - ${p}`).join('\n'));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The node type for a spec, by its kind, or undefined when the kind is not
|
|
62
|
+
* registered. When several types share the kind, the one whose `matches(spec)`
|
|
63
|
+
* holds — undefined when none does; two matching is an SDK bug and throws.
|
|
64
|
+
*/
|
|
65
|
+
byKind(kind, spec) {
|
|
66
|
+
const all = this.#byKind.get(kind);
|
|
67
|
+
if (!all)
|
|
68
|
+
return undefined;
|
|
69
|
+
if (all.length === 1)
|
|
70
|
+
return all[0];
|
|
71
|
+
const hits = all.filter((e) => e.type.matches(spec));
|
|
72
|
+
if (hits.length > 1) {
|
|
73
|
+
throw new Error(`internal SDK error: a ${kind} spec matches ${hits.map((h) => h.type.typeName).join(' and ')}; exactly one may.`);
|
|
74
|
+
}
|
|
75
|
+
return hits[0];
|
|
76
|
+
}
|
|
77
|
+
/** Every node type registered for a kind (several when they share it), in registration order. */
|
|
78
|
+
typesOfKind(kind) {
|
|
79
|
+
return this.#byKind.get(kind) ?? [];
|
|
80
|
+
}
|
|
81
|
+
/** The node type for a type name in the file, or undefined when it is not registered. */
|
|
82
|
+
byTypeName(typeName) {
|
|
83
|
+
return this.#byTypeName.get(typeName);
|
|
84
|
+
}
|
|
85
|
+
/** Every registered kind, sorted. */
|
|
86
|
+
kinds() {
|
|
87
|
+
return [...this.#byKind.keys()].sort();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Where a registered type lives, as the registry's messages name it: `<family>/<kind>`. */
|
|
91
|
+
function placeOf(entry) {
|
|
92
|
+
return `${entry.family.id}/${entry.type.kind}`;
|
|
93
|
+
}
|
|
94
|
+
/** What is wrong with one version's implementation, as registry problems. */
|
|
95
|
+
function implementationProblems(where, key, impl, type, options) {
|
|
96
|
+
const at = `${where}@${key}`;
|
|
97
|
+
const out = [];
|
|
98
|
+
if (impl.version !== key)
|
|
99
|
+
out.push(`${at}: listed under ${key} but declares version ${impl.version}`);
|
|
100
|
+
if (impl.kind !== type.kind)
|
|
101
|
+
out.push(`${at}: declares kind "${impl.kind}"`);
|
|
102
|
+
if (impl.typeName !== type.typeName)
|
|
103
|
+
out.push(`${at}: declares type name "${impl.typeName}"`);
|
|
104
|
+
if (impl.factory !== type.factory)
|
|
105
|
+
out.push(`${at}: declares factory "${impl.factory}", the type says "${type.factory}"`);
|
|
106
|
+
// Typed as required; checked here too, for an implementation the compiler did not see.
|
|
107
|
+
if (typeof impl.expressions !== 'function') {
|
|
108
|
+
out.push(`${at}: declares no expressions(spec); return [] when the type has no expression sites`);
|
|
109
|
+
}
|
|
110
|
+
if (impl.definition === 'bundled') {
|
|
111
|
+
if (!options.hasBundledDefinition(impl.typeName, impl.version)) {
|
|
112
|
+
out.push(`${at}: is bundled, but ${impl.typeName}@${impl.version} is not a bundled definition`);
|
|
113
|
+
}
|
|
114
|
+
if (impl.errorPort !== undefined) {
|
|
115
|
+
out.push(`${at}: is bundled, so its definition answers errorPort — remove the declaration (#1011)`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (impl.errorPort === undefined) {
|
|
119
|
+
out.push(`${at}: is per-tenant, so it must declare errorPort — there is no definition to ask`);
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versioned node types — one implementation per version (design §4.2, §7).
|
|
3
|
+
*
|
|
4
|
+
* A node type whose serialized shape changed between versions registers one
|
|
5
|
+
* {@link NodeType} per version under a {@link VersionedNodeType}, the way n8n's
|
|
6
|
+
* `VersionedNodeType` maps each version to its own implementation. A new version
|
|
7
|
+
* is a new entry (usually a subclass of the previous one), so adding it cannot
|
|
8
|
+
* change how a node at an older version serializes, deserializes or prints.
|
|
9
|
+
*/
|
|
10
|
+
import type { ArtifactContexts, NodeType } from './node-type.js';
|
|
11
|
+
export interface VersionedNodeType<Spec, Serialized, Ctx extends ArtifactContexts,
|
|
12
|
+
/** The implementation type: an artifact's own extension of NodeType, when it has one. */
|
|
13
|
+
Impl extends NodeType<Spec, Serialized, Ctx> = NodeType<Spec, Serialized, Ctx>> {
|
|
14
|
+
readonly kind: string;
|
|
15
|
+
readonly typeName: string;
|
|
16
|
+
readonly factory: string;
|
|
17
|
+
/** The version used when the author names none. Changing it is a breaking change. */
|
|
18
|
+
readonly defaultVersion: string;
|
|
19
|
+
/** Every registered version → its implementation. Keys equal each entry's `version`. */
|
|
20
|
+
readonly versions: Readonly<Record<string, Impl>>;
|
|
21
|
+
/**
|
|
22
|
+
* The version a spec needs when the author named none (`requested` undefined),
|
|
23
|
+
* e.g. a read that sets `resultMode` needs `core.datafabric.read@1.4`. Omit it
|
|
24
|
+
* and the default version is used. An explicit request is never second-guessed:
|
|
25
|
+
* the registry resolves it exactly or refuses it (see `resolveVersion`).
|
|
26
|
+
*/
|
|
27
|
+
select?(spec: Spec): string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether this node type is the one for `spec`, when several share a kind —
|
|
30
|
+
* one authoring kind can cover several node types (`transform` and its
|
|
31
|
+
* `variant`s, `http` and `{ managed }`). Required for each type of a shared
|
|
32
|
+
* kind, and exactly one of them must match a given spec; omit it for a kind
|
|
33
|
+
* this type has alone.
|
|
34
|
+
*/
|
|
35
|
+
matches?(spec: Spec): boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Either form a family may list: one version, or several. */
|
|
38
|
+
export type AnyNodeType<Ctx extends ArtifactContexts> = NodeType<any, any, Ctx> | VersionedNodeType<any, any, Ctx>;
|
|
39
|
+
/** True for a {@link VersionedNodeType}; a plain {@link NodeType} carries `version` instead. */
|
|
40
|
+
export declare function isVersioned<Ctx extends ArtifactContexts>(t: AnyNodeType<Ctx>): t is AnyNodeType<Ctx> & VersionedNodeType<unknown, unknown, Ctx>;
|
|
41
|
+
/** A single-version node type as the one-entry {@link VersionedNodeType} the registry stores. */
|
|
42
|
+
export declare function asVersioned<Ctx extends ArtifactContexts>(t: AnyNodeType<Ctx>): VersionedNodeType<unknown, unknown, Ctx>;
|
|
43
|
+
/**
|
|
44
|
+
* The exact version to emit for `spec`: the author's request when there is one —
|
|
45
|
+
* refused unless it is registered — else `select(spec)`, else the default.
|
|
46
|
+
* An unregistered request throws for the author, naming the step (`where`) and
|
|
47
|
+
* the registered versions; a `select` that returns an unregistered version is the
|
|
48
|
+
* node type's bug, not the author's, and throws as an internal SDK error.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveVersion<Spec, Ctx extends ArtifactContexts>(t: VersionedNodeType<Spec, unknown, Ctx>, spec: Spec, requested: string | undefined, where: string): NodeType<Spec, unknown, Ctx>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ownEntry } from '../own-entry.js';
|
|
2
|
+
/** True for a {@link VersionedNodeType}; a plain {@link NodeType} carries `version` instead. */
|
|
3
|
+
export function isVersioned(t) {
|
|
4
|
+
return 'versions' in t;
|
|
5
|
+
}
|
|
6
|
+
/** A single-version node type as the one-entry {@link VersionedNodeType} the registry stores. */
|
|
7
|
+
export function asVersioned(t) {
|
|
8
|
+
if (isVersioned(t))
|
|
9
|
+
return t;
|
|
10
|
+
const one = t;
|
|
11
|
+
return {
|
|
12
|
+
kind: one.kind,
|
|
13
|
+
typeName: one.typeName,
|
|
14
|
+
factory: one.factory,
|
|
15
|
+
defaultVersion: one.version,
|
|
16
|
+
versions: { [one.version]: one },
|
|
17
|
+
...(one.matches ? { matches: (spec) => one.matches(spec) } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The exact version to emit for `spec`: the author's request when there is one —
|
|
22
|
+
* refused unless it is registered — else `select(spec)`, else the default.
|
|
23
|
+
* An unregistered request throws for the author, naming the step (`where`) and
|
|
24
|
+
* the registered versions; a `select` that returns an unregistered version is the
|
|
25
|
+
* node type's bug, not the author's, and throws as an internal SDK error.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveVersion(t, spec, requested, where) {
|
|
28
|
+
const selected = requested === undefined ? t.select?.(spec) : undefined;
|
|
29
|
+
const version = requested ?? selected ?? t.defaultVersion;
|
|
30
|
+
const impl = ownEntry(t.versions, version);
|
|
31
|
+
if (!impl) {
|
|
32
|
+
const known = Object.keys(t.versions).sort().join(', ');
|
|
33
|
+
if (requested === undefined && selected === undefined) {
|
|
34
|
+
// A registered type's default is always registered; this is a type used before registration.
|
|
35
|
+
throw new Error(`internal SDK error: ${t.typeName}'s defaultVersion ${version} is not one of its versions (${known}), `
|
|
36
|
+
+ `used for ${where}. This is a bug in the node type, not in the flow; please report it.`);
|
|
37
|
+
}
|
|
38
|
+
if (requested === undefined) {
|
|
39
|
+
throw new Error(`internal SDK error: ${t.typeName}'s select() chose ${version} for ${where}, but the type registers only `
|
|
40
|
+
+ `${known}. This is a bug in the node type, not in the flow; please report it.`);
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`${where} requests ${t.typeName}@${version}, but this SDK registers only ${known}. `
|
|
43
|
+
+ 'Versions are exact — omit { version } to use the default, or request one listed here.');
|
|
44
|
+
}
|
|
45
|
+
return impl;
|
|
46
|
+
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Internal: what `check`
|
|
3
|
-
*
|
|
2
|
+
* Internal: what `check` says about a `rawNode` for a node type the SDK has a
|
|
3
|
+
* typed factory for, for the families not yet on the node-type registry. A
|
|
4
|
+
* registered type carries its own advice (FlowNodeType.rawNode; raw-node.ts asks
|
|
5
|
+
* the registry first), so a family's entries leave this table when it is ported.
|
|
4
6
|
* Not re-exported from the package entry point.
|
|
5
7
|
*/
|
|
6
|
-
/** The factory to use for one node type
|
|
8
|
+
/** The factory to use for one node type. */
|
|
7
9
|
export interface TypedFactory {
|
|
8
|
-
/** The typed spelling, as the
|
|
10
|
+
/** The typed spelling, as the warning names it. */
|
|
9
11
|
factory: string;
|
|
10
|
-
/**
|
|
11
|
-
* Every `<version>` with a `<nodeType>@<version>` entry in `core-definitions.json`.
|
|
12
|
-
* Listed here rather than read from the file because this module sits under
|
|
13
|
-
* `node-classes.ts`, which must not import `node:*`; `raw-node-typed-family.test.ts`
|
|
14
|
-
* pins the two equal.
|
|
15
|
-
*/
|
|
16
|
-
bundled: readonly string[];
|
|
17
12
|
}
|
|
18
13
|
/**
|
|
19
14
|
* Every node type the SDK authors as a STEP through a typed factory, with the
|
|
@@ -26,33 +21,10 @@ export interface TypedFactory {
|
|
|
26
21
|
* (`uipath.agent.resource.*`, attached to an agent). `decompile` keeps an
|
|
27
22
|
* orphaned one as a `rawNode`, and a warning on that round trip would be noise.
|
|
28
23
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* have a typed spelling.
|
|
24
|
+
* A REGISTERED family's types are not here: they carry the same advice
|
|
25
|
+
* themselves (the Data Fabric verbs, since Phase 3).
|
|
32
26
|
*/
|
|
33
27
|
export declare const TYPED_FACTORIES: Readonly<Record<string, TypedFactory>>;
|
|
34
|
-
/**
|
|
35
|
-
* Every `entityConfig` key the product reads or persists on a Data Fabric node,
|
|
36
|
-
* across the four verbs. flow-workbench develop `eed682f19`:
|
|
37
|
-
*
|
|
38
|
-
* - services `serialization/entity-vdo.ts` `interface EntityConfig` (:229-272):
|
|
39
|
-
* `entityName`, `resultMode`, `_recordLimit`, `_skip`, `_sort`,
|
|
40
|
-
* `_selectedFieldNames`, `_filters`, `_entityFields`, `_relatedFields`,
|
|
41
|
-
* `_folderKey`, `_entityKey`, `_resourceKey`, `_outputSchema`;
|
|
42
|
-
* `CreateEntityConfig` (:719) adds `fieldValues`; `UpdateEntityConfig` (:744)
|
|
43
|
-
* adds `recordSource`, `readEntityNodeId`, `recordId`, `fieldUpdates`.
|
|
44
|
-
* - canvas `properties-panel/EntityConfigField.tsx` `EntityConfigInputs`
|
|
45
|
-
* (:85-110) and `entity/useEntityPanelState.ts` `EntitySelectionPatch`
|
|
46
|
-
* (:248-270), which the panels persist on an entity pick:
|
|
47
|
-
* `_entityDisplayName`, `_choiceSets`, `_folderPath`, `_entitySubType`.
|
|
48
|
-
* - Create/Update/DeleteEntityConfigField.tsx declare nothing beyond these.
|
|
49
|
-
*
|
|
50
|
-
* One union rather than one set per verb: a key another verb reads is at worst
|
|
51
|
-
* ignored, and a per-verb split would refuse a canvas-written key on a verb
|
|
52
|
-
* whose panel happens not to declare it. The test pins every key the typed
|
|
53
|
-
* factories write to this set.
|
|
54
|
-
*/
|
|
55
|
-
export declare const DATAFABRIC_ENTITY_CONFIG_KEYS: ReadonlySet<string>;
|
|
56
28
|
/**
|
|
57
29
|
* A reminder, as a `warning`, that a `rawNode` stands in for a typed factory,
|
|
58
30
|
* or `undefined` for a type with no factory.
|
|
@@ -62,36 +34,15 @@ export declare const DATAFABRIC_ENTITY_CONFIG_KEYS: ReadonlySet<string>;
|
|
|
62
34
|
* related-path filter needs), and nothing checks factory coverage family by
|
|
63
35
|
* family. So the raw node keeps compiling at every version. The one failure
|
|
64
36
|
* the eval archive measured, an invented key the node never reads, is refused
|
|
65
|
-
* by
|
|
37
|
+
* by the node type's own `rawNode.inputProblem` instead (Data Fabric).
|
|
66
38
|
*
|
|
67
39
|
* @param nodeType - The definition's `nodeType`, as passed to `rawNode`.
|
|
68
40
|
* @returns The warning, or `undefined` for a type with no typed factory.
|
|
69
41
|
*/
|
|
70
42
|
export declare function typedFamilyRawNodeWarning(nodeType: string): string | undefined;
|
|
71
43
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* This is where the eval failure became possible. A raw node renders its inputs
|
|
76
|
-
* verbatim, and `core.datafabric.read@1.4`'s registry definition declares only
|
|
77
|
-
* `entityName` and `resultMode`, so `validate` cannot see any other key. Measured
|
|
78
|
-
* on the eval archive (2026-09-23, skill-flow-datafabric-native-contract-intake-pipeline):
|
|
79
|
-
* the agent wrote `_sortOptions: [{ fieldName, isDescending }]` in place of
|
|
80
|
-
* `_sort`, `check` printed "no issues", `validate` said Valid, and the query
|
|
81
|
-
* would have run unsorted. The allowed set is what the product reads
|
|
82
|
-
* ({@link DATAFABRIC_ENTITY_CONFIG_KEYS}), so `_entityFields` and the other
|
|
83
|
-
* canvas snapshots stay legal.
|
|
84
|
-
*
|
|
85
|
-
* Severity follows the version: at a bundled `<nodeType>@<version>` the key set
|
|
86
|
-
* is known, so the key is refused (`error`); at a version this SDK has not
|
|
87
|
-
* synced, a newer node could read a new key, so it is reported (`warning`).
|
|
88
|
-
*
|
|
89
|
-
* @param nodeType - The node's type.
|
|
90
|
-
* @param version - The version the node is emitted at.
|
|
91
|
-
* @param inputs - The node's inputs, before rendering.
|
|
92
|
-
* @returns The diagnostic, or `undefined` for a clean node or a non-Data-Fabric type.
|
|
44
|
+
* The RAW_NODE_TYPED_FAMILY sentence for `nodeType`, naming its typed `factory`
|
|
45
|
+
* and appending a family's `hint`. One spelling for the not-yet-ported table
|
|
46
|
+
* above and for a registered node type's own advice (raw-node.ts).
|
|
93
47
|
*/
|
|
94
|
-
export declare function
|
|
95
|
-
severity: 'error' | 'warning';
|
|
96
|
-
message: string;
|
|
97
|
-
} | undefined;
|
|
48
|
+
export declare function typedFactoryWarning(nodeType: string, factory: string, hint?: string): string;
|