@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.
@@ -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
- /** Parameters the author typed, handed to the child under `input`. */
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;
@@ -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
- checkFilterNarrowing({ nodes, edges }, originators, outgoing, issues);
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, originators, sinks, incoming, outgoing, issues);
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. 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
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
- * 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.
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
- /** 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);
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 (originators.length > 0 && !reachableFromSources.has(node.id)) {
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
- // 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
- }
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.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.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",