@dudousxd/nestjs-catalog 0.19.0 → 0.20.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/catalog.pipeline.d.ts +154 -2
- package/dist/catalog.pipeline.js +371 -27
- package/dist/client.d.ts +2 -2
- package/dist/client.js +13 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -4
- package/package.json +1 -1
|
@@ -27,6 +27,39 @@ export type ConnectorKind = (typeof CONNECTOR_KINDS)[number];
|
|
|
27
27
|
* entirely. Anything narrowing a stored value narrows against *this*.
|
|
28
28
|
*/
|
|
29
29
|
export declare function isConnectorKind(value: unknown): value is ConnectorKind;
|
|
30
|
+
/**
|
|
31
|
+
* How the bytes behind a `file` or `s3` connector are read as records.
|
|
32
|
+
*
|
|
33
|
+
* A list rather than a loose string, for the reason {@link CONNECTOR_KINDS} is
|
|
34
|
+
* one: this used to be compared against string literals in the parser and
|
|
35
|
+
* spelled out again in a dropdown, and the two had no way to disagree loudly.
|
|
36
|
+
* The parser's chain also *ended* in JSON, so a format it did not recognise was
|
|
37
|
+
* not refused — it was read as JSON, and a spreadsheet handed to `JSON.parse`
|
|
38
|
+
* fails with a syntax error that names a byte offset rather than the format.
|
|
39
|
+
*
|
|
40
|
+
* `xlsx` is the odd one and is named for what it is: the only member whose
|
|
41
|
+
* payload is binary. The other three are text, and everything that reads them
|
|
42
|
+
* decodes the bytes first. Anything deciding something *per format* narrows
|
|
43
|
+
* against this and answers {@link unreachableSourceFormat}.
|
|
44
|
+
*/
|
|
45
|
+
export declare const SOURCE_FORMATS: readonly ["csv", "ndjson", "json", "xlsx"];
|
|
46
|
+
export type SourceFormat = (typeof SOURCE_FORMATS)[number];
|
|
47
|
+
/** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
|
|
48
|
+
export declare function isSourceFormat(value: unknown): value is SourceFormat;
|
|
49
|
+
/**
|
|
50
|
+
* The format that never compiles quietly.
|
|
51
|
+
*
|
|
52
|
+
* The {@link unreachableNodeKind} of formats, and it exists for the same reason:
|
|
53
|
+
* a member added to {@link SOURCE_FORMATS} without a branch in the parser should
|
|
54
|
+
* be a type error naming the file, not a connector that offers a format in a
|
|
55
|
+
* dropdown and then reads the file as JSON.
|
|
56
|
+
*
|
|
57
|
+
* It throws as well as failing to compile, because a connector config is JSON
|
|
58
|
+
* that outlives the build that wrote it: a `format` stored by a newer deployment
|
|
59
|
+
* and read by an older one is possible, and falling back to a default for it
|
|
60
|
+
* would be exactly the silent path this closes.
|
|
61
|
+
*/
|
|
62
|
+
export declare function unreachableSourceFormat(format: never, where: string): never;
|
|
30
63
|
/**
|
|
31
64
|
* What a published workflow runs as. **Not an authored object.**
|
|
32
65
|
*
|
|
@@ -1042,6 +1075,13 @@ export interface WorkflowSinkNode extends WorkflowNodeBase, ReusableNodeRef {
|
|
|
1042
1075
|
* answers are two documented shapes, and anything else fails the node naming
|
|
1043
1076
|
* the workflow, the version and the child run id.
|
|
1044
1077
|
*
|
|
1078
|
+
* All of the paragraph above describes the **envelope** mode, which is the
|
|
1079
|
+
* default and what every stored call node is. {@link callMode} names the other
|
|
1080
|
+
* one: a plain call sends {@link config} verbatim, so a workflow that has never
|
|
1081
|
+
* heard of this catalog can be called without being edited — and gives up the
|
|
1082
|
+
* ability to hand rows back, because it is told no key to stage them under. See
|
|
1083
|
+
* {@link WORKFLOW_CALL_MODES}.
|
|
1084
|
+
*
|
|
1045
1085
|
* ## `config` is not a credential store
|
|
1046
1086
|
*
|
|
1047
1087
|
* Named `config` rather than `input` so it travels the same path a source
|
|
@@ -1067,9 +1107,109 @@ export interface WorkflowCallNode extends WorkflowNodeBase {
|
|
|
1067
1107
|
* to *this* graph and is a number. This one identifies somebody else's code.
|
|
1068
1108
|
*/
|
|
1069
1109
|
callVersion: string;
|
|
1070
|
-
/**
|
|
1110
|
+
/**
|
|
1111
|
+
* Parameters the author typed. Where they land depends on
|
|
1112
|
+
* {@link WorkflowCallNode.callMode}: under `input` in an envelope call, and as
|
|
1113
|
+
* the whole of the child's payload in a plain one.
|
|
1114
|
+
*/
|
|
1071
1115
|
config: Record<string, unknown>;
|
|
1116
|
+
/**
|
|
1117
|
+
* Whether the child is handed a {@link WorkflowCallEnvelope} or the bare
|
|
1118
|
+
* {@link config}. See {@link WORKFLOW_CALL_MODES}, which is where the choice
|
|
1119
|
+
* is argued.
|
|
1120
|
+
*
|
|
1121
|
+
* Absent means `'envelope'`, which is what every call node stored before this
|
|
1122
|
+
* field existed is and what every one of them has always done. Read it through
|
|
1123
|
+
* {@link workflowCallMode} rather than defaulting it a second time — one
|
|
1124
|
+
* default, no second copy to drift.
|
|
1125
|
+
*/
|
|
1126
|
+
callMode?: WorkflowCallMode;
|
|
1072
1127
|
}
|
|
1128
|
+
/**
|
|
1129
|
+
* What a {@link WorkflowCallNode} puts on the wire, and the whole of it.
|
|
1130
|
+
*
|
|
1131
|
+
* ## Why there is a second mode at all
|
|
1132
|
+
*
|
|
1133
|
+
* The catalog could not call a workflow that does not know about the catalog.
|
|
1134
|
+
* A `call` node wraps the author's `config` in a {@link WorkflowCallEnvelope},
|
|
1135
|
+
* so a workflow that already exists — one registered years before this package,
|
|
1136
|
+
* whose body reads `data["proc"]` — receives `{catalog: {...}, input: {proc:
|
|
1137
|
+
* ...}}` and dies on the first key it looks for. The only repair available was
|
|
1138
|
+
* to edit the callee, which inverts the dependency exactly the wrong way round:
|
|
1139
|
+
* every workflow anybody wanted to call would have to start depending on this
|
|
1140
|
+
* package's contract, and a Python workflow registered in another repository
|
|
1141
|
+
* would have to be changed to be reachable from a graph.
|
|
1142
|
+
*
|
|
1143
|
+
* ## Why the nesting is not being loosened instead
|
|
1144
|
+
*
|
|
1145
|
+
* The envelope nests for one stated reason, which is on {@link
|
|
1146
|
+
* WorkflowCallEnvelope}: an author's parameter called `runId` must not be able
|
|
1147
|
+
* to shadow the run id. That reason is sound and it is not being weakened. It
|
|
1148
|
+
* simply does not reach the plain mode, because a plain call sends **no catalog
|
|
1149
|
+
* metadata at all** — there is no `runId`, no `nodeId`, no contract number on
|
|
1150
|
+
* the wire, so there is nothing a parameter could shadow. The flat payload is
|
|
1151
|
+
* not the envelope with its guard removed; it is a different, smaller promise.
|
|
1152
|
+
*
|
|
1153
|
+
* ## What the plain mode costs, which is not small
|
|
1154
|
+
*
|
|
1155
|
+
* No `runId` and no `nodeId` means the callee has no key to stage rows under.
|
|
1156
|
+
* Rows travel through the stage store addressed by `(runId, nodeId, batch)` —
|
|
1157
|
+
* see {@link WorkflowStageRef} — and a callee that was told neither cannot
|
|
1158
|
+
* write where the next node would read. So a plain call **cannot return rows to
|
|
1159
|
+
* the graph**, and that is not a convention anybody could follow more carefully:
|
|
1160
|
+
* it is arithmetic. `validateWorkflow` refuses a plain call with an outbound
|
|
1161
|
+
* edge for exactly this reason (`call-plain-has-output`), and its return value
|
|
1162
|
+
* is not read as a row count — see {@link readWorkflowCallOutput} for the shape
|
|
1163
|
+
* that is deliberately *not* consulted on this path.
|
|
1164
|
+
*
|
|
1165
|
+
* A plain call is therefore for its **effect**: run the thing, and let something
|
|
1166
|
+
* else in the graph produce what gets committed.
|
|
1167
|
+
*
|
|
1168
|
+
* ## Why a mode on the node rather than a second node kind or a boolean
|
|
1169
|
+
*
|
|
1170
|
+
* A boolean is the shape {@link WORKFLOW_PREDICATE_KINDS} argues against one
|
|
1171
|
+
* level down, and for the reason it gives: a `plain?: boolean` beside a future
|
|
1172
|
+
* third wire format is two optional flags whose combinations nobody defined, and
|
|
1173
|
+
* every reader invents its own rule for which wins. A closed list with an
|
|
1174
|
+
* exhaustiveness guard ({@link unreachableCallMode}) makes a third format a
|
|
1175
|
+
* compile error naming the files that have to answer for it.
|
|
1176
|
+
*
|
|
1177
|
+
* A second node *kind* was the other candidate and it is too big. The kind list
|
|
1178
|
+
* is deliberately small and every entry earns it by doing something no wiring
|
|
1179
|
+
* can express (see {@link WORKFLOW_NODE_KINDS}). A plain call does the same
|
|
1180
|
+
* thing a call does at the level the graph reasons about — it hands this
|
|
1181
|
+
* position to a workflow somebody else registered, pinned by name and version.
|
|
1182
|
+
* What differs is the payload. Splitting the kind would duplicate `callName`,
|
|
1183
|
+
* `callVersion`, `config`, the pin check, the picker, the plan entry and the
|
|
1184
|
+
* canvas node for a difference of one field, and every place that today writes
|
|
1185
|
+
* `node.kind === 'call'` would have to remember to write both — which is the
|
|
1186
|
+
* hand-maintained list going quiet that {@link NODE_KIND_IS_REUSABLE} exists to
|
|
1187
|
+
* stop.
|
|
1188
|
+
*/
|
|
1189
|
+
export declare const WORKFLOW_CALL_MODES: readonly ["envelope", "plain"];
|
|
1190
|
+
export type WorkflowCallMode = (typeof WORKFLOW_CALL_MODES)[number];
|
|
1191
|
+
/** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
|
|
1192
|
+
export declare function isWorkflowCallMode(value: unknown): value is WorkflowCallMode;
|
|
1193
|
+
/**
|
|
1194
|
+
* {@link unreachableNodeKind}, one level down, and for the identical reason.
|
|
1195
|
+
*
|
|
1196
|
+
* Every branch over {@link WorkflowCallMode} ends here, so a third wire format
|
|
1197
|
+
* added to the list without a rule for building its payload, hashing it,
|
|
1198
|
+
* validating it or reading its answer is a type error naming the file. It throws
|
|
1199
|
+
* as well, because a mode arrives as JSON out of a column and a build older than
|
|
1200
|
+
* the data is a thing that happens.
|
|
1201
|
+
*/
|
|
1202
|
+
export declare function unreachableCallMode(mode: never, where: string): never;
|
|
1203
|
+
/**
|
|
1204
|
+
* The mode this call node runs in, with the default applied once.
|
|
1205
|
+
*
|
|
1206
|
+
* Absent means `'envelope'` — that is what every node stored before the field
|
|
1207
|
+
* existed is, and reading it as anything else would silently change what a
|
|
1208
|
+
* deployment's graphs already do. One function so that the store, the runner,
|
|
1209
|
+
* the hash and the canvas cannot each carry their own `?? 'envelope'` and have
|
|
1210
|
+
* one of them drift.
|
|
1211
|
+
*/
|
|
1212
|
+
export declare function workflowCallMode(node: WorkflowCallNode): WorkflowCallMode;
|
|
1073
1213
|
/**
|
|
1074
1214
|
* The kinds of test an {@link WorkflowIfNode} can make.
|
|
1075
1215
|
*
|
|
@@ -2364,6 +2504,18 @@ export interface WorkflowCallOutput {
|
|
|
2364
2504
|
* schema for a workflow's output anywhere in the durable contract, and no way
|
|
2365
2505
|
* to reach one if there were. So the check is here, at the one moment the
|
|
2366
2506
|
* answer exists, and it names what it saw.
|
|
2507
|
+
*
|
|
2508
|
+
* ## Not called at all for a plain call, which is a decision and not an omission
|
|
2509
|
+
*
|
|
2510
|
+
* A plain call is handed no run id and no node id, so its callee could not have
|
|
2511
|
+
* staged anything under `(runId, nodeId, batch)` even if it wanted to. Running
|
|
2512
|
+
* this over its answer would be worse than pointless in both directions: a
|
|
2513
|
+
* callee that happens to return `{batches, rowCount}` meaning something else
|
|
2514
|
+
* entirely would have this graph go and read a stage that does not exist, and a
|
|
2515
|
+
* callee returning one of the two would fail the node over a key it was never
|
|
2516
|
+
* told about. So the plain path reports zero rows unconditionally and reads
|
|
2517
|
+
* nothing — see `WorkflowRunnerService.callOutput`, which is where that is
|
|
2518
|
+
* enforced rather than merely intended.
|
|
2367
2519
|
*/
|
|
2368
2520
|
export declare function readWorkflowCallOutput(value: unknown): WorkflowCallOutput | undefined;
|
|
2369
2521
|
/**
|
|
@@ -2489,7 +2641,7 @@ export interface CallableWorkflowBlock {
|
|
|
2489
2641
|
}
|
|
2490
2642
|
export declare function callableWorkflowBlock(ref: CallableWorkflowRef): CallableWorkflowBlock | undefined;
|
|
2491
2643
|
/** Every way a graph can be refused. Exported so a canvas can key off the code. */
|
|
2492
|
-
export declare const WORKFLOW_ISSUE_CODES: readonly ["empty", "invalid-node-id", "duplicate-node-id", "edge-endpoint-missing", "self-edge", "duplicate-edge", "cycle", "no-source", "source-has-input", "no-sink", "duplicate-sink-type", "sink-has-output", "unreachable", "dead-end", "transform-not-named", "call-not-named", "if-not-named", "if-threshold-invalid", "if-needs-one-input", "branch-not-labelled", "branch-on-plain-edge", "filter-predicate-invalid", "filter-narrows-unacknowledged", "filter-narrows-nothing", "version-pin-invalid"];
|
|
2644
|
+
export declare const WORKFLOW_ISSUE_CODES: readonly ["empty", "invalid-node-id", "duplicate-node-id", "edge-endpoint-missing", "self-edge", "duplicate-edge", "cycle", "no-source", "source-has-input", "no-sink", "duplicate-sink-type", "sink-has-output", "unreachable", "dead-end", "transform-not-named", "call-not-named", "call-plain-has-output", "if-not-named", "if-threshold-invalid", "if-needs-one-input", "branch-not-labelled", "branch-on-plain-edge", "filter-predicate-invalid", "filter-narrows-unacknowledged", "filter-narrows-nothing", "version-pin-invalid"];
|
|
2493
2645
|
export type WorkflowIssueCode = (typeof WORKFLOW_ISSUE_CODES)[number];
|
|
2494
2646
|
export interface WorkflowValidationIssue {
|
|
2495
2647
|
code: WorkflowIssueCode;
|
package/dist/catalog.pipeline.js
CHANGED
|
@@ -9,14 +9,19 @@
|
|
|
9
9
|
* systems each believing they decide when a load runs.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.REDACTED_SECRET = exports.CATALOG_PIPELINE_STORE = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_CALL_CONTRACT = exports.WORKFLOW_EXECUTION_MODES = exports.WORKFLOW_STATUSES = exports.WORKFLOW_BRANCH_LABELS = exports.NODE_KIND_IS_REUSABLE = exports.REUSABLE_NODE_KINDS = exports.WORKFLOW_FILTER_MAX_VALUES = exports.WORKFLOW_FILTER_MAX_DEPTH = exports.WORKFLOW_FILTER_COLUMN_PATTERN = exports.WORKFLOW_FILTER_OPERATORS = exports.WORKFLOW_FILTER_PREDICATE_KINDS = exports.WORKFLOW_PREDICATE_KINDS = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_COLUMN_GAP = exports.WORKFLOW_NODE_HEIGHT = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_SKIP_REASONS = exports.CODE_CONTEXT_CONTRACT = exports.TRANSFORM_RUNNER = exports.TRANSFORM_LANGUAGES = exports.CONNECTOR_KINDS = void 0;
|
|
12
|
+
exports.REDACTED_SECRET = exports.CATALOG_PIPELINE_STORE = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_CALL_CONTRACT = exports.WORKFLOW_EXECUTION_MODES = exports.WORKFLOW_STATUSES = exports.WORKFLOW_BRANCH_LABELS = exports.NODE_KIND_IS_REUSABLE = exports.REUSABLE_NODE_KINDS = exports.WORKFLOW_FILTER_MAX_VALUES = exports.WORKFLOW_FILTER_MAX_DEPTH = exports.WORKFLOW_FILTER_COLUMN_PATTERN = exports.WORKFLOW_FILTER_OPERATORS = exports.WORKFLOW_FILTER_PREDICATE_KINDS = exports.WORKFLOW_PREDICATE_KINDS = exports.WORKFLOW_CALL_MODES = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_COLUMN_GAP = exports.WORKFLOW_NODE_HEIGHT = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_SKIP_REASONS = exports.CODE_CONTEXT_CONTRACT = exports.TRANSFORM_RUNNER = exports.TRANSFORM_LANGUAGES = exports.SOURCE_FORMATS = exports.CONNECTOR_KINDS = void 0;
|
|
13
13
|
exports.isConnectorKind = isConnectorKind;
|
|
14
|
+
exports.isSourceFormat = isSourceFormat;
|
|
15
|
+
exports.unreachableSourceFormat = unreachableSourceFormat;
|
|
14
16
|
exports.isTransformLanguage = isTransformLanguage;
|
|
15
17
|
exports.isWorkflowSkipReason = isWorkflowSkipReason;
|
|
16
18
|
exports.isWorkflowNodeKind = isWorkflowNodeKind;
|
|
17
19
|
exports.unreachableNodeKind = unreachableNodeKind;
|
|
18
20
|
exports.workflowColumnX = workflowColumnX;
|
|
19
21
|
exports.workflowRowY = workflowRowY;
|
|
22
|
+
exports.isWorkflowCallMode = isWorkflowCallMode;
|
|
23
|
+
exports.unreachableCallMode = unreachableCallMode;
|
|
24
|
+
exports.workflowCallMode = workflowCallMode;
|
|
20
25
|
exports.isWorkflowPredicateKind = isWorkflowPredicateKind;
|
|
21
26
|
exports.unreachablePredicateKind = unreachablePredicateKind;
|
|
22
27
|
exports.isWorkflowIfPredicate = isWorkflowIfPredicate;
|
|
@@ -93,6 +98,57 @@ exports.CONNECTOR_KINDS = [
|
|
|
93
98
|
function isConnectorKind(value) {
|
|
94
99
|
return exports.CONNECTOR_KINDS.some((kind) => kind === value);
|
|
95
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* How the bytes behind a `file` or `s3` connector are read as records.
|
|
103
|
+
*
|
|
104
|
+
* A list rather than a loose string, for the reason {@link CONNECTOR_KINDS} is
|
|
105
|
+
* one: this used to be compared against string literals in the parser and
|
|
106
|
+
* spelled out again in a dropdown, and the two had no way to disagree loudly.
|
|
107
|
+
* The parser's chain also *ended* in JSON, so a format it did not recognise was
|
|
108
|
+
* not refused — it was read as JSON, and a spreadsheet handed to `JSON.parse`
|
|
109
|
+
* fails with a syntax error that names a byte offset rather than the format.
|
|
110
|
+
*
|
|
111
|
+
* `xlsx` is the odd one and is named for what it is: the only member whose
|
|
112
|
+
* payload is binary. The other three are text, and everything that reads them
|
|
113
|
+
* decodes the bytes first. Anything deciding something *per format* narrows
|
|
114
|
+
* against this and answers {@link unreachableSourceFormat}.
|
|
115
|
+
*/
|
|
116
|
+
exports.SOURCE_FORMATS = [
|
|
117
|
+
/** Delimited text with a header row. The delimiter is configurable. */
|
|
118
|
+
'csv',
|
|
119
|
+
/** One JSON value per line. */
|
|
120
|
+
'ndjson',
|
|
121
|
+
/** A JSON document, optionally with the array nested in an envelope. */
|
|
122
|
+
'json',
|
|
123
|
+
/**
|
|
124
|
+
* A spreadsheet workbook — binary, and the only member that is.
|
|
125
|
+
*
|
|
126
|
+
* Named for the modern extension, but the reader identifies the container
|
|
127
|
+
* from its own bytes, so the legacy `.xls` and the macro-enabled `.xlsm` are
|
|
128
|
+
* this format too rather than three names for one decision.
|
|
129
|
+
*/
|
|
130
|
+
'xlsx',
|
|
131
|
+
];
|
|
132
|
+
/** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
|
|
133
|
+
function isSourceFormat(value) {
|
|
134
|
+
return exports.SOURCE_FORMATS.some((format) => format === value);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The format that never compiles quietly.
|
|
138
|
+
*
|
|
139
|
+
* The {@link unreachableNodeKind} of formats, and it exists for the same reason:
|
|
140
|
+
* a member added to {@link SOURCE_FORMATS} without a branch in the parser should
|
|
141
|
+
* be a type error naming the file, not a connector that offers a format in a
|
|
142
|
+
* dropdown and then reads the file as JSON.
|
|
143
|
+
*
|
|
144
|
+
* It throws as well as failing to compile, because a connector config is JSON
|
|
145
|
+
* that outlives the build that wrote it: a `format` stored by a newer deployment
|
|
146
|
+
* and read by an older one is possible, and falling back to a default for it
|
|
147
|
+
* would be exactly the silent path this closes.
|
|
148
|
+
*/
|
|
149
|
+
function unreachableSourceFormat(format, where) {
|
|
150
|
+
throw new Error(`${where} does not handle a source format of ${JSON.stringify(format)}. The format list and every decision made per format are meant to move together.`);
|
|
151
|
+
}
|
|
96
152
|
/**
|
|
97
153
|
* TypeScript is Node's own type stripping, so it costs no compiler and no build
|
|
98
154
|
* step — and types are erased, never checked. A transform with a wrong type
|
|
@@ -321,6 +377,109 @@ function workflowColumnX(column) {
|
|
|
321
377
|
function workflowRowY(row) {
|
|
322
378
|
return row * (exports.WORKFLOW_NODE_HEIGHT + exports.WORKFLOW_ROW_GAP);
|
|
323
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* What a {@link WorkflowCallNode} puts on the wire, and the whole of it.
|
|
382
|
+
*
|
|
383
|
+
* ## Why there is a second mode at all
|
|
384
|
+
*
|
|
385
|
+
* The catalog could not call a workflow that does not know about the catalog.
|
|
386
|
+
* A `call` node wraps the author's `config` in a {@link WorkflowCallEnvelope},
|
|
387
|
+
* so a workflow that already exists — one registered years before this package,
|
|
388
|
+
* whose body reads `data["proc"]` — receives `{catalog: {...}, input: {proc:
|
|
389
|
+
* ...}}` and dies on the first key it looks for. The only repair available was
|
|
390
|
+
* to edit the callee, which inverts the dependency exactly the wrong way round:
|
|
391
|
+
* every workflow anybody wanted to call would have to start depending on this
|
|
392
|
+
* package's contract, and a Python workflow registered in another repository
|
|
393
|
+
* would have to be changed to be reachable from a graph.
|
|
394
|
+
*
|
|
395
|
+
* ## Why the nesting is not being loosened instead
|
|
396
|
+
*
|
|
397
|
+
* The envelope nests for one stated reason, which is on {@link
|
|
398
|
+
* WorkflowCallEnvelope}: an author's parameter called `runId` must not be able
|
|
399
|
+
* to shadow the run id. That reason is sound and it is not being weakened. It
|
|
400
|
+
* simply does not reach the plain mode, because a plain call sends **no catalog
|
|
401
|
+
* metadata at all** — there is no `runId`, no `nodeId`, no contract number on
|
|
402
|
+
* the wire, so there is nothing a parameter could shadow. The flat payload is
|
|
403
|
+
* not the envelope with its guard removed; it is a different, smaller promise.
|
|
404
|
+
*
|
|
405
|
+
* ## What the plain mode costs, which is not small
|
|
406
|
+
*
|
|
407
|
+
* No `runId` and no `nodeId` means the callee has no key to stage rows under.
|
|
408
|
+
* Rows travel through the stage store addressed by `(runId, nodeId, batch)` —
|
|
409
|
+
* see {@link WorkflowStageRef} — and a callee that was told neither cannot
|
|
410
|
+
* write where the next node would read. So a plain call **cannot return rows to
|
|
411
|
+
* the graph**, and that is not a convention anybody could follow more carefully:
|
|
412
|
+
* it is arithmetic. `validateWorkflow` refuses a plain call with an outbound
|
|
413
|
+
* edge for exactly this reason (`call-plain-has-output`), and its return value
|
|
414
|
+
* is not read as a row count — see {@link readWorkflowCallOutput} for the shape
|
|
415
|
+
* that is deliberately *not* consulted on this path.
|
|
416
|
+
*
|
|
417
|
+
* A plain call is therefore for its **effect**: run the thing, and let something
|
|
418
|
+
* else in the graph produce what gets committed.
|
|
419
|
+
*
|
|
420
|
+
* ## Why a mode on the node rather than a second node kind or a boolean
|
|
421
|
+
*
|
|
422
|
+
* A boolean is the shape {@link WORKFLOW_PREDICATE_KINDS} argues against one
|
|
423
|
+
* level down, and for the reason it gives: a `plain?: boolean` beside a future
|
|
424
|
+
* third wire format is two optional flags whose combinations nobody defined, and
|
|
425
|
+
* every reader invents its own rule for which wins. A closed list with an
|
|
426
|
+
* exhaustiveness guard ({@link unreachableCallMode}) makes a third format a
|
|
427
|
+
* compile error naming the files that have to answer for it.
|
|
428
|
+
*
|
|
429
|
+
* A second node *kind* was the other candidate and it is too big. The kind list
|
|
430
|
+
* is deliberately small and every entry earns it by doing something no wiring
|
|
431
|
+
* can express (see {@link WORKFLOW_NODE_KINDS}). A plain call does the same
|
|
432
|
+
* thing a call does at the level the graph reasons about — it hands this
|
|
433
|
+
* position to a workflow somebody else registered, pinned by name and version.
|
|
434
|
+
* What differs is the payload. Splitting the kind would duplicate `callName`,
|
|
435
|
+
* `callVersion`, `config`, the pin check, the picker, the plan entry and the
|
|
436
|
+
* canvas node for a difference of one field, and every place that today writes
|
|
437
|
+
* `node.kind === 'call'` would have to remember to write both — which is the
|
|
438
|
+
* hand-maintained list going quiet that {@link NODE_KIND_IS_REUSABLE} exists to
|
|
439
|
+
* stop.
|
|
440
|
+
*/
|
|
441
|
+
exports.WORKFLOW_CALL_MODES = [
|
|
442
|
+
/**
|
|
443
|
+
* The child is handed a {@link WorkflowCallEnvelope}: the catalog's metadata
|
|
444
|
+
* under `catalog`, the author's parameters under `input`. The callee can stage
|
|
445
|
+
* rows back for the graph, and it has to have been written for this catalog.
|
|
446
|
+
*/
|
|
447
|
+
'envelope',
|
|
448
|
+
/**
|
|
449
|
+
* The child is handed {@link WorkflowCallNode.config} verbatim, with nothing
|
|
450
|
+
* added and nothing wrapped. The callee needs to know nothing about the
|
|
451
|
+
* catalog — and cannot return rows to it.
|
|
452
|
+
*/
|
|
453
|
+
'plain',
|
|
454
|
+
];
|
|
455
|
+
/** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
|
|
456
|
+
function isWorkflowCallMode(value) {
|
|
457
|
+
return exports.WORKFLOW_CALL_MODES.some((mode) => mode === value);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* {@link unreachableNodeKind}, one level down, and for the identical reason.
|
|
461
|
+
*
|
|
462
|
+
* Every branch over {@link WorkflowCallMode} ends here, so a third wire format
|
|
463
|
+
* added to the list without a rule for building its payload, hashing it,
|
|
464
|
+
* validating it or reading its answer is a type error naming the file. It throws
|
|
465
|
+
* as well, because a mode arrives as JSON out of a column and a build older than
|
|
466
|
+
* the data is a thing that happens.
|
|
467
|
+
*/
|
|
468
|
+
function unreachableCallMode(mode, where) {
|
|
469
|
+
throw new Error(`${where} has no rule for the call mode ${JSON.stringify(mode)}. It was added to WORKFLOW_CALL_MODES without teaching this code what to put on the wire for it, and guessing would send a workflow a payload nobody authored.`);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* The mode this call node runs in, with the default applied once.
|
|
473
|
+
*
|
|
474
|
+
* Absent means `'envelope'` — that is what every node stored before the field
|
|
475
|
+
* existed is, and reading it as anything else would silently change what a
|
|
476
|
+
* deployment's graphs already do. One function so that the store, the runner,
|
|
477
|
+
* the hash and the canvas cannot each carry their own `?? 'envelope'` and have
|
|
478
|
+
* one of them drift.
|
|
479
|
+
*/
|
|
480
|
+
function workflowCallMode(node) {
|
|
481
|
+
return node.callMode ?? 'envelope';
|
|
482
|
+
}
|
|
324
483
|
/**
|
|
325
484
|
* The kinds of test an {@link WorkflowIfNode} can make.
|
|
326
485
|
*
|
|
@@ -1169,6 +1328,18 @@ exports.WORKFLOW_CALL_CONTRACT = 1;
|
|
|
1169
1328
|
* schema for a workflow's output anywhere in the durable contract, and no way
|
|
1170
1329
|
* to reach one if there were. So the check is here, at the one moment the
|
|
1171
1330
|
* answer exists, and it names what it saw.
|
|
1331
|
+
*
|
|
1332
|
+
* ## Not called at all for a plain call, which is a decision and not an omission
|
|
1333
|
+
*
|
|
1334
|
+
* A plain call is handed no run id and no node id, so its callee could not have
|
|
1335
|
+
* staged anything under `(runId, nodeId, batch)` even if it wanted to. Running
|
|
1336
|
+
* this over its answer would be worse than pointless in both directions: a
|
|
1337
|
+
* callee that happens to return `{batches, rowCount}` meaning something else
|
|
1338
|
+
* entirely would have this graph go and read a stage that does not exist, and a
|
|
1339
|
+
* callee returning one of the two would fail the node over a key it was never
|
|
1340
|
+
* told about. So the plain path reports zero rows unconditionally and reads
|
|
1341
|
+
* nothing — see `WorkflowRunnerService.callOutput`, which is where that is
|
|
1342
|
+
* enforced rather than merely intended.
|
|
1172
1343
|
*/
|
|
1173
1344
|
function readWorkflowCallOutput(value) {
|
|
1174
1345
|
if (typeof value !== 'object' || value === null)
|
|
@@ -1223,6 +1394,13 @@ exports.WORKFLOW_ISSUE_CODES = [
|
|
|
1223
1394
|
'dead-end',
|
|
1224
1395
|
'transform-not-named',
|
|
1225
1396
|
'call-not-named',
|
|
1397
|
+
/**
|
|
1398
|
+
* A plain call wired into something. See {@link WORKFLOW_CALL_MODES}: a plain
|
|
1399
|
+
* call is told no run id and no node id, so it has nowhere to stage rows and
|
|
1400
|
+
* always passes on none — and every node that can sit downstream of a call
|
|
1401
|
+
* consumes rows and nothing else.
|
|
1402
|
+
*/
|
|
1403
|
+
'call-plain-has-output',
|
|
1226
1404
|
'if-not-named',
|
|
1227
1405
|
'if-threshold-invalid',
|
|
1228
1406
|
'if-needs-one-input',
|
|
@@ -1279,11 +1457,17 @@ function validateWorkflow(graph) {
|
|
|
1279
1457
|
return issues;
|
|
1280
1458
|
const { outgoing, incoming } = buildAdjacency(nodes, edges);
|
|
1281
1459
|
const originators = nodes.filter(originatesRows);
|
|
1460
|
+
// Deliberately a *different* set from `originators` — see `runsWithoutInput`.
|
|
1461
|
+
const roots = nodes.filter(runsWithoutInput);
|
|
1282
1462
|
const sinks = nodes.filter((node) => node.kind === 'sink');
|
|
1283
1463
|
checkNodeWiring(nodes, incoming, outgoing, issues);
|
|
1284
1464
|
checkEndpoints(originators, sinks, issues);
|
|
1285
1465
|
checkBranches(edges, byId, issues);
|
|
1286
|
-
|
|
1466
|
+
checkPlainCallOutputs(nodes, outgoing, byId, issues);
|
|
1467
|
+
// `roots` rather than `originators`, because this walks the graph forwards to
|
|
1468
|
+
// find which sinks a filter can narrow and a plain call is a perfectly
|
|
1469
|
+
// ordinary ancestor of nothing at all — it just never contributes rows.
|
|
1470
|
+
checkFilterNarrowing({ nodes, edges }, roots, outgoing, issues);
|
|
1287
1471
|
const looped = findCycle(nodes, incoming, outgoing);
|
|
1288
1472
|
if (looped) {
|
|
1289
1473
|
issues.push({
|
|
@@ -1295,27 +1479,127 @@ function validateWorkflow(graph) {
|
|
|
1295
1479
|
// only unreachable *because* of the cycle, which points at the wrong boxes.
|
|
1296
1480
|
return issues;
|
|
1297
1481
|
}
|
|
1298
|
-
checkReachability(nodes,
|
|
1482
|
+
checkReachability(nodes, roots, sinks, incoming, outgoing, issues);
|
|
1299
1483
|
return issues;
|
|
1300
1484
|
}
|
|
1485
|
+
/**
|
|
1486
|
+
* A plain call may not feed anything, and this is where that is refused.
|
|
1487
|
+
*
|
|
1488
|
+
* ## The rule, stated once
|
|
1489
|
+
*
|
|
1490
|
+
* **A call node in `plain` mode must have no outbound edge.** Not "must not feed
|
|
1491
|
+
* a sink", not "must not be the only thing feeding a sink" — no outbound edge at
|
|
1492
|
+
* all, and the reason it collapses that far is that there is no weaker version
|
|
1493
|
+
* of it that means anything. Every node kind that can sit downstream of a call —
|
|
1494
|
+
* transform, if, filter, sink — consumes rows and *only* rows. There is no
|
|
1495
|
+
* ordering-only wire in this model. So "a plain call with downstream nodes
|
|
1496
|
+
* expecting rows" and "a plain call with an outbound edge" are the same set.
|
|
1497
|
+
*
|
|
1498
|
+
* ## How it lands against the rest of the validator
|
|
1499
|
+
*
|
|
1500
|
+
* Three rules had to move for this one to be statable, and each moved in a way
|
|
1501
|
+
* that is narrower than it looks:
|
|
1502
|
+
*
|
|
1503
|
+
* - **`no-source`.** A plain call is no longer something that "reads": see
|
|
1504
|
+
* {@link originatesRows}. Without that, a graph of `plain call → sink` would
|
|
1505
|
+
* have passed the check that a graph has something producing rows, and then
|
|
1506
|
+
* committed an empty snapshot over whatever was live. It is refused here
|
|
1507
|
+
* first, and would be refused by `no-source` even if this check were deleted.
|
|
1508
|
+
* - **`dead-end` — every path reaches the sink.** A plain call reaches no sink
|
|
1509
|
+
* by construction, so it is exempt, and the exemption is exactly one node
|
|
1510
|
+
* wide: nothing can be *behind* a plain call, because a plain call has no
|
|
1511
|
+
* outbound edge, so no other node's route to the sink can run through one.
|
|
1512
|
+
* The message `dead-end` carries is "it would be computed and thrown away",
|
|
1513
|
+
* and that is precisely what a plain call is not — its effect is the point,
|
|
1514
|
+
* and it has already happened by the time the sink commits.
|
|
1515
|
+
* - **the one-sink rule.** Untouched. A graph still needs a sink and still needs
|
|
1516
|
+
* something that originates rows, and a plain call is now neither, so plain
|
|
1517
|
+
* calls cannot be a graph on their own — the rows come from a source or from
|
|
1518
|
+
* an envelope call, exactly as before.
|
|
1519
|
+
*
|
|
1520
|
+
* What a legal plain call looks like, then: `source → sink` with `source →
|
|
1521
|
+
* plainCall` beside it — the effect runs after the source and the load commits
|
|
1522
|
+
* the source's rows — or a plain call with nothing wired to it at all, which
|
|
1523
|
+
* runs at some point in the topological order and is reported like any other
|
|
1524
|
+
* node. Wiring a source into a plain call that is the source's *only* outbound
|
|
1525
|
+
* edge is still refused, by `dead-end`, pointed at the source: those rows really
|
|
1526
|
+
* would be fetched and dropped.
|
|
1527
|
+
*/
|
|
1528
|
+
function checkPlainCallOutputs(nodes, outgoing, byId, issues) {
|
|
1529
|
+
for (const node of nodes) {
|
|
1530
|
+
if (node.kind !== 'call' || workflowCallMode(node) !== 'plain')
|
|
1531
|
+
continue;
|
|
1532
|
+
const fed = outgoing.get(node.id) ?? [];
|
|
1533
|
+
if (fed.length === 0)
|
|
1534
|
+
continue;
|
|
1535
|
+
issues.push({
|
|
1536
|
+
code: 'call-plain-has-output',
|
|
1537
|
+
nodeIds: [node.id, ...fed],
|
|
1538
|
+
message: `Call node "${node.name}" (${node.id}) is a plain call and is wired into ${listNodes(fed, byId)}, which cannot work. A plain call sends this node's parameters to ${node.callName || 'the workflow it calls'} verbatim and nothing else — no run id and no node id — so the workflow it calls is told no key to write rows under and this node always passes on zero. Everything downstream would run on an empty input and the load would commit an empty snapshot without anything failing. Unwire it: a plain call is run for its effect, and something else in this graph produces what gets committed. If the workflow you are calling is meant to produce rows for this graph, it needs the envelope instead, which is what tells it where to put them.`,
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
/** `"a" (n1) and "b" (n2)`, for a message that has to name several boxes. */
|
|
1543
|
+
function listNodes(ids, byId) {
|
|
1544
|
+
return ids
|
|
1545
|
+
.map((id) => {
|
|
1546
|
+
const node = byId.get(id);
|
|
1547
|
+
return node ? `"${node.name}" (${id})` : `"${id}"`;
|
|
1548
|
+
})
|
|
1549
|
+
.join(' and ');
|
|
1550
|
+
}
|
|
1301
1551
|
/**
|
|
1302
1552
|
* Whether a node can produce rows without anything wired into it.
|
|
1303
1553
|
*
|
|
1304
|
-
* A source obviously can.
|
|
1305
|
-
* `call` kind changes rather than extends: the workflow it hands off to
|
|
1306
|
-
* itself read from a system, so a graph of `call → sink` is a real pipeline
|
|
1307
|
-
* refusing it for having "no source" would be false. What is not weakened is
|
|
1554
|
+
* A source obviously can. An **envelope call** node can too, and this is the one
|
|
1555
|
+
* rule the `call` kind changes rather than extends: the workflow it hands off to
|
|
1556
|
+
* may itself read from a system, so a graph of `call → sink` is a real pipeline
|
|
1557
|
+
* and refusing it for having "no source" would be false. What is not weakened is
|
|
1308
1558
|
* that a graph still needs *something* that originates rows and *something*
|
|
1309
1559
|
* that commits them — a graph of transforms alone is still refused.
|
|
1310
1560
|
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1561
|
+
* A **plain** call is not one of them, and that is the load-bearing half of this
|
|
1562
|
+
* function now. A plain call is told no run id and no node id, so it has no key
|
|
1563
|
+
* to stage rows under and cannot produce any — see {@link WORKFLOW_CALL_MODES}.
|
|
1564
|
+
* Counting it here would let `plain call → sink` past `no-source` and commit an
|
|
1565
|
+
* empty snapshot over whatever was live, which is the exact silence this file is
|
|
1566
|
+
* arranged against.
|
|
1567
|
+
*
|
|
1568
|
+
* ## This used to be the reachability root set as well, and no longer is
|
|
1569
|
+
*
|
|
1570
|
+
* It said so, and the reason it gave was that it made the root set conservative.
|
|
1571
|
+
* The plain mode splits the two questions, because the answers genuinely differ:
|
|
1572
|
+
* a plain call **runs** with nothing wired into it (so it is a root, and calling
|
|
1573
|
+
* it unreachable would be false — it would run) and **produces nothing** (so it
|
|
1574
|
+
* is not something that reads). One function answering both would have to be
|
|
1575
|
+
* wrong about one of them. See {@link runsWithoutInput} for the other half.
|
|
1315
1576
|
*/
|
|
1316
1577
|
function originatesRows(node) {
|
|
1578
|
+
if (node.kind === 'source')
|
|
1579
|
+
return true;
|
|
1580
|
+
return node.kind === 'call' && workflowCallMode(node) === 'envelope';
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Whether a node runs whether or not anything is wired into it.
|
|
1584
|
+
*
|
|
1585
|
+
* The root set for reachability, which used to be {@link originatesRows} and is
|
|
1586
|
+
* now its own question — see the note there. Every call node is one of these,
|
|
1587
|
+
* both modes: a call with no inbound edge sits at in-degree zero in the
|
|
1588
|
+
* topological order and is dispatched like anything else, so reporting it as
|
|
1589
|
+
* "not reachable from any source, so it would never run" would be a message that
|
|
1590
|
+
* is simply untrue.
|
|
1591
|
+
*
|
|
1592
|
+
* Every call node rather than only the unwired ones, for the reason the old
|
|
1593
|
+
* function gave: it keeps a mid-graph call node from making everything
|
|
1594
|
+
* downstream of it look unreachable when its own upstream is fine.
|
|
1595
|
+
*/
|
|
1596
|
+
function runsWithoutInput(node) {
|
|
1317
1597
|
return node.kind === 'source' || node.kind === 'call';
|
|
1318
1598
|
}
|
|
1599
|
+
/** Whether this node is a call that can never hand rows back to the graph. */
|
|
1600
|
+
function isPlainCall(node) {
|
|
1601
|
+
return node.kind === 'call' && workflowCallMode(node) === 'plain';
|
|
1602
|
+
}
|
|
1319
1603
|
/**
|
|
1320
1604
|
* Index the nodes by id, reporting the ids that cannot be used as one.
|
|
1321
1605
|
*
|
|
@@ -1852,12 +2136,17 @@ function peelTails(leftover, outgoing) {
|
|
|
1852
2136
|
}
|
|
1853
2137
|
return leftover;
|
|
1854
2138
|
}
|
|
1855
|
-
/**
|
|
1856
|
-
|
|
1857
|
-
|
|
2139
|
+
/**
|
|
2140
|
+
* Nodes that nothing reading reaches, and nodes that reach no sink.
|
|
2141
|
+
*
|
|
2142
|
+
* `roots` is {@link runsWithoutInput} and not {@link originatesRows}: this asks
|
|
2143
|
+
* what would *run*, and a plain call runs whether anything feeds it or not.
|
|
2144
|
+
*/
|
|
2145
|
+
function checkReachability(nodes, roots, sinks, incoming, outgoing, issues) {
|
|
2146
|
+
const reachableFromSources = walk(roots.map((node) => node.id), outgoing);
|
|
1858
2147
|
const reachesASink = walk(sinks.map((sink) => sink.id), incoming);
|
|
1859
2148
|
for (const node of nodes) {
|
|
1860
|
-
if (
|
|
2149
|
+
if (roots.length > 0 && !reachableFromSources.has(node.id)) {
|
|
1861
2150
|
issues.push({
|
|
1862
2151
|
code: 'unreachable',
|
|
1863
2152
|
nodeIds: [node.id],
|
|
@@ -1865,6 +2154,15 @@ function checkReachability(nodes, originators, sinks, incoming, outgoing, issues
|
|
|
1865
2154
|
});
|
|
1866
2155
|
continue;
|
|
1867
2156
|
}
|
|
2157
|
+
// The one exemption the plain mode buys, and it is exactly one node wide.
|
|
2158
|
+
// A plain call reaches no sink by construction — `call-plain-has-output`
|
|
2159
|
+
// refuses it an outbound edge — so `dead-end` would fire on every one of
|
|
2160
|
+
// them, with a message ("it would be computed and thrown away") that is
|
|
2161
|
+
// false about it: the effect it was run for has happened. Nothing can hide
|
|
2162
|
+
// behind this, because nothing can be downstream of a plain call, so no
|
|
2163
|
+
// other node's route to the sink can run through one.
|
|
2164
|
+
if (isPlainCall(node))
|
|
2165
|
+
continue;
|
|
1868
2166
|
if (sinks.length > 0 && !reachesASink.has(node.id)) {
|
|
1869
2167
|
issues.push({
|
|
1870
2168
|
code: 'dead-end',
|
|
@@ -2100,6 +2398,13 @@ function canonicalNode(node) {
|
|
|
2100
2398
|
node.callName,
|
|
2101
2399
|
node.callVersion,
|
|
2102
2400
|
sortedEntries(node.config),
|
|
2401
|
+
// Appended only for the non-default mode, exactly as `edge.branch` above
|
|
2402
|
+
// is appended only when there is a label. Every call node in every
|
|
2403
|
+
// deployment today is an envelope call — whether it says so or says
|
|
2404
|
+
// nothing — so every one of them hashes to the string it always did and
|
|
2405
|
+
// no stored graph is renumbered by picking up this release. See
|
|
2406
|
+
// `canonicalCallMode` for why the two spellings must fold together.
|
|
2407
|
+
...canonicalCallMode(workflowCallMode(node)),
|
|
2103
2408
|
]);
|
|
2104
2409
|
}
|
|
2105
2410
|
if (node.kind === 'if') {
|
|
@@ -2144,6 +2449,27 @@ function canonicalNode(node) {
|
|
|
2144
2449
|
* no version bump and no diff — which is precisely the silence this feature was
|
|
2145
2450
|
* built to end.
|
|
2146
2451
|
*/
|
|
2452
|
+
/**
|
|
2453
|
+
* The call mode, as zero or one trailing hash component.
|
|
2454
|
+
*
|
|
2455
|
+
* Zero for `envelope`, and that is the opposite choice from {@link
|
|
2456
|
+
* canonicalReuse} beside it — for the opposite reason. There, absent and present
|
|
2457
|
+
* mean genuinely different things ("follow the latest" against "pinned to v1"),
|
|
2458
|
+
* so they must hash differently. Here absent and `'envelope'` are one behaviour
|
|
2459
|
+
* spelled two ways: a node that says `callMode: 'envelope'` puts precisely the
|
|
2460
|
+
* same bytes on the wire as a node that says nothing. A fingerprint that told
|
|
2461
|
+
* them apart would report an edit when a canvas normalised the field, which is
|
|
2462
|
+
* the cosmetic version bump {@link workflowGraphHash} exists to not do.
|
|
2463
|
+
*
|
|
2464
|
+
* `plain` earns its component, because it changes what the child receives.
|
|
2465
|
+
*/
|
|
2466
|
+
function canonicalCallMode(mode) {
|
|
2467
|
+
if (mode === 'envelope')
|
|
2468
|
+
return [];
|
|
2469
|
+
if (mode === 'plain')
|
|
2470
|
+
return ['plain'];
|
|
2471
|
+
return unreachableCallMode(mode, 'workflowGraphHash');
|
|
2472
|
+
}
|
|
2147
2473
|
function canonicalReuse(node) {
|
|
2148
2474
|
if (node.useId === undefined)
|
|
2149
2475
|
return [];
|
|
@@ -2252,18 +2578,8 @@ function isWorkflowNode(value) {
|
|
|
2252
2578
|
if (kind === 'sink') {
|
|
2253
2579
|
return typeof Reflect.get(value, 'targetType') === 'string';
|
|
2254
2580
|
}
|
|
2255
|
-
if (kind === 'call')
|
|
2256
|
-
|
|
2257
|
-
// a stored call node missing its version is a node that would run whatever
|
|
2258
|
-
// is registered today, which is the failure the pin exists to remove — and
|
|
2259
|
-
// a graph that half-narrows is a load that runs nine nodes of ten.
|
|
2260
|
-
const config = Reflect.get(value, 'config');
|
|
2261
|
-
return (typeof Reflect.get(value, 'callName') === 'string' &&
|
|
2262
|
-
typeof Reflect.get(value, 'callVersion') === 'string' &&
|
|
2263
|
-
typeof config === 'object' &&
|
|
2264
|
-
config !== null &&
|
|
2265
|
-
!Array.isArray(config));
|
|
2266
|
-
}
|
|
2581
|
+
if (kind === 'call')
|
|
2582
|
+
return isCallNodeShape(value);
|
|
2267
2583
|
if (kind === 'if') {
|
|
2268
2584
|
// The predicate in full, refused rather than defaulted: a gate read back
|
|
2269
2585
|
// without a test it recognises would have to invent one, and inventing one
|
|
@@ -2282,6 +2598,34 @@ function isWorkflowNode(value) {
|
|
|
2282
2598
|
}
|
|
2283
2599
|
return isWorkflowNodeKindUnhandled(kind);
|
|
2284
2600
|
}
|
|
2601
|
+
/**
|
|
2602
|
+
* Everything a `call` node carries, checked as strictly as a source's.
|
|
2603
|
+
*
|
|
2604
|
+
* Its own function rather than a branch of {@link isWorkflowNode}, which the
|
|
2605
|
+
* complexity bound will not hold any more of — and the split is where it should
|
|
2606
|
+
* be, because this is the kind with the most to check.
|
|
2607
|
+
*
|
|
2608
|
+
* A stored call node missing its version is a node that would run whatever is
|
|
2609
|
+
* registered today, which is the failure the pin exists to remove, and a graph
|
|
2610
|
+
* that half-narrows is a load that runs nine nodes of ten. A `callMode` that is
|
|
2611
|
+
* present and unrecognised is refused rather than dropped, for the reason an
|
|
2612
|
+
* unrecognised `edge.branch` is: reading it back as the default would turn a
|
|
2613
|
+
* plain call into an envelope call silently, and the callee would be handed a
|
|
2614
|
+
* payload nobody authored. Absent is accepted and always will be — it is what
|
|
2615
|
+
* every call node written before the field existed carries, and it means the
|
|
2616
|
+
* envelope, which is what those nodes have always sent.
|
|
2617
|
+
*/
|
|
2618
|
+
function isCallNodeShape(value) {
|
|
2619
|
+
const callMode = Reflect.get(value, 'callMode');
|
|
2620
|
+
if (callMode !== undefined && !isWorkflowCallMode(callMode))
|
|
2621
|
+
return false;
|
|
2622
|
+
const config = Reflect.get(value, 'config');
|
|
2623
|
+
return (typeof Reflect.get(value, 'callName') === 'string' &&
|
|
2624
|
+
typeof Reflect.get(value, 'callVersion') === 'string' &&
|
|
2625
|
+
typeof config === 'object' &&
|
|
2626
|
+
config !== null &&
|
|
2627
|
+
!Array.isArray(config));
|
|
2628
|
+
}
|
|
2285
2629
|
/**
|
|
2286
2630
|
* Whether a stored `narrows` is one this build can read.
|
|
2287
2631
|
*
|
package/dist/client.d.ts
CHANGED
|
@@ -153,8 +153,8 @@ export declare const catalogRoutes: {
|
|
|
153
153
|
readonly traces: () => string;
|
|
154
154
|
readonly trace: (id: string) => string;
|
|
155
155
|
};
|
|
156
|
-
export type { CatalogConnection, CatalogConnector, ConnectionCheck, CatalogTransform, CatalogWorkflow, CatalogWorkflowCapabilities, CatalogWorkflowRelease, ConnectorKind, ConnectorRun, TransformLanguage, TransformResult, CallableWorkflowRef, WorkflowBranchLabel, WorkflowCallEnvelope, WorkflowCallNode, WorkflowCallOutput, WorkflowEdge, WorkflowExecutionMode, WorkflowFilterAll, WorkflowFilterAny, WorkflowFilterComparison, WorkflowFilterGroup, WorkflowFilterNode, WorkflowFilterOneOf, WorkflowFilterOperator, WorkflowFilterPredicate, WorkflowFilterPredicateKind, WorkflowFilterPresence, WorkflowFilterValue, WorkflowGraph, WorkflowEnvPredicate, WorkflowIfNode, WorkflowIfPredicate, WorkflowIssueCode, WorkflowNode, WorkflowNodeKind, WorkflowNodeOutcome, WorkflowPredicateKind, WorkflowRowCountPredicate, WorkflowRunOrderEntry, WorkflowSinkNode, WorkflowSkipReason, WorkflowSourceNode, WorkflowStageRef, WorkflowTransformNode, WorkflowValidationIssue, CatalogReusableNode, CatalogReusableNodeUse, ReusableNodeBody, ReusableNodeKind, ReusableNodeRef, ReusableSinkBody, ReusableSourceBody, VersionPinCopy, } from './catalog.pipeline';
|
|
157
|
-
export { CONNECTOR_KINDS, isConnectorKind, isTransformLanguage, isWorkflowEdge, isWorkflowNode, liveWorkflowVersion, REDACTED_SECRET, TRANSFORM_LANGUAGES, readWorkflowCallOutput, WORKFLOW_CALL_CONTRACT, applyReusableNode, reusableNodeBodyOf, isReusableNodeBody, isReusableNodeKind, REUSABLE_NODE_KINDS, NODE_KIND_IS_REUSABLE, nodeKindIsReusable, unreachableReusableNodeKind, describeLiveVersion, describeVersionPin, } from './catalog.pipeline';
|
|
156
|
+
export type { CatalogConnection, CatalogConnector, ConnectionCheck, CatalogTransform, CatalogWorkflow, CatalogWorkflowCapabilities, CatalogWorkflowRelease, ConnectorKind, ConnectorRun, TransformLanguage, TransformResult, CallableWorkflowRef, WorkflowBranchLabel, WorkflowCallEnvelope, WorkflowCallMode, WorkflowCallNode, WorkflowCallOutput, WorkflowEdge, WorkflowExecutionMode, WorkflowFilterAll, WorkflowFilterAny, WorkflowFilterComparison, WorkflowFilterGroup, WorkflowFilterNode, WorkflowFilterOneOf, WorkflowFilterOperator, WorkflowFilterPredicate, WorkflowFilterPredicateKind, WorkflowFilterPresence, WorkflowFilterValue, WorkflowGraph, WorkflowEnvPredicate, WorkflowIfNode, WorkflowIfPredicate, WorkflowIssueCode, WorkflowNode, WorkflowNodeKind, WorkflowNodeOutcome, WorkflowPredicateKind, WorkflowRowCountPredicate, WorkflowRunOrderEntry, WorkflowSinkNode, WorkflowSkipReason, WorkflowSourceNode, WorkflowStageRef, WorkflowTransformNode, WorkflowValidationIssue, CatalogReusableNode, CatalogReusableNodeUse, ReusableNodeBody, ReusableNodeKind, ReusableNodeRef, ReusableSinkBody, ReusableSourceBody, SourceFormat, VersionPinCopy, } from './catalog.pipeline';
|
|
157
|
+
export { CONNECTOR_KINDS, isConnectorKind, isSourceFormat, isTransformLanguage, SOURCE_FORMATS, isWorkflowEdge, isWorkflowNode, liveWorkflowVersion, REDACTED_SECRET, TRANSFORM_LANGUAGES, readWorkflowCallOutput, WORKFLOW_CALL_CONTRACT, WORKFLOW_CALL_MODES, isWorkflowCallMode, unreachableCallMode, workflowCallMode, applyReusableNode, reusableNodeBodyOf, isReusableNodeBody, isReusableNodeKind, REUSABLE_NODE_KINDS, NODE_KIND_IS_REUSABLE, nodeKindIsReusable, unreachableReusableNodeKind, describeLiveVersion, describeVersionPin, } from './catalog.pipeline';
|
|
158
158
|
/**
|
|
159
159
|
* The workflow validator, shipped to the browser deliberately.
|
|
160
160
|
*
|
package/dist/client.js
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* types are.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.
|
|
15
|
-
exports.DELETE_RECONCILIATION_STRATEGIES = exports.callableWorkflowBlock = exports.isWorkflowStatus = exports.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_STATUSES = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableFilterPredicateKind = exports.unreachableFilterOperator = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowFilterMatches = exports.isWorkflowSkipReason = exports.isWorkflowPredicateKind = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowBranchLabel = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_FILTER_PREDICATE_KINDS = exports.WORKFLOW_FILTER_OPERATORS = exports.WORKFLOW_FILTER_MAX_VALUES = exports.WORKFLOW_FILTER_MAX_DEPTH = exports.WORKFLOW_FILTER_COLUMN_PATTERN = void 0;
|
|
14
|
+
exports.validateWorkflow = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_HEIGHT = exports.WORKFLOW_COLUMN_GAP = exports.describeVersionPin = exports.describeLiveVersion = exports.unreachableReusableNodeKind = exports.nodeKindIsReusable = exports.NODE_KIND_IS_REUSABLE = exports.REUSABLE_NODE_KINDS = exports.isReusableNodeKind = exports.isReusableNodeBody = exports.reusableNodeBodyOf = exports.applyReusableNode = exports.workflowCallMode = exports.unreachableCallMode = exports.isWorkflowCallMode = exports.WORKFLOW_CALL_MODES = exports.WORKFLOW_CALL_CONTRACT = exports.readWorkflowCallOutput = exports.TRANSFORM_LANGUAGES = exports.REDACTED_SECRET = exports.liveWorkflowVersion = exports.isWorkflowNode = exports.isWorkflowEdge = exports.SOURCE_FORMATS = exports.isTransformLanguage = exports.isSourceFormat = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.catalogRoutes = exports.UnsafeIdentifierError = exports.physicalColumn = exports.outputAlias = exports.isSafeIdentifier = exports.VALUELESS_FILTER_OPERATORS = exports.resolveObjectFilters = exports.parseObjectFilter = exports.offeredFilterOperators = exports.isCatalogFilterOperator = exports.filterOperatorsFor = exports.filterOperatorTakesValue = exports.encodeObjectFilter = exports.coerceFilterValue = exports.CATALOG_FILTER_OPERATORS = exports.CATALOG_FILTER_LIMIT = exports.CATALOG_REVISION_LIMIT = void 0;
|
|
15
|
+
exports.DELETE_RECONCILIATION_STRATEGIES = exports.callableWorkflowBlock = exports.isWorkflowStatus = exports.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_STATUSES = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableFilterPredicateKind = exports.unreachableFilterOperator = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowFilterMatches = exports.isWorkflowSkipReason = exports.isWorkflowPredicateKind = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowBranchLabel = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_FILTER_PREDICATE_KINDS = exports.WORKFLOW_FILTER_OPERATORS = exports.WORKFLOW_FILTER_MAX_VALUES = exports.WORKFLOW_FILTER_MAX_DEPTH = exports.WORKFLOW_FILTER_COLUMN_PATTERN = exports.WORKFLOW_PREDICATE_KINDS = exports.WORKFLOW_BRANCH_LABELS = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_EXECUTION_MODES = void 0;
|
|
16
16
|
exports.isDeleteReconciliationStrategy = isDeleteReconciliationStrategy;
|
|
17
17
|
exports.pipelineExpectationRoutes = pipelineExpectationRoutes;
|
|
18
18
|
// A value, not a type: a screen saying how far back the history goes should read
|
|
@@ -134,7 +134,9 @@ exports.catalogRoutes = {
|
|
|
134
134
|
var catalog_pipeline_1 = require("./catalog.pipeline");
|
|
135
135
|
Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.CONNECTOR_KINDS; } });
|
|
136
136
|
Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
|
|
137
|
+
Object.defineProperty(exports, "isSourceFormat", { enumerable: true, get: function () { return catalog_pipeline_1.isSourceFormat; } });
|
|
137
138
|
Object.defineProperty(exports, "isTransformLanguage", { enumerable: true, get: function () { return catalog_pipeline_1.isTransformLanguage; } });
|
|
139
|
+
Object.defineProperty(exports, "SOURCE_FORMATS", { enumerable: true, get: function () { return catalog_pipeline_1.SOURCE_FORMATS; } });
|
|
138
140
|
// The canvas narrows nodes and edges it reads back from HTTP. Without these
|
|
139
141
|
// it either imports them from the package root — dragging NestJS and MikroORM
|
|
140
142
|
// into a browser bundle — or writes its own copy of the checks, which is the
|
|
@@ -158,6 +160,15 @@ Object.defineProperty(exports, "TRANSFORM_LANGUAGES", { enumerable: true, get: f
|
|
|
158
160
|
// runner does, so the two cannot disagree about what "no rows" looks like.
|
|
159
161
|
Object.defineProperty(exports, "readWorkflowCallOutput", { enumerable: true, get: function () { return catalog_pipeline_1.readWorkflowCallOutput; } });
|
|
160
162
|
Object.defineProperty(exports, "WORKFLOW_CALL_CONTRACT", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_CALL_CONTRACT; } });
|
|
163
|
+
// The two wire formats a call node can take, and the reader that applies the
|
|
164
|
+
// default. The inspector has to offer exactly the modes the runner can build a
|
|
165
|
+
// payload for, and a screen carrying its own `?? 'envelope'` is the second
|
|
166
|
+
// copy of a default that eventually disagrees with the hash — which would show
|
|
167
|
+
// an author unsaved changes on a graph nobody edited.
|
|
168
|
+
Object.defineProperty(exports, "WORKFLOW_CALL_MODES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_CALL_MODES; } });
|
|
169
|
+
Object.defineProperty(exports, "isWorkflowCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowCallMode; } });
|
|
170
|
+
Object.defineProperty(exports, "unreachableCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableCallMode; } });
|
|
171
|
+
Object.defineProperty(exports, "workflowCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.workflowCallMode; } });
|
|
161
172
|
// Reusable nodes, and the two directions a screen needs them in: the fold onto
|
|
162
173
|
// a node, so a picker can show what choosing one will do without a round trip,
|
|
163
174
|
// and the lift off a node, so "save this as reusable" sends the same body the
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { type CatalogOverlayStore, FileCatalogOverlayStore, InMemoryCatalogOverl
|
|
|
8
8
|
export { CATALOG_OVERLAY_STORE } from './catalog.overlay-store.token';
|
|
9
9
|
export { MikroOrmCatalogRegistry } from './catalog.registry';
|
|
10
10
|
export { CatalogRegistry } from './catalog.registry.base';
|
|
11
|
-
export { CATALOG_PIPELINE_STORE, CODE_CONTEXT_CONTRACT, type CatalogCodeContext, type CatalogConnection, type CatalogConnector, type ConnectionCheck, CONNECTOR_KINDS, type CatalogLoadExpectations, type CatalogLoadExpectationStore, type CatalogPipelineStore, type CatalogStageStore, type CatalogTransform, type CatalogWorkflow, type CatalogWorkflowCapabilities, type CatalogWorkflowRelease, type CatalogWorkflowReleaseStore, type CatalogWorkflowStore, type CallableWorkflowBlock, type CallableWorkflowDisagreement, type CallableWorkflowRef, callableWorkflowBlock, type ConnectorKind, type ConnectorRun, type DeleteReconciliation, isConnectorKind, isPipelineStore, isTransformLanguage, type LoadExpectation, type RowCountBound, type StoredLoadExpectation, readWorkflowCallOutput, REDACTED_SECRET, supportsLoadExpectations, supportsReusableNodes, supportsTransformPins, supportsTransformRevisions, applyReusableNode, type CatalogReusableNode, type CatalogReusableNodeStore, type CatalogReusableNodeUse, describeLiveVersion, describeVersionPin, isReusableNodeBody, isReusableNodeKind, NODE_KIND_IS_REUSABLE, nodeKindIsReusable, REUSABLE_NODE_KINDS, type ReusableNodeBody, type ReusableNodeKind, type ReusableNodeRef, type ReusableSinkBody, type ReusableSourceBody, reusableNodeBodyOf, unreachableReusableNodeKind, type VersionPinCopy, isWorkflowBranchLabel, isWorkflowEdge, isWorkflowExecutionMode, isWorkflowFilterOperator, isWorkflowFilterPredicate, isWorkflowFilterPredicateKind, isWorkflowFilterValue, isWorkflowIfPredicate, isWorkflowNode, isWorkflowNodeKind, isWorkflowPredicateKind, isWorkflowSkipReason, isWorkflowStatus, liveWorkflowVersion, supportsWorkflowReleases, supportsWorkflows, supportsWorkflowStages, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, type TransformLanguage, type TransformResult, type TransformRunner, unreachableFilterOperator, unreachableFilterPredicateKind, unreachableNodeKind, unreachablePredicateKind, validateWorkflow, WORKFLOW_BRANCH_LABELS, WORKFLOW_CALL_CONTRACT, WORKFLOW_COLUMN_GAP, WORKFLOW_EXECUTION_MODES, WORKFLOW_FILTER_COLUMN_PATTERN, WORKFLOW_FILTER_MAX_DEPTH, WORKFLOW_FILTER_MAX_VALUES, WORKFLOW_FILTER_OPERATORS, WORKFLOW_FILTER_PREDICATE_KINDS, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_HEIGHT, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_NODE_WIDTH, WORKFLOW_PREDICATE_KINDS, WORKFLOW_ROW_GAP, WORKFLOW_SKIP_REASONS, WORKFLOW_STATUSES, type WorkflowBranchLabel, workflowColumnX, workflowRowY, type WorkflowCallEnvelope, type WorkflowCallNode, type WorkflowCallOutput, type WorkflowEdge, type WorkflowExecutionMode, type WorkflowFilterAll, type WorkflowFilterAny, type WorkflowFilterComparison, type WorkflowFilterGroup, workflowFilterMatches, type WorkflowFilterNode, type WorkflowFilterOneOf, type WorkflowFilterOperator, type WorkflowFilterPredicate, type WorkflowFilterPredicateKind, type WorkflowFilterPresence, type WorkflowFilterValue, type WorkflowGraph, workflowGraphHash, type WorkflowEnvPredicate, type WorkflowIfNode, type WorkflowIfPredicate, type WorkflowIssueCode, type WorkflowNode, type WorkflowNodeKind, workflowNarrowedTypes, type WorkflowNodeOutcome, workflowNodeRuns, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowRunOrderEntry, type WorkflowPredicateKind, type WorkflowRowCountPredicate, type WorkflowSinkNode, type WorkflowSkipReason, type WorkflowSourceNode, type WorkflowStageRef, type WorkflowStatus, type WorkflowTransformNode, type WorkflowValidationIssue, } from './catalog.pipeline';
|
|
11
|
+
export { CATALOG_PIPELINE_STORE, CODE_CONTEXT_CONTRACT, type CatalogCodeContext, type CatalogConnection, type CatalogConnector, type ConnectionCheck, CONNECTOR_KINDS, type CatalogLoadExpectations, type CatalogLoadExpectationStore, type CatalogPipelineStore, type CatalogStageStore, type CatalogTransform, type CatalogWorkflow, type CatalogWorkflowCapabilities, type CatalogWorkflowRelease, type CatalogWorkflowReleaseStore, type CatalogWorkflowStore, type CallableWorkflowBlock, type CallableWorkflowDisagreement, type CallableWorkflowRef, callableWorkflowBlock, type ConnectorKind, type ConnectorRun, type DeleteReconciliation, isConnectorKind, isPipelineStore, isSourceFormat, isTransformLanguage, type LoadExpectation, type RowCountBound, SOURCE_FORMATS, type SourceFormat, unreachableSourceFormat, type StoredLoadExpectation, readWorkflowCallOutput, REDACTED_SECRET, supportsLoadExpectations, supportsReusableNodes, supportsTransformPins, supportsTransformRevisions, applyReusableNode, type CatalogReusableNode, type CatalogReusableNodeStore, type CatalogReusableNodeUse, describeLiveVersion, describeVersionPin, isReusableNodeBody, isReusableNodeKind, NODE_KIND_IS_REUSABLE, nodeKindIsReusable, REUSABLE_NODE_KINDS, type ReusableNodeBody, type ReusableNodeKind, type ReusableNodeRef, type ReusableSinkBody, type ReusableSourceBody, reusableNodeBodyOf, unreachableReusableNodeKind, type VersionPinCopy, isWorkflowBranchLabel, isWorkflowEdge, isWorkflowExecutionMode, isWorkflowFilterOperator, isWorkflowFilterPredicate, isWorkflowFilterPredicateKind, isWorkflowFilterValue, isWorkflowIfPredicate, isWorkflowNode, isWorkflowCallMode, isWorkflowNodeKind, isWorkflowPredicateKind, isWorkflowSkipReason, isWorkflowStatus, liveWorkflowVersion, supportsWorkflowReleases, supportsWorkflows, supportsWorkflowStages, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, type TransformLanguage, type TransformResult, type TransformRunner, unreachableFilterOperator, unreachableFilterPredicateKind, unreachableCallMode, unreachableNodeKind, unreachablePredicateKind, validateWorkflow, WORKFLOW_BRANCH_LABELS, WORKFLOW_CALL_CONTRACT, WORKFLOW_CALL_MODES, WORKFLOW_COLUMN_GAP, WORKFLOW_EXECUTION_MODES, WORKFLOW_FILTER_COLUMN_PATTERN, WORKFLOW_FILTER_MAX_DEPTH, WORKFLOW_FILTER_MAX_VALUES, WORKFLOW_FILTER_OPERATORS, WORKFLOW_FILTER_PREDICATE_KINDS, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_HEIGHT, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_NODE_WIDTH, WORKFLOW_PREDICATE_KINDS, WORKFLOW_ROW_GAP, WORKFLOW_SKIP_REASONS, WORKFLOW_STATUSES, type WorkflowBranchLabel, workflowColumnX, workflowRowY, type WorkflowCallEnvelope, type WorkflowCallMode, workflowCallMode, type WorkflowCallNode, type WorkflowCallOutput, type WorkflowEdge, type WorkflowExecutionMode, type WorkflowFilterAll, type WorkflowFilterAny, type WorkflowFilterComparison, type WorkflowFilterGroup, workflowFilterMatches, type WorkflowFilterNode, type WorkflowFilterOneOf, type WorkflowFilterOperator, type WorkflowFilterPredicate, type WorkflowFilterPredicateKind, type WorkflowFilterPresence, type WorkflowFilterValue, type WorkflowGraph, workflowGraphHash, type WorkflowEnvPredicate, type WorkflowIfNode, type WorkflowIfPredicate, type WorkflowIssueCode, type WorkflowNode, type WorkflowNodeKind, workflowNarrowedTypes, type WorkflowNodeOutcome, workflowNodeRuns, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowRunOrderEntry, type WorkflowPredicateKind, type WorkflowRowCountPredicate, type WorkflowSinkNode, type WorkflowSkipReason, type WorkflowSourceNode, type WorkflowStageRef, type WorkflowStatus, type WorkflowTransformNode, type WorkflowValidationIssue, } from './catalog.pipeline';
|
|
12
12
|
export { type ColumnarStageBatch, STAGE_ENCODING, STAGE_ENCODING_VERSION, type StagePayload, classifyStagePayload, decodeStageRows, encodeStageRows, isColumnarStageBatch, } from './catalog.stage-encoding';
|
|
13
13
|
export * from './catalog.environment';
|
|
14
14
|
export { QueryCache } from './catalog.query-cache';
|
package/dist/index.js
CHANGED
|
@@ -14,10 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.RequireScopes = exports.RequireHuman = exports.REQUIRES_HUMAN = exports.REQUIRED_SCOPES = exports.MikroOrmReadStore = exports.UnsafeIdentifierError = void 0;
|
|
17
|
+
exports.isWorkflowExecutionMode = exports.isWorkflowEdge = exports.isWorkflowBranchLabel = exports.unreachableReusableNodeKind = exports.reusableNodeBodyOf = exports.REUSABLE_NODE_KINDS = exports.nodeKindIsReusable = exports.NODE_KIND_IS_REUSABLE = exports.isReusableNodeKind = exports.isReusableNodeBody = exports.describeVersionPin = exports.describeLiveVersion = exports.applyReusableNode = exports.supportsTransformRevisions = exports.supportsTransformPins = exports.supportsReusableNodes = exports.supportsLoadExpectations = exports.REDACTED_SECRET = exports.readWorkflowCallOutput = exports.unreachableSourceFormat = exports.SOURCE_FORMATS = exports.isTransformLanguage = exports.isSourceFormat = exports.isPipelineStore = exports.isConnectorKind = exports.callableWorkflowBlock = exports.CONNECTOR_KINDS = exports.CODE_CONTEXT_CONTRACT = exports.CATALOG_PIPELINE_STORE = exports.CatalogRegistry = exports.MikroOrmCatalogRegistry = exports.CATALOG_OVERLAY_STORE = exports.InMemoryCatalogOverlayStore = exports.FileCatalogOverlayStore = exports.CATALOG_OPTIONS = exports.isStreamingQueryStore = exports.isQueryStore = exports.assertReadOnlyShape = exports.CatalogModule = exports.emitCatalog = exports.curationActor = exports.channelNameFor = exports.catalogEventPhase = exports.UNATTRIBUTED_PRINCIPAL_ID = exports.CATALOG_LIB = exports.CATALOG_EVENTS = exports.CATALOG_EVENT_PHASE_FALLBACK = exports.CATALOG_EVENT_PHASE = exports.CatalogType = exports.CatalogProperty = void 0;
|
|
18
|
+
exports.workflowRunOrder = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowGraphHash = exports.workflowFilterMatches = exports.workflowCallMode = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_STATUSES = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_PREDICATE_KINDS = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_NODE_HEIGHT = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_FILTER_PREDICATE_KINDS = exports.WORKFLOW_FILTER_OPERATORS = exports.WORKFLOW_FILTER_MAX_VALUES = exports.WORKFLOW_FILTER_MAX_DEPTH = exports.WORKFLOW_FILTER_COLUMN_PATTERN = exports.WORKFLOW_EXECUTION_MODES = exports.WORKFLOW_COLUMN_GAP = exports.WORKFLOW_CALL_MODES = exports.WORKFLOW_CALL_CONTRACT = exports.WORKFLOW_BRANCH_LABELS = exports.validateWorkflow = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableCallMode = exports.unreachableFilterPredicateKind = exports.unreachableFilterOperator = exports.TRANSFORM_LANGUAGES = exports.TRANSFORM_RUNNER = exports.supportsWorkflowStages = exports.supportsWorkflows = exports.supportsWorkflowReleases = exports.liveWorkflowVersion = exports.isWorkflowStatus = exports.isWorkflowSkipReason = exports.isWorkflowPredicateKind = exports.isWorkflowNodeKind = exports.isWorkflowCallMode = exports.isWorkflowNode = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = void 0;
|
|
19
|
+
exports.findColumnCollisions = exports.supportsObjectFilters = exports.CatalogColumnCollisionError = exports.CATALOG_STORE = exports.CATALOG_SNAPSHOT_MODES = exports.CATALOG_RESERVED_COLUMNS = exports.assertSafeIdentifier = exports.assertNoColumnCollisions = exports.StaticKeyPrincipalResolver = exports.readableObjectPage = exports.mayWrite = exports.mayRead = exports.maySeeClassification = exports.PRINCIPAL_ACTOR_SEPARATOR = exports.parsePrincipalId = exports.hasScope = exports.expandScopes = exports.delegatePrincipal = exports.composePrincipalId = exports.CATALOG_PRINCIPAL_RESOLVER = exports.traceOutcomeFilter = exports.supportsSavedQueryRevisions = exports.isWorkspaceStore = exports.isTraceStore = exports.isCatalogTraceOutcome = exports.embeddedVisualization = exports.CATALOG_WORKSPACE_STORE = exports.CATALOG_TRACE_STORE = exports.CATALOG_TRACE_OUTCOMES = exports.CATALOG_REVISION_LIMIT = exports.visibleToPrincipal = exports.searchCatalog = exports.maySearch = exports.emptySearch = exports.bestMatch = exports.MAX_SEARCH_LIMIT = exports.DEFAULT_SEARCH_LIMIT = exports.CatalogService = exports.SubprocessTransformRunner = exports.toCsv = exports.guardFormula = exports.csvLines = exports.csvCell = exports.QueryCache = exports.isColumnarStageBatch = exports.encodeStageRows = exports.decodeStageRows = exports.classifyStagePayload = exports.STAGE_ENCODING_VERSION = exports.STAGE_ENCODING = void 0;
|
|
20
|
+
exports.RequireScopes = exports.RequireHuman = exports.REQUIRES_HUMAN = exports.REQUIRED_SCOPES = exports.MikroOrmReadStore = exports.UnsafeIdentifierError = exports.supportsCarryForward = exports.physicalColumn = exports.outputAlias = exports.isWriteStore = exports.isSafeIdentifier = exports.isReservedColumn = exports.isCatalogStoreCapabilities = void 0;
|
|
21
21
|
var catalog_decorators_1 = require("./catalog.decorators");
|
|
22
22
|
Object.defineProperty(exports, "CatalogProperty", { enumerable: true, get: function () { return catalog_decorators_1.CatalogProperty; } });
|
|
23
23
|
Object.defineProperty(exports, "CatalogType", { enumerable: true, get: function () { return catalog_decorators_1.CatalogType; } });
|
|
@@ -63,7 +63,10 @@ Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: funct
|
|
|
63
63
|
Object.defineProperty(exports, "callableWorkflowBlock", { enumerable: true, get: function () { return catalog_pipeline_1.callableWorkflowBlock; } });
|
|
64
64
|
Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
|
|
65
65
|
Object.defineProperty(exports, "isPipelineStore", { enumerable: true, get: function () { return catalog_pipeline_1.isPipelineStore; } });
|
|
66
|
+
Object.defineProperty(exports, "isSourceFormat", { enumerable: true, get: function () { return catalog_pipeline_1.isSourceFormat; } });
|
|
66
67
|
Object.defineProperty(exports, "isTransformLanguage", { enumerable: true, get: function () { return catalog_pipeline_1.isTransformLanguage; } });
|
|
68
|
+
Object.defineProperty(exports, "SOURCE_FORMATS", { enumerable: true, get: function () { return catalog_pipeline_1.SOURCE_FORMATS; } });
|
|
69
|
+
Object.defineProperty(exports, "unreachableSourceFormat", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableSourceFormat; } });
|
|
67
70
|
Object.defineProperty(exports, "readWorkflowCallOutput", { enumerable: true, get: function () { return catalog_pipeline_1.readWorkflowCallOutput; } });
|
|
68
71
|
Object.defineProperty(exports, "REDACTED_SECRET", { enumerable: true, get: function () { return catalog_pipeline_1.REDACTED_SECRET; } });
|
|
69
72
|
Object.defineProperty(exports, "supportsLoadExpectations", { enumerable: true, get: function () { return catalog_pipeline_1.supportsLoadExpectations; } });
|
|
@@ -89,6 +92,7 @@ Object.defineProperty(exports, "isWorkflowFilterPredicateKind", { enumerable: tr
|
|
|
89
92
|
Object.defineProperty(exports, "isWorkflowFilterValue", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowFilterValue; } });
|
|
90
93
|
Object.defineProperty(exports, "isWorkflowIfPredicate", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowIfPredicate; } });
|
|
91
94
|
Object.defineProperty(exports, "isWorkflowNode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowNode; } });
|
|
95
|
+
Object.defineProperty(exports, "isWorkflowCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowCallMode; } });
|
|
92
96
|
Object.defineProperty(exports, "isWorkflowNodeKind", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowNodeKind; } });
|
|
93
97
|
Object.defineProperty(exports, "isWorkflowPredicateKind", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowPredicateKind; } });
|
|
94
98
|
Object.defineProperty(exports, "isWorkflowSkipReason", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowSkipReason; } });
|
|
@@ -101,11 +105,13 @@ Object.defineProperty(exports, "TRANSFORM_RUNNER", { enumerable: true, get: func
|
|
|
101
105
|
Object.defineProperty(exports, "TRANSFORM_LANGUAGES", { enumerable: true, get: function () { return catalog_pipeline_1.TRANSFORM_LANGUAGES; } });
|
|
102
106
|
Object.defineProperty(exports, "unreachableFilterOperator", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableFilterOperator; } });
|
|
103
107
|
Object.defineProperty(exports, "unreachableFilterPredicateKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableFilterPredicateKind; } });
|
|
108
|
+
Object.defineProperty(exports, "unreachableCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableCallMode; } });
|
|
104
109
|
Object.defineProperty(exports, "unreachableNodeKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableNodeKind; } });
|
|
105
110
|
Object.defineProperty(exports, "unreachablePredicateKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachablePredicateKind; } });
|
|
106
111
|
Object.defineProperty(exports, "validateWorkflow", { enumerable: true, get: function () { return catalog_pipeline_1.validateWorkflow; } });
|
|
107
112
|
Object.defineProperty(exports, "WORKFLOW_BRANCH_LABELS", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_BRANCH_LABELS; } });
|
|
108
113
|
Object.defineProperty(exports, "WORKFLOW_CALL_CONTRACT", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_CALL_CONTRACT; } });
|
|
114
|
+
Object.defineProperty(exports, "WORKFLOW_CALL_MODES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_CALL_MODES; } });
|
|
109
115
|
Object.defineProperty(exports, "WORKFLOW_COLUMN_GAP", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_COLUMN_GAP; } });
|
|
110
116
|
Object.defineProperty(exports, "WORKFLOW_EXECUTION_MODES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_EXECUTION_MODES; } });
|
|
111
117
|
Object.defineProperty(exports, "WORKFLOW_FILTER_COLUMN_PATTERN", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_FILTER_COLUMN_PATTERN; } });
|
|
@@ -124,6 +130,7 @@ Object.defineProperty(exports, "WORKFLOW_SKIP_REASONS", { enumerable: true, get:
|
|
|
124
130
|
Object.defineProperty(exports, "WORKFLOW_STATUSES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_STATUSES; } });
|
|
125
131
|
Object.defineProperty(exports, "workflowColumnX", { enumerable: true, get: function () { return catalog_pipeline_1.workflowColumnX; } });
|
|
126
132
|
Object.defineProperty(exports, "workflowRowY", { enumerable: true, get: function () { return catalog_pipeline_1.workflowRowY; } });
|
|
133
|
+
Object.defineProperty(exports, "workflowCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.workflowCallMode; } });
|
|
127
134
|
Object.defineProperty(exports, "workflowFilterMatches", { enumerable: true, get: function () { return catalog_pipeline_1.workflowFilterMatches; } });
|
|
128
135
|
Object.defineProperty(exports, "workflowGraphHash", { enumerable: true, get: function () { return catalog_pipeline_1.workflowGraphHash; } });
|
|
129
136
|
Object.defineProperty(exports, "workflowNarrowedTypes", { enumerable: true, get: function () { return catalog_pipeline_1.workflowNarrowedTypes; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-catalog",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "A metadata registry for NestJS: object types, properties and relations, derived from your ORM and enriched with decorators.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Davide Carvalho",
|