@dudousxd/nestjs-catalog 0.19.0 → 0.21.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.
@@ -27,6 +27,46 @@ 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, so a spreadsheet handed to `JSON.parse`
38
+ * failed with a syntax error naming a byte offset rather than the format, and
39
+ * so did `format: "parquet"`.
40
+ *
41
+ * Two things distinguish the members, and everything downstream turns on one or
42
+ * the other. **Text or binary:** `xlsx` and `parquet` are binary, so everything
43
+ * that reads them takes bytes, and the other two are decoded first. **Whether
44
+ * there is a row boundary a reader can find without holding the whole
45
+ * payload:** `csv` and `ndjson` have one at every newline and `parquet` has one
46
+ * at every row group, so those three are read as a stream; `json` is a single
47
+ * value whose array may be nested inside an envelope that is only found by
48
+ * parsing down to it, and `xlsx` is a ZIP whose shared-string table generally
49
+ * has to be read before the sheet. Anything deciding something *per format*
50
+ * narrows against this list and answers {@link unreachableSourceFormat}.
51
+ */
52
+ export declare const SOURCE_FORMATS: readonly ["csv", "ndjson", "json", "xlsx", "parquet"];
53
+ export type SourceFormat = (typeof SOURCE_FORMATS)[number];
54
+ /** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
55
+ export declare function isSourceFormat(value: unknown): value is SourceFormat;
56
+ /**
57
+ * The format that never compiles quietly.
58
+ *
59
+ * The {@link unreachableNodeKind} of formats, and it exists for the same reason:
60
+ * a member added to {@link SOURCE_FORMATS} without a branch in the parser should
61
+ * be a type error naming the file, not a connector that offers a format in a
62
+ * dropdown and then reads the file as JSON.
63
+ *
64
+ * It throws as well as failing to compile, because a connector config is JSON
65
+ * that outlives the build that wrote it: a `format` stored by a newer deployment
66
+ * and read by an older one is possible, and falling back to a default for it
67
+ * would be exactly the silent path this closes.
68
+ */
69
+ export declare function unreachableSourceFormat(format: never, where: string): never;
30
70
  /**
31
71
  * What a published workflow runs as. **Not an authored object.**
32
72
  *
@@ -1042,6 +1082,13 @@ export interface WorkflowSinkNode extends WorkflowNodeBase, ReusableNodeRef {
1042
1082
  * answers are two documented shapes, and anything else fails the node naming
1043
1083
  * the workflow, the version and the child run id.
1044
1084
  *
1085
+ * All of the paragraph above describes the **envelope** mode, which is the
1086
+ * default and what every stored call node is. {@link callMode} names the other
1087
+ * one: a plain call sends {@link config} verbatim, so a workflow that has never
1088
+ * heard of this catalog can be called without being edited — and gives up the
1089
+ * ability to hand rows back, because it is told no key to stage them under. See
1090
+ * {@link WORKFLOW_CALL_MODES}.
1091
+ *
1045
1092
  * ## `config` is not a credential store
1046
1093
  *
1047
1094
  * Named `config` rather than `input` so it travels the same path a source
@@ -1067,9 +1114,109 @@ export interface WorkflowCallNode extends WorkflowNodeBase {
1067
1114
  * to *this* graph and is a number. This one identifies somebody else's code.
1068
1115
  */
1069
1116
  callVersion: string;
1070
- /** Parameters the author typed, handed to the child under `input`. */
1117
+ /**
1118
+ * Parameters the author typed. Where they land depends on
1119
+ * {@link WorkflowCallNode.callMode}: under `input` in an envelope call, and as
1120
+ * the whole of the child's payload in a plain one.
1121
+ */
1071
1122
  config: Record<string, unknown>;
1123
+ /**
1124
+ * Whether the child is handed a {@link WorkflowCallEnvelope} or the bare
1125
+ * {@link config}. See {@link WORKFLOW_CALL_MODES}, which is where the choice
1126
+ * is argued.
1127
+ *
1128
+ * Absent means `'envelope'`, which is what every call node stored before this
1129
+ * field existed is and what every one of them has always done. Read it through
1130
+ * {@link workflowCallMode} rather than defaulting it a second time — one
1131
+ * default, no second copy to drift.
1132
+ */
1133
+ callMode?: WorkflowCallMode;
1072
1134
  }
1135
+ /**
1136
+ * What a {@link WorkflowCallNode} puts on the wire, and the whole of it.
1137
+ *
1138
+ * ## Why there is a second mode at all
1139
+ *
1140
+ * The catalog could not call a workflow that does not know about the catalog.
1141
+ * A `call` node wraps the author's `config` in a {@link WorkflowCallEnvelope},
1142
+ * so a workflow that already exists — one registered years before this package,
1143
+ * whose body reads `data["proc"]` — receives `{catalog: {...}, input: {proc:
1144
+ * ...}}` and dies on the first key it looks for. The only repair available was
1145
+ * to edit the callee, which inverts the dependency exactly the wrong way round:
1146
+ * every workflow anybody wanted to call would have to start depending on this
1147
+ * package's contract, and a Python workflow registered in another repository
1148
+ * would have to be changed to be reachable from a graph.
1149
+ *
1150
+ * ## Why the nesting is not being loosened instead
1151
+ *
1152
+ * The envelope nests for one stated reason, which is on {@link
1153
+ * WorkflowCallEnvelope}: an author's parameter called `runId` must not be able
1154
+ * to shadow the run id. That reason is sound and it is not being weakened. It
1155
+ * simply does not reach the plain mode, because a plain call sends **no catalog
1156
+ * metadata at all** — there is no `runId`, no `nodeId`, no contract number on
1157
+ * the wire, so there is nothing a parameter could shadow. The flat payload is
1158
+ * not the envelope with its guard removed; it is a different, smaller promise.
1159
+ *
1160
+ * ## What the plain mode costs, which is not small
1161
+ *
1162
+ * No `runId` and no `nodeId` means the callee has no key to stage rows under.
1163
+ * Rows travel through the stage store addressed by `(runId, nodeId, batch)` —
1164
+ * see {@link WorkflowStageRef} — and a callee that was told neither cannot
1165
+ * write where the next node would read. So a plain call **cannot return rows to
1166
+ * the graph**, and that is not a convention anybody could follow more carefully:
1167
+ * it is arithmetic. `validateWorkflow` refuses a plain call with an outbound
1168
+ * edge for exactly this reason (`call-plain-has-output`), and its return value
1169
+ * is not read as a row count — see {@link readWorkflowCallOutput} for the shape
1170
+ * that is deliberately *not* consulted on this path.
1171
+ *
1172
+ * A plain call is therefore for its **effect**: run the thing, and let something
1173
+ * else in the graph produce what gets committed.
1174
+ *
1175
+ * ## Why a mode on the node rather than a second node kind or a boolean
1176
+ *
1177
+ * A boolean is the shape {@link WORKFLOW_PREDICATE_KINDS} argues against one
1178
+ * level down, and for the reason it gives: a `plain?: boolean` beside a future
1179
+ * third wire format is two optional flags whose combinations nobody defined, and
1180
+ * every reader invents its own rule for which wins. A closed list with an
1181
+ * exhaustiveness guard ({@link unreachableCallMode}) makes a third format a
1182
+ * compile error naming the files that have to answer for it.
1183
+ *
1184
+ * A second node *kind* was the other candidate and it is too big. The kind list
1185
+ * is deliberately small and every entry earns it by doing something no wiring
1186
+ * can express (see {@link WORKFLOW_NODE_KINDS}). A plain call does the same
1187
+ * thing a call does at the level the graph reasons about — it hands this
1188
+ * position to a workflow somebody else registered, pinned by name and version.
1189
+ * What differs is the payload. Splitting the kind would duplicate `callName`,
1190
+ * `callVersion`, `config`, the pin check, the picker, the plan entry and the
1191
+ * canvas node for a difference of one field, and every place that today writes
1192
+ * `node.kind === 'call'` would have to remember to write both — which is the
1193
+ * hand-maintained list going quiet that {@link NODE_KIND_IS_REUSABLE} exists to
1194
+ * stop.
1195
+ */
1196
+ export declare const WORKFLOW_CALL_MODES: readonly ["envelope", "plain"];
1197
+ export type WorkflowCallMode = (typeof WORKFLOW_CALL_MODES)[number];
1198
+ /** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
1199
+ export declare function isWorkflowCallMode(value: unknown): value is WorkflowCallMode;
1200
+ /**
1201
+ * {@link unreachableNodeKind}, one level down, and for the identical reason.
1202
+ *
1203
+ * Every branch over {@link WorkflowCallMode} ends here, so a third wire format
1204
+ * added to the list without a rule for building its payload, hashing it,
1205
+ * validating it or reading its answer is a type error naming the file. It throws
1206
+ * as well, because a mode arrives as JSON out of a column and a build older than
1207
+ * the data is a thing that happens.
1208
+ */
1209
+ export declare function unreachableCallMode(mode: never, where: string): never;
1210
+ /**
1211
+ * The mode this call node runs in, with the default applied once.
1212
+ *
1213
+ * Absent means `'envelope'` — that is what every node stored before the field
1214
+ * existed is, and reading it as anything else would silently change what a
1215
+ * deployment's graphs already do. One function so that the store, the runner,
1216
+ * the hash and the canvas cannot each carry their own `?? 'envelope'` and have
1217
+ * one of them drift.
1218
+ */
1219
+ export declare function workflowCallMode(node: WorkflowCallNode): WorkflowCallMode;
1073
1220
  /**
1074
1221
  * The kinds of test an {@link WorkflowIfNode} can make.
1075
1222
  *
@@ -2364,6 +2511,18 @@ export interface WorkflowCallOutput {
2364
2511
  * schema for a workflow's output anywhere in the durable contract, and no way
2365
2512
  * to reach one if there were. So the check is here, at the one moment the
2366
2513
  * answer exists, and it names what it saw.
2514
+ *
2515
+ * ## Not called at all for a plain call, which is a decision and not an omission
2516
+ *
2517
+ * A plain call is handed no run id and no node id, so its callee could not have
2518
+ * staged anything under `(runId, nodeId, batch)` even if it wanted to. Running
2519
+ * this over its answer would be worse than pointless in both directions: a
2520
+ * callee that happens to return `{batches, rowCount}` meaning something else
2521
+ * entirely would have this graph go and read a stage that does not exist, and a
2522
+ * callee returning one of the two would fail the node over a key it was never
2523
+ * told about. So the plain path reports zero rows unconditionally and reads
2524
+ * nothing — see `WorkflowRunnerService.callOutput`, which is where that is
2525
+ * enforced rather than merely intended.
2367
2526
  */
2368
2527
  export declare function readWorkflowCallOutput(value: unknown): WorkflowCallOutput | undefined;
2369
2528
  /**
@@ -2489,7 +2648,7 @@ export interface CallableWorkflowBlock {
2489
2648
  }
2490
2649
  export declare function callableWorkflowBlock(ref: CallableWorkflowRef): CallableWorkflowBlock | undefined;
2491
2650
  /** 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"];
2651
+ 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
2652
  export type WorkflowIssueCode = (typeof WORKFLOW_ISSUE_CODES)[number];
2494
2653
  export interface WorkflowValidationIssue {
2495
2654
  code: WorkflowIssueCode;
@@ -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,73 @@ 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, so a spreadsheet handed to `JSON.parse`
109
+ * failed with a syntax error naming a byte offset rather than the format, and
110
+ * so did `format: "parquet"`.
111
+ *
112
+ * Two things distinguish the members, and everything downstream turns on one or
113
+ * the other. **Text or binary:** `xlsx` and `parquet` are binary, so everything
114
+ * that reads them takes bytes, and the other two are decoded first. **Whether
115
+ * there is a row boundary a reader can find without holding the whole
116
+ * payload:** `csv` and `ndjson` have one at every newline and `parquet` has one
117
+ * at every row group, so those three are read as a stream; `json` is a single
118
+ * value whose array may be nested inside an envelope that is only found by
119
+ * parsing down to it, and `xlsx` is a ZIP whose shared-string table generally
120
+ * has to be read before the sheet. Anything deciding something *per format*
121
+ * narrows against this list and answers {@link unreachableSourceFormat}.
122
+ */
123
+ exports.SOURCE_FORMATS = [
124
+ /** Delimited text with a header row. The delimiter is configurable. */
125
+ 'csv',
126
+ /** One JSON value per line. */
127
+ 'ndjson',
128
+ /** A JSON document, optionally with the array nested in an envelope. */
129
+ 'json',
130
+ /**
131
+ * A spreadsheet workbook — binary, and read whole.
132
+ *
133
+ * Named for the modern extension, but the reader identifies the container
134
+ * from its own bytes, so the legacy `.xls` and the macro-enabled `.xlsm` are
135
+ * this format too rather than three names for one decision.
136
+ */
137
+ 'xlsx',
138
+ /**
139
+ * Apache Parquet — binary, and read a row group at a time.
140
+ *
141
+ * A row group is a chunk boundary the format supplies rather than one a
142
+ * reader has to invent, which is what separates it from `xlsx`. It also
143
+ * carries a real type system, so unlike the text formats a value arrives as
144
+ * the type the writer meant rather than as a string.
145
+ */
146
+ 'parquet',
147
+ ];
148
+ /** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
149
+ function isSourceFormat(value) {
150
+ return exports.SOURCE_FORMATS.some((format) => format === value);
151
+ }
152
+ /**
153
+ * The format that never compiles quietly.
154
+ *
155
+ * The {@link unreachableNodeKind} of formats, and it exists for the same reason:
156
+ * a member added to {@link SOURCE_FORMATS} without a branch in the parser should
157
+ * be a type error naming the file, not a connector that offers a format in a
158
+ * dropdown and then reads the file as JSON.
159
+ *
160
+ * It throws as well as failing to compile, because a connector config is JSON
161
+ * that outlives the build that wrote it: a `format` stored by a newer deployment
162
+ * and read by an older one is possible, and falling back to a default for it
163
+ * would be exactly the silent path this closes.
164
+ */
165
+ function unreachableSourceFormat(format, where) {
166
+ 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.`);
167
+ }
96
168
  /**
97
169
  * TypeScript is Node's own type stripping, so it costs no compiler and no build
98
170
  * step — and types are erased, never checked. A transform with a wrong type
@@ -321,6 +393,109 @@ function workflowColumnX(column) {
321
393
  function workflowRowY(row) {
322
394
  return row * (exports.WORKFLOW_NODE_HEIGHT + exports.WORKFLOW_ROW_GAP);
323
395
  }
396
+ /**
397
+ * What a {@link WorkflowCallNode} puts on the wire, and the whole of it.
398
+ *
399
+ * ## Why there is a second mode at all
400
+ *
401
+ * The catalog could not call a workflow that does not know about the catalog.
402
+ * A `call` node wraps the author's `config` in a {@link WorkflowCallEnvelope},
403
+ * so a workflow that already exists — one registered years before this package,
404
+ * whose body reads `data["proc"]` — receives `{catalog: {...}, input: {proc:
405
+ * ...}}` and dies on the first key it looks for. The only repair available was
406
+ * to edit the callee, which inverts the dependency exactly the wrong way round:
407
+ * every workflow anybody wanted to call would have to start depending on this
408
+ * package's contract, and a Python workflow registered in another repository
409
+ * would have to be changed to be reachable from a graph.
410
+ *
411
+ * ## Why the nesting is not being loosened instead
412
+ *
413
+ * The envelope nests for one stated reason, which is on {@link
414
+ * WorkflowCallEnvelope}: an author's parameter called `runId` must not be able
415
+ * to shadow the run id. That reason is sound and it is not being weakened. It
416
+ * simply does not reach the plain mode, because a plain call sends **no catalog
417
+ * metadata at all** — there is no `runId`, no `nodeId`, no contract number on
418
+ * the wire, so there is nothing a parameter could shadow. The flat payload is
419
+ * not the envelope with its guard removed; it is a different, smaller promise.
420
+ *
421
+ * ## What the plain mode costs, which is not small
422
+ *
423
+ * No `runId` and no `nodeId` means the callee has no key to stage rows under.
424
+ * Rows travel through the stage store addressed by `(runId, nodeId, batch)` —
425
+ * see {@link WorkflowStageRef} — and a callee that was told neither cannot
426
+ * write where the next node would read. So a plain call **cannot return rows to
427
+ * the graph**, and that is not a convention anybody could follow more carefully:
428
+ * it is arithmetic. `validateWorkflow` refuses a plain call with an outbound
429
+ * edge for exactly this reason (`call-plain-has-output`), and its return value
430
+ * is not read as a row count — see {@link readWorkflowCallOutput} for the shape
431
+ * that is deliberately *not* consulted on this path.
432
+ *
433
+ * A plain call is therefore for its **effect**: run the thing, and let something
434
+ * else in the graph produce what gets committed.
435
+ *
436
+ * ## Why a mode on the node rather than a second node kind or a boolean
437
+ *
438
+ * A boolean is the shape {@link WORKFLOW_PREDICATE_KINDS} argues against one
439
+ * level down, and for the reason it gives: a `plain?: boolean` beside a future
440
+ * third wire format is two optional flags whose combinations nobody defined, and
441
+ * every reader invents its own rule for which wins. A closed list with an
442
+ * exhaustiveness guard ({@link unreachableCallMode}) makes a third format a
443
+ * compile error naming the files that have to answer for it.
444
+ *
445
+ * A second node *kind* was the other candidate and it is too big. The kind list
446
+ * is deliberately small and every entry earns it by doing something no wiring
447
+ * can express (see {@link WORKFLOW_NODE_KINDS}). A plain call does the same
448
+ * thing a call does at the level the graph reasons about — it hands this
449
+ * position to a workflow somebody else registered, pinned by name and version.
450
+ * What differs is the payload. Splitting the kind would duplicate `callName`,
451
+ * `callVersion`, `config`, the pin check, the picker, the plan entry and the
452
+ * canvas node for a difference of one field, and every place that today writes
453
+ * `node.kind === 'call'` would have to remember to write both — which is the
454
+ * hand-maintained list going quiet that {@link NODE_KIND_IS_REUSABLE} exists to
455
+ * stop.
456
+ */
457
+ exports.WORKFLOW_CALL_MODES = [
458
+ /**
459
+ * The child is handed a {@link WorkflowCallEnvelope}: the catalog's metadata
460
+ * under `catalog`, the author's parameters under `input`. The callee can stage
461
+ * rows back for the graph, and it has to have been written for this catalog.
462
+ */
463
+ 'envelope',
464
+ /**
465
+ * The child is handed {@link WorkflowCallNode.config} verbatim, with nothing
466
+ * added and nothing wrapped. The callee needs to know nothing about the
467
+ * catalog — and cannot return rows to it.
468
+ */
469
+ 'plain',
470
+ ];
471
+ /** Same reason as {@link isConnectorKind}: one list, no second copy to drift. */
472
+ function isWorkflowCallMode(value) {
473
+ return exports.WORKFLOW_CALL_MODES.some((mode) => mode === value);
474
+ }
475
+ /**
476
+ * {@link unreachableNodeKind}, one level down, and for the identical reason.
477
+ *
478
+ * Every branch over {@link WorkflowCallMode} ends here, so a third wire format
479
+ * added to the list without a rule for building its payload, hashing it,
480
+ * validating it or reading its answer is a type error naming the file. It throws
481
+ * as well, because a mode arrives as JSON out of a column and a build older than
482
+ * the data is a thing that happens.
483
+ */
484
+ function unreachableCallMode(mode, where) {
485
+ 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.`);
486
+ }
487
+ /**
488
+ * The mode this call node runs in, with the default applied once.
489
+ *
490
+ * Absent means `'envelope'` — that is what every node stored before the field
491
+ * existed is, and reading it as anything else would silently change what a
492
+ * deployment's graphs already do. One function so that the store, the runner,
493
+ * the hash and the canvas cannot each carry their own `?? 'envelope'` and have
494
+ * one of them drift.
495
+ */
496
+ function workflowCallMode(node) {
497
+ return node.callMode ?? 'envelope';
498
+ }
324
499
  /**
325
500
  * The kinds of test an {@link WorkflowIfNode} can make.
326
501
  *
@@ -1169,6 +1344,18 @@ exports.WORKFLOW_CALL_CONTRACT = 1;
1169
1344
  * schema for a workflow's output anywhere in the durable contract, and no way
1170
1345
  * to reach one if there were. So the check is here, at the one moment the
1171
1346
  * answer exists, and it names what it saw.
1347
+ *
1348
+ * ## Not called at all for a plain call, which is a decision and not an omission
1349
+ *
1350
+ * A plain call is handed no run id and no node id, so its callee could not have
1351
+ * staged anything under `(runId, nodeId, batch)` even if it wanted to. Running
1352
+ * this over its answer would be worse than pointless in both directions: a
1353
+ * callee that happens to return `{batches, rowCount}` meaning something else
1354
+ * entirely would have this graph go and read a stage that does not exist, and a
1355
+ * callee returning one of the two would fail the node over a key it was never
1356
+ * told about. So the plain path reports zero rows unconditionally and reads
1357
+ * nothing — see `WorkflowRunnerService.callOutput`, which is where that is
1358
+ * enforced rather than merely intended.
1172
1359
  */
1173
1360
  function readWorkflowCallOutput(value) {
1174
1361
  if (typeof value !== 'object' || value === null)
@@ -1223,6 +1410,13 @@ exports.WORKFLOW_ISSUE_CODES = [
1223
1410
  'dead-end',
1224
1411
  'transform-not-named',
1225
1412
  'call-not-named',
1413
+ /**
1414
+ * A plain call wired into something. See {@link WORKFLOW_CALL_MODES}: a plain
1415
+ * call is told no run id and no node id, so it has nowhere to stage rows and
1416
+ * always passes on none — and every node that can sit downstream of a call
1417
+ * consumes rows and nothing else.
1418
+ */
1419
+ 'call-plain-has-output',
1226
1420
  'if-not-named',
1227
1421
  'if-threshold-invalid',
1228
1422
  'if-needs-one-input',
@@ -1279,11 +1473,17 @@ function validateWorkflow(graph) {
1279
1473
  return issues;
1280
1474
  const { outgoing, incoming } = buildAdjacency(nodes, edges);
1281
1475
  const originators = nodes.filter(originatesRows);
1476
+ // Deliberately a *different* set from `originators` — see `runsWithoutInput`.
1477
+ const roots = nodes.filter(runsWithoutInput);
1282
1478
  const sinks = nodes.filter((node) => node.kind === 'sink');
1283
1479
  checkNodeWiring(nodes, incoming, outgoing, issues);
1284
1480
  checkEndpoints(originators, sinks, issues);
1285
1481
  checkBranches(edges, byId, issues);
1286
- checkFilterNarrowing({ nodes, edges }, originators, outgoing, issues);
1482
+ checkPlainCallOutputs(nodes, outgoing, byId, issues);
1483
+ // `roots` rather than `originators`, because this walks the graph forwards to
1484
+ // find which sinks a filter can narrow and a plain call is a perfectly
1485
+ // ordinary ancestor of nothing at all — it just never contributes rows.
1486
+ checkFilterNarrowing({ nodes, edges }, roots, outgoing, issues);
1287
1487
  const looped = findCycle(nodes, incoming, outgoing);
1288
1488
  if (looped) {
1289
1489
  issues.push({
@@ -1295,27 +1495,127 @@ function validateWorkflow(graph) {
1295
1495
  // only unreachable *because* of the cycle, which points at the wrong boxes.
1296
1496
  return issues;
1297
1497
  }
1298
- checkReachability(nodes, originators, sinks, incoming, outgoing, issues);
1498
+ checkReachability(nodes, roots, sinks, incoming, outgoing, issues);
1299
1499
  return issues;
1300
1500
  }
1501
+ /**
1502
+ * A plain call may not feed anything, and this is where that is refused.
1503
+ *
1504
+ * ## The rule, stated once
1505
+ *
1506
+ * **A call node in `plain` mode must have no outbound edge.** Not "must not feed
1507
+ * a sink", not "must not be the only thing feeding a sink" — no outbound edge at
1508
+ * all, and the reason it collapses that far is that there is no weaker version
1509
+ * of it that means anything. Every node kind that can sit downstream of a call —
1510
+ * transform, if, filter, sink — consumes rows and *only* rows. There is no
1511
+ * ordering-only wire in this model. So "a plain call with downstream nodes
1512
+ * expecting rows" and "a plain call with an outbound edge" are the same set.
1513
+ *
1514
+ * ## How it lands against the rest of the validator
1515
+ *
1516
+ * Three rules had to move for this one to be statable, and each moved in a way
1517
+ * that is narrower than it looks:
1518
+ *
1519
+ * - **`no-source`.** A plain call is no longer something that "reads": see
1520
+ * {@link originatesRows}. Without that, a graph of `plain call → sink` would
1521
+ * have passed the check that a graph has something producing rows, and then
1522
+ * committed an empty snapshot over whatever was live. It is refused here
1523
+ * first, and would be refused by `no-source` even if this check were deleted.
1524
+ * - **`dead-end` — every path reaches the sink.** A plain call reaches no sink
1525
+ * by construction, so it is exempt, and the exemption is exactly one node
1526
+ * wide: nothing can be *behind* a plain call, because a plain call has no
1527
+ * outbound edge, so no other node's route to the sink can run through one.
1528
+ * The message `dead-end` carries is "it would be computed and thrown away",
1529
+ * and that is precisely what a plain call is not — its effect is the point,
1530
+ * and it has already happened by the time the sink commits.
1531
+ * - **the one-sink rule.** Untouched. A graph still needs a sink and still needs
1532
+ * something that originates rows, and a plain call is now neither, so plain
1533
+ * calls cannot be a graph on their own — the rows come from a source or from
1534
+ * an envelope call, exactly as before.
1535
+ *
1536
+ * What a legal plain call looks like, then: `source → sink` with `source →
1537
+ * plainCall` beside it — the effect runs after the source and the load commits
1538
+ * the source's rows — or a plain call with nothing wired to it at all, which
1539
+ * runs at some point in the topological order and is reported like any other
1540
+ * node. Wiring a source into a plain call that is the source's *only* outbound
1541
+ * edge is still refused, by `dead-end`, pointed at the source: those rows really
1542
+ * would be fetched and dropped.
1543
+ */
1544
+ function checkPlainCallOutputs(nodes, outgoing, byId, issues) {
1545
+ for (const node of nodes) {
1546
+ if (node.kind !== 'call' || workflowCallMode(node) !== 'plain')
1547
+ continue;
1548
+ const fed = outgoing.get(node.id) ?? [];
1549
+ if (fed.length === 0)
1550
+ continue;
1551
+ issues.push({
1552
+ code: 'call-plain-has-output',
1553
+ nodeIds: [node.id, ...fed],
1554
+ 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.`,
1555
+ });
1556
+ }
1557
+ }
1558
+ /** `"a" (n1) and "b" (n2)`, for a message that has to name several boxes. */
1559
+ function listNodes(ids, byId) {
1560
+ return ids
1561
+ .map((id) => {
1562
+ const node = byId.get(id);
1563
+ return node ? `"${node.name}" (${id})` : `"${id}"`;
1564
+ })
1565
+ .join(' and ');
1566
+ }
1301
1567
  /**
1302
1568
  * Whether a node can produce rows without anything wired into it.
1303
1569
  *
1304
- * A source obviously can. A **call** node can too, and this is the one rule the
1305
- * `call` kind changes rather than extends: the workflow it hands off to may
1306
- * itself read from a system, so a graph of `call → sink` is a real pipeline and
1307
- * refusing it for having "no source" would be false. What is not weakened is
1570
+ * A source obviously can. An **envelope call** node can too, and this is the one
1571
+ * rule the `call` kind changes rather than extends: the workflow it hands off to
1572
+ * may itself read from a system, so a graph of `call → sink` is a real pipeline
1573
+ * and refusing it for having "no source" would be false. What is not weakened is
1308
1574
  * that a graph still needs *something* that originates rows and *something*
1309
1575
  * that commits them — a graph of transforms alone is still refused.
1310
1576
  *
1311
- * Every call node counts, not only the ones with no inbound edge, and that is
1312
- * the conservative direction: it makes this the root set for reachability too,
1313
- * so a mid-graph call node cannot make everything downstream of it look
1314
- * unreachable when its own upstream is fine.
1577
+ * A **plain** call is not one of them, and that is the load-bearing half of this
1578
+ * function now. A plain call is told no run id and no node id, so it has no key
1579
+ * to stage rows under and cannot produce any see {@link WORKFLOW_CALL_MODES}.
1580
+ * Counting it here would let `plain call → sink` past `no-source` and commit an
1581
+ * empty snapshot over whatever was live, which is the exact silence this file is
1582
+ * arranged against.
1583
+ *
1584
+ * ## This used to be the reachability root set as well, and no longer is
1585
+ *
1586
+ * It said so, and the reason it gave was that it made the root set conservative.
1587
+ * The plain mode splits the two questions, because the answers genuinely differ:
1588
+ * a plain call **runs** with nothing wired into it (so it is a root, and calling
1589
+ * it unreachable would be false — it would run) and **produces nothing** (so it
1590
+ * is not something that reads). One function answering both would have to be
1591
+ * wrong about one of them. See {@link runsWithoutInput} for the other half.
1315
1592
  */
1316
1593
  function originatesRows(node) {
1594
+ if (node.kind === 'source')
1595
+ return true;
1596
+ return node.kind === 'call' && workflowCallMode(node) === 'envelope';
1597
+ }
1598
+ /**
1599
+ * Whether a node runs whether or not anything is wired into it.
1600
+ *
1601
+ * The root set for reachability, which used to be {@link originatesRows} and is
1602
+ * now its own question — see the note there. Every call node is one of these,
1603
+ * both modes: a call with no inbound edge sits at in-degree zero in the
1604
+ * topological order and is dispatched like anything else, so reporting it as
1605
+ * "not reachable from any source, so it would never run" would be a message that
1606
+ * is simply untrue.
1607
+ *
1608
+ * Every call node rather than only the unwired ones, for the reason the old
1609
+ * function gave: it keeps a mid-graph call node from making everything
1610
+ * downstream of it look unreachable when its own upstream is fine.
1611
+ */
1612
+ function runsWithoutInput(node) {
1317
1613
  return node.kind === 'source' || node.kind === 'call';
1318
1614
  }
1615
+ /** Whether this node is a call that can never hand rows back to the graph. */
1616
+ function isPlainCall(node) {
1617
+ return node.kind === 'call' && workflowCallMode(node) === 'plain';
1618
+ }
1319
1619
  /**
1320
1620
  * Index the nodes by id, reporting the ids that cannot be used as one.
1321
1621
  *
@@ -1852,12 +2152,17 @@ function peelTails(leftover, outgoing) {
1852
2152
  }
1853
2153
  return leftover;
1854
2154
  }
1855
- /** Nodes that nothing reading reaches, and nodes that reach no sink. */
1856
- function checkReachability(nodes, originators, sinks, incoming, outgoing, issues) {
1857
- const reachableFromSources = walk(originators.map((node) => node.id), outgoing);
2155
+ /**
2156
+ * Nodes that nothing reading reaches, and nodes that reach no sink.
2157
+ *
2158
+ * `roots` is {@link runsWithoutInput} and not {@link originatesRows}: this asks
2159
+ * what would *run*, and a plain call runs whether anything feeds it or not.
2160
+ */
2161
+ function checkReachability(nodes, roots, sinks, incoming, outgoing, issues) {
2162
+ const reachableFromSources = walk(roots.map((node) => node.id), outgoing);
1858
2163
  const reachesASink = walk(sinks.map((sink) => sink.id), incoming);
1859
2164
  for (const node of nodes) {
1860
- if (originators.length > 0 && !reachableFromSources.has(node.id)) {
2165
+ if (roots.length > 0 && !reachableFromSources.has(node.id)) {
1861
2166
  issues.push({
1862
2167
  code: 'unreachable',
1863
2168
  nodeIds: [node.id],
@@ -1865,6 +2170,15 @@ function checkReachability(nodes, originators, sinks, incoming, outgoing, issues
1865
2170
  });
1866
2171
  continue;
1867
2172
  }
2173
+ // The one exemption the plain mode buys, and it is exactly one node wide.
2174
+ // A plain call reaches no sink by construction — `call-plain-has-output`
2175
+ // refuses it an outbound edge — so `dead-end` would fire on every one of
2176
+ // them, with a message ("it would be computed and thrown away") that is
2177
+ // false about it: the effect it was run for has happened. Nothing can hide
2178
+ // behind this, because nothing can be downstream of a plain call, so no
2179
+ // other node's route to the sink can run through one.
2180
+ if (isPlainCall(node))
2181
+ continue;
1868
2182
  if (sinks.length > 0 && !reachesASink.has(node.id)) {
1869
2183
  issues.push({
1870
2184
  code: 'dead-end',
@@ -2100,6 +2414,13 @@ function canonicalNode(node) {
2100
2414
  node.callName,
2101
2415
  node.callVersion,
2102
2416
  sortedEntries(node.config),
2417
+ // Appended only for the non-default mode, exactly as `edge.branch` above
2418
+ // is appended only when there is a label. Every call node in every
2419
+ // deployment today is an envelope call — whether it says so or says
2420
+ // nothing — so every one of them hashes to the string it always did and
2421
+ // no stored graph is renumbered by picking up this release. See
2422
+ // `canonicalCallMode` for why the two spellings must fold together.
2423
+ ...canonicalCallMode(workflowCallMode(node)),
2103
2424
  ]);
2104
2425
  }
2105
2426
  if (node.kind === 'if') {
@@ -2144,6 +2465,27 @@ function canonicalNode(node) {
2144
2465
  * no version bump and no diff — which is precisely the silence this feature was
2145
2466
  * built to end.
2146
2467
  */
2468
+ /**
2469
+ * The call mode, as zero or one trailing hash component.
2470
+ *
2471
+ * Zero for `envelope`, and that is the opposite choice from {@link
2472
+ * canonicalReuse} beside it — for the opposite reason. There, absent and present
2473
+ * mean genuinely different things ("follow the latest" against "pinned to v1"),
2474
+ * so they must hash differently. Here absent and `'envelope'` are one behaviour
2475
+ * spelled two ways: a node that says `callMode: 'envelope'` puts precisely the
2476
+ * same bytes on the wire as a node that says nothing. A fingerprint that told
2477
+ * them apart would report an edit when a canvas normalised the field, which is
2478
+ * the cosmetic version bump {@link workflowGraphHash} exists to not do.
2479
+ *
2480
+ * `plain` earns its component, because it changes what the child receives.
2481
+ */
2482
+ function canonicalCallMode(mode) {
2483
+ if (mode === 'envelope')
2484
+ return [];
2485
+ if (mode === 'plain')
2486
+ return ['plain'];
2487
+ return unreachableCallMode(mode, 'workflowGraphHash');
2488
+ }
2147
2489
  function canonicalReuse(node) {
2148
2490
  if (node.useId === undefined)
2149
2491
  return [];
@@ -2252,18 +2594,8 @@ function isWorkflowNode(value) {
2252
2594
  if (kind === 'sink') {
2253
2595
  return typeof Reflect.get(value, 'targetType') === 'string';
2254
2596
  }
2255
- if (kind === 'call') {
2256
- // Both strings, and the config object, exactly as strictly as a source's:
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
- }
2597
+ if (kind === 'call')
2598
+ return isCallNodeShape(value);
2267
2599
  if (kind === 'if') {
2268
2600
  // The predicate in full, refused rather than defaulted: a gate read back
2269
2601
  // without a test it recognises would have to invent one, and inventing one
@@ -2282,6 +2614,34 @@ function isWorkflowNode(value) {
2282
2614
  }
2283
2615
  return isWorkflowNodeKindUnhandled(kind);
2284
2616
  }
2617
+ /**
2618
+ * Everything a `call` node carries, checked as strictly as a source's.
2619
+ *
2620
+ * Its own function rather than a branch of {@link isWorkflowNode}, which the
2621
+ * complexity bound will not hold any more of — and the split is where it should
2622
+ * be, because this is the kind with the most to check.
2623
+ *
2624
+ * A stored call node missing its version is a node that would run whatever is
2625
+ * registered today, which is the failure the pin exists to remove, and a graph
2626
+ * that half-narrows is a load that runs nine nodes of ten. A `callMode` that is
2627
+ * present and unrecognised is refused rather than dropped, for the reason an
2628
+ * unrecognised `edge.branch` is: reading it back as the default would turn a
2629
+ * plain call into an envelope call silently, and the callee would be handed a
2630
+ * payload nobody authored. Absent is accepted and always will be — it is what
2631
+ * every call node written before the field existed carries, and it means the
2632
+ * envelope, which is what those nodes have always sent.
2633
+ */
2634
+ function isCallNodeShape(value) {
2635
+ const callMode = Reflect.get(value, 'callMode');
2636
+ if (callMode !== undefined && !isWorkflowCallMode(callMode))
2637
+ return false;
2638
+ const config = Reflect.get(value, 'config');
2639
+ return (typeof Reflect.get(value, 'callName') === 'string' &&
2640
+ typeof Reflect.get(value, 'callVersion') === 'string' &&
2641
+ typeof config === 'object' &&
2642
+ config !== null &&
2643
+ !Array.isArray(config));
2644
+ }
2285
2645
  /**
2286
2646
  * Whether a stored `narrows` is one this build can read.
2287
2647
  *
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.WORKFLOW_PREDICATE_KINDS = exports.WORKFLOW_BRANCH_LABELS = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_EXECUTION_MODES = 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.WORKFLOW_CALL_CONTRACT = exports.readWorkflowCallOutput = exports.TRANSFORM_LANGUAGES = exports.REDACTED_SECRET = exports.liveWorkflowVersion = exports.isWorkflowNode = exports.isWorkflowEdge = exports.isTransformLanguage = 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 = 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.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = 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.isTransformLanguage = 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.QueryCache = exports.isColumnarStageBatch = exports.encodeStageRows = exports.decodeStageRows = exports.classifyStagePayload = exports.STAGE_ENCODING_VERSION = exports.STAGE_ENCODING = exports.workflowRunOrder = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowGraphHash = exports.workflowFilterMatches = 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_CONTRACT = exports.WORKFLOW_BRANCH_LABELS = exports.validateWorkflow = exports.unreachablePredicateKind = exports.unreachableNodeKind = 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.isWorkflowNode = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = void 0;
19
- exports.supportsCarryForward = exports.physicalColumn = exports.outputAlias = exports.isWriteStore = exports.isSafeIdentifier = exports.isReservedColumn = exports.isCatalogStoreCapabilities = 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 = void 0;
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.19.0",
3
+ "version": "0.21.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",