@dudousxd/nestjs-catalog 0.24.0 → 0.26.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.
@@ -75,6 +75,58 @@ export interface CatalogEnvironment {
75
75
  * `obj_<type>`) and carry no environment in them, so two environments in one
76
76
  * database would collide on every table. Separate databases make the
77
77
  * collision impossible and make MySQL's own `GRANT` the enforcement point.
78
+ *
79
+ * ## PostgreSQL keeps this exactly, and there the choice is a real one
80
+ *
81
+ * The sentence above leans on MySQL not distinguishing the two words. Postgres
82
+ * does distinguish them, and in a way that looks like an invitation: one
83
+ * connection reaches many schemas, which MySQL cannot do, so each environment
84
+ * could be a schema in one database behind one connection pool. That is
85
+ * cheaper — one pool instead of N — and it is refused.
86
+ *
87
+ * **The property that has to survive is the one this file is built around:
88
+ * there is no ambient default, and a cross-environment read is impossible
89
+ * because the database makes it so rather than because the application was
90
+ * careful.** Schema-per-environment cannot keep it, by either of the two
91
+ * routes available.
92
+ *
93
+ * *Route one, `search_path`.* Isolation then rests on a session variable on a
94
+ * pooled connection — and that is not a hypothetical hazard here, it is one
95
+ * this codebase has already measured and written up. `runReadOnlyQuery` in the
96
+ * MikroORM store deliberately passes its statement timeout as a per-statement
97
+ * hint rather than `SET SESSION`, because the session form was observed riding
98
+ * the pooled connection into an unrelated request: "after one query-console
99
+ * request, a *different* `em.fork()` read `@@SESSION.MAX_EXECUTION_TIME` back
100
+ * as the value set here". A leaked `MAX_EXECUTION_TIME` is a slow query. A
101
+ * leaked `search_path` is dev's request answered out of production's schema,
102
+ * returning entirely plausible rows, which is the failure
103
+ * {@link resolveEnvironment} exists to make impossible.
104
+ *
105
+ * *Route two, qualify every identifier.* Then isolation is a prefix that has to
106
+ * be present on every statement — which is the same class of thing as a
107
+ * `WHERE` clause, and this interface's own docblock says why that is refused:
108
+ * "there is no field here that a `WHERE` clause could be built out of, because
109
+ * a filter is precisely the sort of isolation that fails silently the one time
110
+ * somebody forgets it". A forgotten schema qualifier is a forgotten filter.
111
+ *
112
+ * And `GRANT` cannot rescue either route, which is the argument that actually
113
+ * settles it. One connection pool is one role; if that role can reach both
114
+ * schemas — which is what "one connection reaches many schemas" *means* — then
115
+ * `GRANT` is enforcing nothing between them. Making it the enforcement point
116
+ * again requires a role per environment, a role per environment requires a
117
+ * connection per environment, and at that point the shared pool that motivated
118
+ * the whole idea is gone and separate databases cost nothing extra.
119
+ *
120
+ * **What it costs:** N connection pools on Postgres, the same as on MySQL, and
121
+ * no cross-environment SQL join. The second is a feature — data never moves
122
+ * between environments — and the first is the price of the guarantee.
123
+ *
124
+ * **What an operator has to know:** nothing new. The deployment story is the
125
+ * same on both engines, which is the main thing this choice buys: one
126
+ * `catalogDatabaseNameFor`, one `ensureDatabase`, one shape of `GRANT`, and no
127
+ * per-engine paragraph in a runbook. The genuine Postgres/MySQL differences
128
+ * live in the store's `dialect.ts` and are about column case and search, not
129
+ * about isolation.
78
130
  */
79
131
  databaseName: string;
80
132
  /**
@@ -77,15 +77,43 @@ const ENVIRONMENT_ID_PATTERN = /^[a-z][a-z0-9_]{0,23}$/;
77
77
  * module refuses it as a tenant: "default" is the value that means "no
78
78
  * namespace at all", so an environment called `default` would derive the bare
79
79
  * keyspace and quietly share a results queue with every other engine on the
80
- * Redis. The rest are MySQL's own schemas, which an environment must never be
81
- * pointed at.
80
+ * Redis.
81
+ *
82
+ * The rest are databases the *engine* owns, and an environment must never be
83
+ * pointed at one — an environment id becomes a database name, so `mysql` or
84
+ * `postgres` here means this package running `CREATE TABLE catalog_object_type`
85
+ * inside the server's own maintenance database.
86
+ *
87
+ * **Both engines' lists, on both engines, deliberately.** The alternative is a
88
+ * refusal that depends on which driver happens to be mounted, and that is the
89
+ * shape that bites during a migration: an environment named `postgres` is
90
+ * perfectly legal on MySQL today and becomes a live incident on the day somebody
91
+ * moves the deployment, at which point renaming an environment means renaming
92
+ * its database, its MikroORM context and its Redis keyspace. Refusing the union
93
+ * costs a deployment nothing — nobody wants an environment called
94
+ * `information_schema` — and keeps the answer the same everywhere.
95
+ *
96
+ * `template0` and `template1` are Postgres's own, and are the two most likely to
97
+ * be typed by accident by somebody who has just read a `createdb` man page.
82
98
  */
83
99
  const RESERVED_ENVIRONMENT_IDS = [
84
100
  'default',
101
+ // MySQL's.
85
102
  'information_schema',
86
103
  'mysql',
87
104
  'performance_schema',
88
105
  'sys',
106
+ // PostgreSQL's. `postgres` is the maintenance database every cluster ships
107
+ // with and the one a client connects to when it has nowhere else to go.
108
+ 'postgres',
109
+ 'template0',
110
+ 'template1',
111
+ // Not a database but a schema, and reserved because a Postgres deployment
112
+ // that ever did put environments in schemas would collide with the default
113
+ // one — see the note on `databaseName` for why this package does not.
114
+ 'public',
115
+ 'pg_catalog',
116
+ 'pg_toast',
89
117
  ];
90
118
  function isEnvironmentId(value) {
91
119
  return (typeof value === 'string' &&
@@ -15,7 +15,7 @@ import { type CatalogRevision } from './catalog.workspace';
15
15
  * execute — a kind that exists in the type and throws at run time is worse than
16
16
  * one that is absent, because the first looks supported in a dropdown.
17
17
  */
18
- export declare const CONNECTOR_KINDS: readonly ["http", "sql", "file", "s3", "inline"];
18
+ export declare const CONNECTOR_KINDS: readonly ["http", "sql", "file", "s3", "inline", "catalog"];
19
19
  export type ConnectorKind = (typeof CONNECTOR_KINDS)[number];
20
20
  /**
21
21
  * The type is derived from the list, not written beside it.
@@ -27,6 +27,42 @@ 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
+ * The connector kind that never compiles quietly.
32
+ *
33
+ * The {@link unreachableNodeKind} of source kinds, and it arrived with
34
+ * `'catalog'` for the reason that kind arrived: two of the places that decide
35
+ * something *per source kind* — the fetcher map and the column question below —
36
+ * were keyed by `string` or answered for `source` as a whole, so a sixth kind
37
+ * could be added and be picked up by neither. A palette that offers a kind
38
+ * nothing can read is the failure {@link CONNECTOR_KINDS} opens by describing,
39
+ * one level down.
40
+ *
41
+ * It throws as well as failing to compile, for the reason its sibling does: a
42
+ * connector's `kind` is a string in a database row, so one written by a newer
43
+ * deployment and read by an older one is possible, and returning a default for
44
+ * it would read the wrong system entirely.
45
+ */
46
+ export declare function unreachableConnectorKind(kind: never, where: string): never;
47
+ /**
48
+ * The config key a `catalog` source names its object type in.
49
+ *
50
+ * A constant rather than a literal in four files, because it is the one field
51
+ * that kind has and it is written by a form, read by a fetcher, checked by a
52
+ * validator and hashed into the graph's fingerprint.
53
+ */
54
+ export declare const CATALOG_SOURCE_TYPE_KEY = "objectType";
55
+ /**
56
+ * Which object type a source reads, when it is a `catalog` source that names one.
57
+ *
58
+ * `undefined` covers both "not that kind" and "that kind, unconfigured", and the
59
+ * two callers want the same thing from both: a source that does not name a type
60
+ * is not one whose columns are known, and it is one the validator refuses. The
61
+ * string is trimmed, because a name that differs from a published type only by
62
+ * surrounding whitespace is a load that resolves nothing at run time and a
63
+ * refusal nobody can see the cause of.
64
+ */
65
+ export declare function workflowSourceObjectType(node: WorkflowNode | Record<string, unknown>): string | undefined;
30
66
  /**
31
67
  * How the bytes behind a `file` or `s3` connector are read as records.
32
68
  *
@@ -3174,7 +3210,7 @@ export interface CallableWorkflowBlock {
3174
3210
  }
3175
3211
  export declare function callableWorkflowBlock(ref: CallableWorkflowRef): CallableWorkflowBlock | undefined;
3176
3212
  /** Every way a graph can be refused. Exported so a canvas can key off the code. */
3177
- 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", "rename-invalid", "column-not-produced", "version-pin-invalid"];
3213
+ 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", "source-type-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", "rename-invalid", "column-not-produced", "version-pin-invalid"];
3178
3214
  export type WorkflowIssueCode = (typeof WORKFLOW_ISSUE_CODES)[number];
3179
3215
  export interface WorkflowValidationIssue {
3180
3216
  code: WorkflowIssueCode;
@@ -3203,8 +3239,16 @@ export interface WorkflowValidationIssue {
3203
3239
  * point at nodes which do not exist produces a second page of consequences, and
3204
3240
  * burying the one real problem under them is how a validation message stops
3205
3241
  * being read.
3242
+ *
3243
+ * `knowledge` is optional and adds only refusals that could not otherwise be
3244
+ * made: with it, a filter or a rename below a `catalog` source can be told it
3245
+ * names a column the published type does not have. Omitting it is a supported
3246
+ * call and the answer is a subset, never a different one — see
3247
+ * {@link WorkflowColumnKnowledge}. The pure, dependency-free promise this
3248
+ * function opens with is unchanged: the lookup is the caller's, and this reaches
3249
+ * nothing.
3206
3250
  */
3207
- export declare function validateWorkflow(graph: WorkflowGraph): WorkflowValidationIssue[];
3251
+ export declare function validateWorkflow(graph: WorkflowGraph, knowledge?: WorkflowColumnKnowledge): WorkflowValidationIssue[];
3208
3252
  /**
3209
3253
  * The object types whose whole published snapshot a node stands in front of.
3210
3254
  *
@@ -3371,9 +3415,23 @@ export declare function workflowFilterColumns(predicate: WorkflowFilterPredicate
3371
3415
  * with some keys re-labelled, and its input is unknown unless something
3372
3416
  * upstream closed it. So `undefined` propagates, and that is the honest
3373
3417
  * answer rather than an empty set.
3374
- * - **A source, a transform and a call are always unknown.** A source's shape is
3375
- * discovered against the live system rather than declared in the graph; a
3376
- * transform is a function body; a call is a workflow this graph does not own.
3418
+ * - **A transform and a call are always unknown.** A transform is a function
3419
+ * body; a call is a workflow this graph does not own.
3420
+ * - **A source is unknown, with one exception, and the exception needs a
3421
+ * lookup.** Every kind that reaches an outside system has a shape discovered
3422
+ * against that system rather than declared in the graph. A `catalog` source
3423
+ * is the one kind whose shape is *already published*: it names an object
3424
+ * type, and the type's properties are exactly the keys its records carry —
3425
+ * see `fetchCatalog`, which asks the store for those properties by name.
3426
+ *
3427
+ * But the properties are not in the graph either. The graph holds a type
3428
+ * **name**; the columns live in the catalog's registry, which this function is
3429
+ * pure and dependency-free in order not to reach. So the answer is a lookup
3430
+ * the caller supplies — {@link WorkflowColumnKnowledge} — and with no lookup
3431
+ * the answer stays `undefined`. That is the honest shape of the claim: a
3432
+ * caller that can see the catalog gets column checking through a source, which
3433
+ * nothing else in this file can offer, and a caller that cannot see it is told
3434
+ * nothing rather than told an empty set.
3377
3435
  * - **It says nothing about a sink's declared properties.** That is the check
3378
3436
  * worth wanting — "this sink writes a property no upstream node produces" —
3379
3437
  * and it is *not* available here: a {@link WorkflowSinkNode} carries a
@@ -3385,7 +3443,24 @@ export declare function workflowFilterColumns(predicate: WorkflowFilterPredicate
3385
3443
  * cyclic graph before it gets here, but the canvas calls this while a graph is
3386
3444
  * being drawn and is entitled to a wrong-but-terminating answer.
3387
3445
  */
3388
- export declare function workflowKnownColumns(graph: WorkflowGraph, nodeId: string): ReadonlySet<string> | undefined;
3446
+ export declare function workflowKnownColumns(graph: WorkflowGraph, nodeId: string, knowledge?: WorkflowColumnKnowledge): ReadonlySet<string> | undefined;
3447
+ /**
3448
+ * What a caller can tell the column walk that the graph does not hold.
3449
+ *
3450
+ * One lookup, because there is one thing: the properties of a published object
3451
+ * type, which is what a `catalog` source's records are keyed by. Optional in
3452
+ * every signature that takes it and `undefined` is a supported answer with its
3453
+ * own meaning — "this console cannot see a type by that name" is not "that type
3454
+ * has no columns", and an empty set would be read as the second.
3455
+ *
3456
+ * A lookup rather than a map, so a caller that already holds the types answers
3457
+ * from what it holds, and one that would have to fetch them can decline by not
3458
+ * passing this at all.
3459
+ */
3460
+ export interface WorkflowColumnKnowledge {
3461
+ /** The property names of a published type, or nothing if it cannot be seen. */
3462
+ columnsOfType(typeName: string): Iterable<string> | undefined;
3463
+ }
3389
3464
  /**
3390
3465
  * Narrow a stored node, loudly.
3391
3466
  *
@@ -9,8 +9,10 @@
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_RENAME_MAX_COLUMNS = exports.WORKFLOW_RENAME_UNNAMED = 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_MODES = exports.TRANSFORM_LANGUAGES = exports.SOURCE_FORMATS = 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_RENAME_MAX_COLUMNS = exports.WORKFLOW_RENAME_UNNAMED = 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_MODES = exports.TRANSFORM_LANGUAGES = exports.SOURCE_FORMATS = exports.CATALOG_SOURCE_TYPE_KEY = exports.CONNECTOR_KINDS = void 0;
13
13
  exports.isConnectorKind = isConnectorKind;
14
+ exports.unreachableConnectorKind = unreachableConnectorKind;
15
+ exports.workflowSourceObjectType = workflowSourceObjectType;
14
16
  exports.isSourceFormat = isSourceFormat;
15
17
  exports.unreachableSourceFormat = unreachableSourceFormat;
16
18
  exports.isTransformLanguage = isTransformLanguage;
@@ -103,6 +105,45 @@ exports.CONNECTOR_KINDS = [
103
105
  's3',
104
106
  /** Records pasted into the config. For trying a transform against real shapes. */
105
107
  'inline',
108
+ /**
109
+ * The catalog's own data: the **current snapshot** of one object type.
110
+ *
111
+ * ## Why this is a kind and not a `sql` connector with a clever query
112
+ *
113
+ * Because that is what it was, and it was silently wrong. A workflow that
114
+ * needed rows the catalog already holds had exactly one way to get them — a
115
+ * `sql` connector naming the physical table, `SELECT … FROM obj_subworeplica`
116
+ * — and the store **retains every committed snapshot in that table**. So the
117
+ * read is not the dataset, it is every load that has ever run, stacked.
118
+ *
119
+ * Measured, with two snapshots present: the source read 89,440 rows against a
120
+ * type holding 44,720; the run finished `succeeded`; the rows *written* were
121
+ * unchanged at 16,119 because the downstream `GROUP BY` collapsed the
122
+ * duplicates; and every `SUM` doubled — `actualLaborCost` from 212,192,113 to
123
+ * 424,384,226. The row count, which is the one number anybody checks, did not
124
+ * move. The graph had been correct once, by the accident of exactly one
125
+ * snapshot existing at the time it was first run.
126
+ *
127
+ * Three things follow, and each of them is why this is a kind of its own
128
+ * rather than a documented convention about which table to name:
129
+ *
130
+ * - **The author names a type, not a table.** `obj_<type>` and `_snapshot_id`
131
+ * are internal schema. A graph that spells them is coupled to a storage
132
+ * layout it does not own and — as measured — quietly wrong about it.
133
+ * - **There is no URL and no credential.** Every other kind that reaches a
134
+ * database needs an address and a secret, and pointing the catalog at its
135
+ * own database meant an operator putting a connection URL on the pod and on
136
+ * the secret allowlist: a credential that did not need to exist. This kind
137
+ * reads through the store the process already holds.
138
+ * - **"Current" is resolved when the run starts**, by asking the store which
139
+ * snapshot it serves, and a type with nothing committed is refused rather
140
+ * than read as zero rows. See `fetchCatalog` in the pipeline package.
141
+ *
142
+ * Not connectable — see `CONNECTION_KINDS` in the react package. A connection
143
+ * is an address and a credential shared by several loads, and this kind has
144
+ * neither.
145
+ */
146
+ 'catalog',
106
147
  ];
107
148
  /**
108
149
  * The type is derived from the list, not written beside it.
@@ -116,6 +157,59 @@ exports.CONNECTOR_KINDS = [
116
157
  function isConnectorKind(value) {
117
158
  return exports.CONNECTOR_KINDS.some((kind) => kind === value);
118
159
  }
160
+ /**
161
+ * The connector kind that never compiles quietly.
162
+ *
163
+ * The {@link unreachableNodeKind} of source kinds, and it arrived with
164
+ * `'catalog'` for the reason that kind arrived: two of the places that decide
165
+ * something *per source kind* — the fetcher map and the column question below —
166
+ * were keyed by `string` or answered for `source` as a whole, so a sixth kind
167
+ * could be added and be picked up by neither. A palette that offers a kind
168
+ * nothing can read is the failure {@link CONNECTOR_KINDS} opens by describing,
169
+ * one level down.
170
+ *
171
+ * It throws as well as failing to compile, for the reason its sibling does: a
172
+ * connector's `kind` is a string in a database row, so one written by a newer
173
+ * deployment and read by an older one is possible, and returning a default for
174
+ * it would read the wrong system entirely.
175
+ */
176
+ function unreachableConnectorKind(kind, where) {
177
+ throw new Error(`${where} does not handle a source of kind ${JSON.stringify(kind)}. The kind list and every decision made per kind are meant to move together.`);
178
+ }
179
+ /**
180
+ * The config key a `catalog` source names its object type in.
181
+ *
182
+ * A constant rather than a literal in four files, because it is the one field
183
+ * that kind has and it is written by a form, read by a fetcher, checked by a
184
+ * validator and hashed into the graph's fingerprint.
185
+ */
186
+ exports.CATALOG_SOURCE_TYPE_KEY = 'objectType';
187
+ /**
188
+ * Which object type a source reads, when it is a `catalog` source that names one.
189
+ *
190
+ * `undefined` covers both "not that kind" and "that kind, unconfigured", and the
191
+ * two callers want the same thing from both: a source that does not name a type
192
+ * is not one whose columns are known, and it is one the validator refuses. The
193
+ * string is trimmed, because a name that differs from a published type only by
194
+ * surrounding whitespace is a load that resolves nothing at run time and a
195
+ * refusal nobody can see the cause of.
196
+ */
197
+ function workflowSourceObjectType(node) {
198
+ // Both fields read reflectively rather than promised by the signature, for two
199
+ // reasons that point the same way: the parameter has to accept any node of the
200
+ // union — a sink carries neither field — and a node arrives out of a JSON
201
+ // column, where a `config` can be anything at all.
202
+ if (Reflect.get(node, 'sourceKind') !== 'catalog')
203
+ return undefined;
204
+ const config = Reflect.get(node, 'config');
205
+ if (typeof config !== 'object' || config === null)
206
+ return undefined;
207
+ const named = Reflect.get(config, exports.CATALOG_SOURCE_TYPE_KEY);
208
+ if (typeof named !== 'string')
209
+ return undefined;
210
+ const trimmed = named.trim();
211
+ return trimmed.length === 0 ? undefined : trimmed;
212
+ }
119
213
  /**
120
214
  * How the bytes behind a `file` or `s3` connector are read as records.
121
215
  *
@@ -1667,6 +1761,16 @@ exports.WORKFLOW_ISSUE_CODES = [
1667
1761
  'unreachable',
1668
1762
  'dead-end',
1669
1763
  'transform-not-named',
1764
+ /**
1765
+ * A `catalog` source that does not say which object type it reads.
1766
+ *
1767
+ * The sibling of `transform-not-named`, and it earns a code of its own for the
1768
+ * reason that one has one: the field is the *whole* of what the node does, and
1769
+ * a node missing it fails inside a durable step halfway through a load rather
1770
+ * than on the canvas. Refused rather than defaulted — there is no sensible
1771
+ * type to guess, and guessing would read somebody else's data.
1772
+ */
1773
+ 'source-type-not-named',
1670
1774
  'call-not-named',
1671
1775
  /**
1672
1776
  * A plain call wired into something. See {@link WORKFLOW_CALL_MODES}: a plain
@@ -1732,8 +1836,16 @@ exports.WORKFLOW_ISSUE_CODES = [
1732
1836
  * point at nodes which do not exist produces a second page of consequences, and
1733
1837
  * burying the one real problem under them is how a validation message stops
1734
1838
  * being read.
1839
+ *
1840
+ * `knowledge` is optional and adds only refusals that could not otherwise be
1841
+ * made: with it, a filter or a rename below a `catalog` source can be told it
1842
+ * names a column the published type does not have. Omitting it is a supported
1843
+ * call and the answer is a subset, never a different one — see
1844
+ * {@link WorkflowColumnKnowledge}. The pure, dependency-free promise this
1845
+ * function opens with is unchanged: the lookup is the caller's, and this reaches
1846
+ * nothing.
1735
1847
  */
1736
- function validateWorkflow(graph) {
1848
+ function validateWorkflow(graph, knowledge) {
1737
1849
  const issues = [];
1738
1850
  const nodes = graph.nodes ?? [];
1739
1851
  const edges = graph.edges ?? [];
@@ -1779,7 +1891,7 @@ function validateWorkflow(graph) {
1779
1891
  checkReachability(nodes, roots, sinks, incoming, outgoing, issues);
1780
1892
  // After the cycle check has returned, so the walk it does cannot meet a loop
1781
1893
  // on a graph this function has already accepted as acyclic.
1782
- checkColumnsProduced({ nodes, edges }, issues);
1894
+ checkColumnsProduced({ nodes, edges }, issues, knowledge);
1783
1895
  return issues;
1784
1896
  }
1785
1897
  /**
@@ -2116,10 +2228,10 @@ function checkBranches(edges, byId, issues) {
2116
2228
  /**
2117
2229
  * A node that names none of the thing it exists to run.
2118
2230
  *
2119
- * The two kinds that point at something outside themselves — a transform at
2120
- * stored code, a call at a registered workflow and both are reported the same
2121
- * way because they are the same mistake: a box on the canvas with nothing
2122
- * behind it, which looks finished and fails at run time.
2231
+ * The kinds that point at something outside themselves — a transform at stored
2232
+ * code, a call at a registered workflow, a `catalog` source at an object type —
2233
+ * and they are reported the same way because they are the same mistake: a box on
2234
+ * the canvas with nothing behind it, which looks finished and fails at run time.
2123
2235
  */
2124
2236
  function nodeIsUnconfigured(node) {
2125
2237
  if (node.kind === 'transform' && node.transformId.length === 0) {
@@ -2129,6 +2241,20 @@ function nodeIsUnconfigured(node) {
2129
2241
  message: `Transform node "${node.name}" (${node.id}) names no transform, so there is no code for it to run.`,
2130
2242
  };
2131
2243
  }
2244
+ if (node.kind === 'source' && node.sourceKind === 'catalog') {
2245
+ // Only this kind, and only from the config: every other kind's address is
2246
+ // allowed to arrive from a named connection, so a blank field on the node is
2247
+ // not evidence of anything. A `catalog` source has no connection to borrow
2248
+ // from — the type name is the whole configuration — so a blank one is
2249
+ // decidable here.
2250
+ if (workflowSourceObjectType(node) === undefined) {
2251
+ return {
2252
+ code: 'source-type-not-named',
2253
+ nodeIds: [node.id],
2254
+ message: `Source "${node.name}" (${node.id}) reads from the catalog but does not say which object type, so there is nothing for it to read. Name the type on the node; there is no default, because a default would read somebody else's data.`,
2255
+ };
2256
+ }
2257
+ }
2132
2258
  if (node.kind === 'call')
2133
2259
  return callIsUnnamed(node);
2134
2260
  if (node.kind === 'if')
@@ -2938,9 +3064,23 @@ function workflowFilterColumns(predicate) {
2938
3064
  * with some keys re-labelled, and its input is unknown unless something
2939
3065
  * upstream closed it. So `undefined` propagates, and that is the honest
2940
3066
  * answer rather than an empty set.
2941
- * - **A source, a transform and a call are always unknown.** A source's shape is
2942
- * discovered against the live system rather than declared in the graph; a
2943
- * transform is a function body; a call is a workflow this graph does not own.
3067
+ * - **A transform and a call are always unknown.** A transform is a function
3068
+ * body; a call is a workflow this graph does not own.
3069
+ * - **A source is unknown, with one exception, and the exception needs a
3070
+ * lookup.** Every kind that reaches an outside system has a shape discovered
3071
+ * against that system rather than declared in the graph. A `catalog` source
3072
+ * is the one kind whose shape is *already published*: it names an object
3073
+ * type, and the type's properties are exactly the keys its records carry —
3074
+ * see `fetchCatalog`, which asks the store for those properties by name.
3075
+ *
3076
+ * But the properties are not in the graph either. The graph holds a type
3077
+ * **name**; the columns live in the catalog's registry, which this function is
3078
+ * pure and dependency-free in order not to reach. So the answer is a lookup
3079
+ * the caller supplies — {@link WorkflowColumnKnowledge} — and with no lookup
3080
+ * the answer stays `undefined`. That is the honest shape of the claim: a
3081
+ * caller that can see the catalog gets column checking through a source, which
3082
+ * nothing else in this file can offer, and a caller that cannot see it is told
3083
+ * nothing rather than told an empty set.
2944
3084
  * - **It says nothing about a sink's declared properties.** That is the check
2945
3085
  * worth wanting — "this sink writes a property no upstream node produces" —
2946
3086
  * and it is *not* available here: a {@link WorkflowSinkNode} carries a
@@ -2952,7 +3092,7 @@ function workflowFilterColumns(predicate) {
2952
3092
  * cyclic graph before it gets here, but the canvas calls this while a graph is
2953
3093
  * being drawn and is entitled to a wrong-but-terminating answer.
2954
3094
  */
2955
- function workflowKnownColumns(graph, nodeId) {
3095
+ function workflowKnownColumns(graph, nodeId, knowledge) {
2956
3096
  const nodes = graph.nodes ?? [];
2957
3097
  const byId = new Map(nodes.map((node) => [node.id, node]));
2958
3098
  const { incoming } = buildAdjacency(nodes, graph.edges ?? []);
@@ -2969,7 +3109,7 @@ function workflowKnownColumns(graph, nodeId) {
2969
3109
  if (!node)
2970
3110
  return undefined;
2971
3111
  open.add(id);
2972
- const produced = producedColumns(node, () => intoNode(id));
3112
+ const produced = producedColumns(node, () => intoNode(id), knowledge);
2973
3113
  open.delete(id);
2974
3114
  answered.set(id, produced);
2975
3115
  return produced;
@@ -3005,7 +3145,7 @@ function workflowKnownColumns(graph, nodeId) {
3005
3145
  * here is a compile error rather than a silent `undefined` — which would be the
3006
3146
  * *safe* wrong answer and would therefore never be noticed.
3007
3147
  */
3008
- function producedColumns(node, upstream) {
3148
+ function producedColumns(node, upstream, knowledge) {
3009
3149
  if (node.kind === 'rename') {
3010
3150
  if (workflowRenameUnnamed(node) === 'drop')
3011
3151
  return new Set(Object.values(node.columns ?? {}));
@@ -3022,25 +3162,72 @@ function producedColumns(node, upstream) {
3022
3162
  // given, which is what makes a closed set survive one.
3023
3163
  if (node.kind === 'filter' || node.kind === 'if')
3024
3164
  return upstream();
3025
- // A source's shape is discovered against the live system, a transform's is
3026
- // inside a function body, a call's belongs to a workflow this graph does not
3027
- // own, and nothing reads a sink's output. See {@link workflowKnownColumns}.
3028
- if (node.kind === 'source' ||
3029
- node.kind === 'transform' ||
3030
- node.kind === 'call' ||
3031
- node.kind === 'sink') {
3165
+ // A source is the one kind whose answer depends on which *source* kind it is.
3166
+ if (node.kind === 'source')
3167
+ return sourceProducedColumns(node, knowledge);
3168
+ // A transform's shape is inside a function body, a call's belongs to a workflow
3169
+ // this graph does not own, and nothing reads a sink's output. See
3170
+ // {@link workflowKnownColumns}.
3171
+ if (node.kind === 'transform' || node.kind === 'call' || node.kind === 'sink') {
3032
3172
  return undefined;
3033
3173
  }
3034
3174
  return unreachableNodeKind(node, 'workflowKnownColumns');
3035
3175
  }
3176
+ /**
3177
+ * What a source produces, per source kind.
3178
+ *
3179
+ * Exhaustive over {@link CONNECTOR_KINDS} rather than one blanket `undefined`
3180
+ * for the whole node kind, and that is the point of the function existing: the
3181
+ * blanket answer was correct for five kinds and became wrong for the sixth
3182
+ * without anything failing to compile. Ending in
3183
+ * {@link unreachableConnectorKind} makes the seventh a build error here.
3184
+ *
3185
+ * Four of the five outside systems answer `undefined` for the same reason: what
3186
+ * an HTTP endpoint, a file, a bucket or a query produces is discovered against
3187
+ * the live system, and the graph holds an address rather than a shape.
3188
+ *
3189
+ * `inline` answers `undefined` too, and that one is a judgement rather than an
3190
+ * absence. The records are *in the config*, so their keys could be read off
3191
+ * them — but they are a sample somebody pasted to try a transform against, and
3192
+ * a set derived from a sample is not closed: the real load reads the same source
3193
+ * with more records in it and no reason for them to share a key set. Treating
3194
+ * three pasted objects as the definition of a column set would refuse a filter
3195
+ * that is going to be right.
3196
+ *
3197
+ * `catalog` is the one that answers, when a caller supplied the lookup. Its
3198
+ * records are the store's own rows, keyed by the property names of the type it
3199
+ * names — `fetchCatalog` asks for exactly those and the store returns exactly
3200
+ * those — so the set is closed in the sense {@link workflowKnownColumns}
3201
+ * requires: an upper bound that holds whatever is upstream, since nothing is.
3202
+ */
3203
+ function sourceProducedColumns(node, knowledge) {
3204
+ const kind = node.sourceKind;
3205
+ if (kind === 'http' || kind === 'sql' || kind === 'file' || kind === 's3' || kind === 'inline') {
3206
+ return undefined;
3207
+ }
3208
+ if (kind === 'catalog') {
3209
+ const named = workflowSourceObjectType(node);
3210
+ if (named === undefined || knowledge === undefined)
3211
+ return undefined;
3212
+ const columns = knowledge.columnsOfType(named);
3213
+ // Absent means "this caller cannot see a type by that name", which is not
3214
+ // the same as a type with no columns and must not become an empty set — a
3215
+ // graph read by a console that has not loaded its types would otherwise have
3216
+ // every filter below the source refused.
3217
+ return columns === undefined ? undefined : new Set(columns);
3218
+ }
3219
+ return unreachableConnectorKind(kind, 'workflowKnownColumns');
3220
+ }
3036
3221
  /**
3037
3222
  * That no node names a column the graph can prove is not there.
3038
3223
  *
3039
- * Only where {@link workflowKnownColumns} answers, which is only downstream of a
3040
- * rename that drops what it does not name. Everywhere else this is silent, and
3041
- * that silence is correct rather than a gap being tolerated: refusing a column
3042
- * the graph merely has no opinion about would make every filter downstream of a
3043
- * transform unsaveable.
3224
+ * Only where {@link workflowKnownColumns} answers: downstream of a rename that
3225
+ * drops what it does not name, or when the caller supplied a
3226
+ * {@link WorkflowColumnKnowledge} downstream of a `catalog` source, whose
3227
+ * columns are the named type's published properties. Everywhere else this is
3228
+ * silent, and that silence is correct rather than a gap being tolerated:
3229
+ * refusing a column the graph merely has no opinion about would make every
3230
+ * filter downstream of a transform unsaveable.
3044
3231
  *
3045
3232
  * A refusal rather than a warning, because both failures are silent and total.
3046
3233
  * A filter on a column that cannot exist matches no row — a comparison against
@@ -3051,7 +3238,7 @@ function producedColumns(node, upstream) {
3051
3238
  * commits NULL into every row. That is the exact shape `property-names.ts` was
3052
3239
  * written about, one node upstream of where it can be caught.
3053
3240
  */
3054
- function checkColumnsProduced(graph, issues) {
3241
+ function checkColumnsProduced(graph, issues, knowledge) {
3055
3242
  for (const node of graph.nodes ?? []) {
3056
3243
  // Narrowed off the union rather than tested with a property check, so a kind
3057
3244
  // that starts naming columns without being answered for here is a type error
@@ -3063,7 +3250,7 @@ function checkColumnsProduced(graph, issues) {
3063
3250
  : Object.keys(node.columns ?? {});
3064
3251
  if (named.length === 0)
3065
3252
  continue;
3066
- const known = workflowKnownColumns(graph, node.id);
3253
+ const known = workflowKnownColumns(graph, node.id, knowledge);
3067
3254
  if (known === undefined)
3068
3255
  continue;
3069
3256
  const missing = named.filter((column) => column.length > 0 && !known.has(column));
@@ -3082,7 +3269,7 @@ function missingColumnMessage(node, missing, known) {
3082
3269
  const consequence = node.kind === 'filter'
3083
3270
  ? 'A test on a column that is not there matches no row — not even a "does not equal" test — so this load would come out empty and every node would report success.'
3084
3271
  : 'A rename of a column that is not there does nothing, so the column it was meant to produce is absent and a sink writing it commits NULL into every row.';
3085
- return `${node.kind === 'filter' ? 'Filter' : 'Rename'} "${node.name}" (${node.id}) names ${quoted(missing)}, and nothing upstream produces ${missing.length === 1 ? 'that column' : 'those columns'}. A rename above this node drops every column it does not name, so what reaches here is exactly ${quoted(known)}. ${consequence}`;
3272
+ return `${node.kind === 'filter' ? 'Filter' : 'Rename'} "${node.name}" (${node.id}) names ${quoted(missing)}, and nothing upstream produces ${missing.length === 1 ? 'that column' : 'those columns'}. Something above this node closes the column set — a rename that drops what it does not name, or a source reading a published object type — so what reaches here is exactly ${quoted(known)}. ${consequence}`;
3086
3273
  }
3087
3274
  function sortedEntries(config) {
3088
3275
  return Object.keys(config)
@@ -229,6 +229,67 @@ export interface CatalogReadStore {
229
229
  read(type: CatalogObjectTypeDef, fields: string[], query: CatalogReadQuery): Promise<CatalogReadResult>;
230
230
  listSnapshots?(type: CatalogObjectTypeDef): Promise<SnapshotRef[]>;
231
231
  }
232
+ /**
233
+ * A store that can hand over the whole of one snapshot, a row at a time.
234
+ *
235
+ * ## What this is for, and why `read` was not enough
236
+ *
237
+ * A workflow reading data the catalog already holds. Until this existed the only
238
+ * route was a `sql` connector naming `obj_<type>` — the physical table, which
239
+ * **retains every committed snapshot** — so a graph reading a type with two
240
+ * loads behind it read both, reported success, and doubled every sum while
241
+ * leaving the row count it wrote unchanged. See `CONNECTOR_KINDS`' `'catalog'`
242
+ * entry for the measurement.
243
+ *
244
+ * {@link CatalogReadStore.read} resolves "current" correctly and could be paged.
245
+ * It is not the right tool for a whole dataset, for two separate reasons:
246
+ *
247
+ * - **A page is `LIMIT`/`OFFSET`.** Reading seven million rows in pages makes the
248
+ * engine walk the offset each time, so the cost is quadratic in the size of
249
+ * the thing being read. That is not a tuning detail here — the row counts this
250
+ * feature exists for are exactly the ones that make it fatal.
251
+ * - **Paging is only correct under a total order**, and `read` does not promise
252
+ * one: a store free to return "some page of the matching rows" would let a
253
+ * paged loop skip and duplicate rows silently, which is the same class of
254
+ * failure this whole feature is repairing.
255
+ *
256
+ * ## Optional, and the option is the store's to take
257
+ *
258
+ * Exactly as {@link CatalogQueryStore.streamQuery} is, and for the same reason: a
259
+ * store fronting an API, or one on a driver that buffers a result set before
260
+ * resolving, cannot do this honestly, and a shim that collected every row and
261
+ * yielded them back would satisfy the type while doing the one thing the type
262
+ * exists to avoid. So an absent `streamSnapshot` is a real answer, and the
263
+ * caller refuses out loud rather than falling back to a paged read — a fallback
264
+ * whose two hazards are listed above.
265
+ *
266
+ * The contract on an implementation is one sentence: **do not read ahead of the
267
+ * consumer.** Whatever the driver offers must pause when the consumer stops
268
+ * pulling, all the way to the socket, or the memory has only moved.
269
+ */
270
+ export interface CatalogSnapshotStreamStore extends CatalogReadStore {
271
+ /**
272
+ * Every row of one snapshot, keyed by property name.
273
+ *
274
+ * `snapshotId` is required and never defaulted, which is the whole shape of
275
+ * the fix: the caller resolves which snapshot is current — once, when its run
276
+ * starts — and then reads *that one*, so a commit landing mid-read cannot have
277
+ * the first half of a load come from one snapshot and the second half from
278
+ * another. A store with no id to be given has nothing to stream.
279
+ *
280
+ * Keys are property names, matching what {@link CatalogReadStore.read} returns
281
+ * and what the write path looks a field up by (`row[property.name]`), so rows
282
+ * read out of one type can be written into another without a translation step
283
+ * that could disagree with either side.
284
+ *
285
+ * Returned synchronously — an async generator, not a promise for one — so a
286
+ * consumer's `for await` owns the resource from the first pull and an
287
+ * abandoned iteration runs the generator's `finally`.
288
+ */
289
+ streamSnapshot(type: CatalogObjectTypeDef, fields: string[], snapshotId: string): AsyncIterable<Record<string, unknown>>;
290
+ }
291
+ /** A store that can stream a whole snapshot. See {@link CatalogSnapshotStreamStore}. */
292
+ export declare function supportsSnapshotStreams(store: unknown): store is CatalogSnapshotStreamStore;
232
293
  /** A store that owns its copy of the data and can be loaded into. */
233
294
  export interface CatalogWriteStore extends CatalogReadStore {
234
295
  /**
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CATALOG_STORE = exports.CatalogColumnCollisionError = exports.UnsafeIdentifierError = exports.physicalColumn = exports.outputAlias = exports.isSafeIdentifier = exports.assertSafeIdentifier = exports.CATALOG_RESERVED_COLUMNS = exports.CATALOG_SNAPSHOT_MODES = void 0;
4
4
  exports.isCatalogStoreCapabilities = isCatalogStoreCapabilities;
5
5
  exports.supportsObjectFilters = supportsObjectFilters;
6
+ exports.supportsSnapshotStreams = supportsSnapshotStreams;
6
7
  exports.isReservedColumn = isReservedColumn;
7
8
  exports.findColumnCollisions = findColumnCollisions;
8
9
  exports.assertNoColumnCollisions = assertNoColumnCollisions;
@@ -53,6 +54,12 @@ function supportsObjectFilters(store) {
53
54
  store !== null &&
54
55
  Array.isArray(Reflect.get(store, 'objectFilterOperators')));
55
56
  }
57
+ /** A store that can stream a whole snapshot. See {@link CatalogSnapshotStreamStore}. */
58
+ function supportsSnapshotStreams(store) {
59
+ return (typeof store === 'object' &&
60
+ store !== null &&
61
+ typeof Reflect.get(store, 'streamSnapshot') === 'function');
62
+ }
56
63
  /**
57
64
  * The columns a snapshot-emulating store adds to every object table.
58
65
  *
package/dist/client.d.ts CHANGED
@@ -155,7 +155,7 @@ export declare const catalogRoutes: {
155
155
  };
156
156
  export type { CatalogConnection, CatalogConnector, ConnectionCheck, CatalogTransform, CatalogTransformFunction, CatalogTransformInput, CatalogRecordTransformFunction, CatalogRecordTransformInput, CatalogWorkflow, CatalogWorkflowCapabilities, CatalogWorkflowRelease, ConnectorKind, ConnectorRun, TransformLanguage, TransformMode, 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, WorkflowRenameNode, WorkflowRenameUnnamed, WorkflowRowCountPredicate, WorkflowRunOrderEntry, WorkflowSinkNode, WorkflowSkipReason, WorkflowSourceNode, WorkflowStageRef, WorkflowTransformNode, WorkflowValidationIssue, CatalogReusableNode, CatalogReusableNodeUse, ReusableNodeBody, ReusableNodeKind, ReusableNodeRef, ReusableSinkBody, ReusableSourceBody, SourceFormat, VersionPinCopy, } from './catalog.pipeline';
157
157
  export { type TransformShape, transformDeclaresModule, transformShape, } from './transform-shape';
158
- export { CONNECTOR_KINDS, isConnectorKind, isSourceFormat, isTransformLanguage, isTransformMode, TRANSFORM_MODES, transformMode, recordModeRefusal, 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
+ export { CATALOG_SOURCE_TYPE_KEY, CONNECTOR_KINDS, isConnectorKind, isSourceFormat, isTransformLanguage, isTransformMode, TRANSFORM_MODES, transformMode, recordModeRefusal, 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';
159
159
  /**
160
160
  * The workflow validator, shipped to the browser deliberately.
161
161
  *
@@ -183,8 +183,8 @@ export { CONNECTOR_KINDS, isConnectorKind, isSourceFormat, isTransformLanguage,
183
183
  * ends up drawn with its boxes overlapping — which is exactly what happened.
184
184
  */
185
185
  export { WORKFLOW_COLUMN_GAP, WORKFLOW_NODE_HEIGHT, WORKFLOW_NODE_WIDTH, WORKFLOW_ROW_GAP, workflowColumnX, workflowRowY, } from './catalog.pipeline';
186
- export { validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_BRANCH_LABELS, WORKFLOW_PREDICATE_KINDS, WORKFLOW_FILTER_COLUMN_PATTERN, WORKFLOW_FILTER_MAX_DEPTH, WORKFLOW_FILTER_MAX_VALUES, WORKFLOW_FILTER_OPERATORS, WORKFLOW_FILTER_PREDICATE_KINDS, WORKFLOW_RENAME_MAX_COLUMNS, WORKFLOW_RENAME_UNNAMED, WORKFLOW_SKIP_REASONS, isWorkflowBranchLabel, isWorkflowFilterOperator, isWorkflowFilterPredicate, isWorkflowFilterPredicateKind, isWorkflowFilterValue, isWorkflowIfPredicate, isWorkflowPredicateKind, isWorkflowRenameColumns, isWorkflowRenameUnnamed, isWorkflowSkipReason, workflowFilterColumns, workflowFilterMatches, renameColumnRefusals, workflowRenameUnnamed, workflowKnownColumns, workflowNarrowedTypes, workflowNodeRuns, unreachableFilterOperator, unreachableFilterPredicateKind, unreachableNodeKind, unreachablePredicateKind, unreachableRenameUnnamed, WORKFLOW_STATUSES, workflowGraphHash, workflowRunOrder, isWorkflowExecutionMode, isWorkflowNodeKind, isWorkflowStatus, callableWorkflowBlock, } from './catalog.pipeline';
187
- export type { CallableWorkflowBlock, CallableWorkflowDisagreement, WorkflowStatus, } from './catalog.pipeline';
186
+ export { validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_BRANCH_LABELS, WORKFLOW_PREDICATE_KINDS, WORKFLOW_FILTER_COLUMN_PATTERN, WORKFLOW_FILTER_MAX_DEPTH, WORKFLOW_FILTER_MAX_VALUES, WORKFLOW_FILTER_OPERATORS, WORKFLOW_FILTER_PREDICATE_KINDS, WORKFLOW_RENAME_MAX_COLUMNS, WORKFLOW_RENAME_UNNAMED, WORKFLOW_SKIP_REASONS, isWorkflowBranchLabel, isWorkflowFilterOperator, isWorkflowFilterPredicate, isWorkflowFilterPredicateKind, isWorkflowFilterValue, isWorkflowIfPredicate, isWorkflowPredicateKind, isWorkflowRenameColumns, isWorkflowRenameUnnamed, isWorkflowSkipReason, workflowFilterColumns, workflowFilterMatches, renameColumnRefusals, workflowRenameUnnamed, workflowKnownColumns, workflowSourceObjectType, workflowNarrowedTypes, workflowNodeRuns, unreachableFilterOperator, unreachableFilterPredicateKind, unreachableConnectorKind, unreachableNodeKind, unreachablePredicateKind, unreachableRenameUnnamed, WORKFLOW_STATUSES, workflowGraphHash, workflowRunOrder, isWorkflowExecutionMode, isWorkflowNodeKind, isWorkflowStatus, callableWorkflowBlock, } from './catalog.pipeline';
187
+ export type { CallableWorkflowBlock, CallableWorkflowDisagreement, WorkflowColumnKnowledge, WorkflowStatus, } from './catalog.pipeline';
188
188
  export type { CatalogTrace, CatalogTraceList, CatalogTraceOutcome, CatalogTraceSpan, TraceQuery, } from './catalog.workspace';
189
189
  export type { CatalogLoadExpectations, DeleteReconciliation, LoadExpectation, RowCountBound, StoredLoadExpectation, } from './catalog.pipeline';
190
190
  /**
package/dist/client.js CHANGED
@@ -11,8 +11,9 @@
11
11
  * types are.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- 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.recordModeRefusal = exports.transformMode = exports.TRANSFORM_MODES = exports.isTransformMode = exports.isTransformLanguage = exports.isSourceFormat = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.transformShape = exports.transformDeclaresModule = 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.unreachableRenameUnnamed = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableFilterPredicateKind = exports.unreachableFilterOperator = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowKnownColumns = exports.workflowRenameUnnamed = exports.renameColumnRefusals = exports.workflowFilterMatches = exports.workflowFilterColumns = exports.isWorkflowSkipReason = exports.isWorkflowRenameUnnamed = exports.isWorkflowRenameColumns = exports.isWorkflowPredicateKind = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowBranchLabel = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_RENAME_UNNAMED = exports.WORKFLOW_RENAME_MAX_COLUMNS = 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 = exports.validateWorkflow = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_HEIGHT = void 0;
14
+ 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.recordModeRefusal = exports.transformMode = exports.TRANSFORM_MODES = exports.isTransformMode = exports.isTransformLanguage = exports.isSourceFormat = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.CATALOG_SOURCE_TYPE_KEY = exports.transformShape = exports.transformDeclaresModule = 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.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_STATUSES = exports.unreachableRenameUnnamed = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableConnectorKind = exports.unreachableFilterPredicateKind = exports.unreachableFilterOperator = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowSourceObjectType = exports.workflowKnownColumns = exports.workflowRenameUnnamed = exports.renameColumnRefusals = exports.workflowFilterMatches = exports.workflowFilterColumns = exports.isWorkflowSkipReason = exports.isWorkflowRenameUnnamed = exports.isWorkflowRenameColumns = exports.isWorkflowPredicateKind = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowBranchLabel = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_RENAME_UNNAMED = exports.WORKFLOW_RENAME_MAX_COLUMNS = 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 = exports.validateWorkflow = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_NODE_WIDTH = exports.WORKFLOW_NODE_HEIGHT = exports.WORKFLOW_COLUMN_GAP = void 0;
16
+ exports.DELETE_RECONCILIATION_STRATEGIES = exports.callableWorkflowBlock = exports.isWorkflowStatus = void 0;
16
17
  exports.isDeleteReconciliationStrategy = isDeleteReconciliationStrategy;
17
18
  exports.pipelineExpectationRoutes = pipelineExpectationRoutes;
18
19
  // A value, not a type: a screen saying how far back the history goes should read
@@ -140,6 +141,9 @@ Object.defineProperty(exports, "transformShape", { enumerable: true, get: functi
140
141
  // Values, not types: a form that offers the kinds should read them from here
141
142
  // rather than keeping a copy that drifts.
142
143
  var catalog_pipeline_1 = require("./catalog.pipeline");
144
+ // The config key a `catalog` source names its object type in, so the
145
+ // inspector writing it and the fetcher reading it cannot spell it differently.
146
+ Object.defineProperty(exports, "CATALOG_SOURCE_TYPE_KEY", { enumerable: true, get: function () { return catalog_pipeline_1.CATALOG_SOURCE_TYPE_KEY; } });
143
147
  Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.CONNECTOR_KINDS; } });
144
148
  Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
145
149
  Object.defineProperty(exports, "isSourceFormat", { enumerable: true, get: function () { return catalog_pipeline_1.isSourceFormat; } });
@@ -303,6 +307,9 @@ Object.defineProperty(exports, "workflowRenameUnnamed", { enumerable: true, get:
303
307
  // a declarative rename buys that a transform cannot. The inspector says it out
304
308
  // loud; see `workflowKnownColumns` for how far it reaches.
305
309
  Object.defineProperty(exports, "workflowKnownColumns", { enumerable: true, get: function () { return catalog_pipeline_3.workflowKnownColumns; } });
310
+ // Which object type a `catalog` source reads, read off the node by the one
311
+ // function the validator and the fetcher also use.
312
+ Object.defineProperty(exports, "workflowSourceObjectType", { enumerable: true, get: function () { return catalog_pipeline_3.workflowSourceObjectType; } });
306
313
  // Which published types a filter stands in front of. The console has to offer
307
314
  // the same acknowledgements the validator requires, and a canvas computing its
308
315
  // own answer would offer a set the server then refuses.
@@ -312,6 +319,10 @@ Object.defineProperty(exports, "workflowNarrowedTypes", { enumerable: true, get:
312
319
  Object.defineProperty(exports, "workflowNodeRuns", { enumerable: true, get: function () { return catalog_pipeline_3.workflowNodeRuns; } });
313
320
  Object.defineProperty(exports, "unreachableFilterOperator", { enumerable: true, get: function () { return catalog_pipeline_3.unreachableFilterOperator; } });
314
321
  Object.defineProperty(exports, "unreachableFilterPredicateKind", { enumerable: true, get: function () { return catalog_pipeline_3.unreachableFilterPredicateKind; } });
322
+ // The kind exhaustiveness helper for *sources*, beside the one for nodes: a
323
+ // console deciding something per source kind is meant to stop compiling when a
324
+ // sixth kind arrives, exactly as the server does.
325
+ Object.defineProperty(exports, "unreachableConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_3.unreachableConnectorKind; } });
315
326
  Object.defineProperty(exports, "unreachableNodeKind", { enumerable: true, get: function () { return catalog_pipeline_3.unreachableNodeKind; } });
316
327
  Object.defineProperty(exports, "unreachablePredicateKind", { enumerable: true, get: function () { return catalog_pipeline_3.unreachablePredicateKind; } });
317
328
  Object.defineProperty(exports, "unreachableRenameUnnamed", { enumerable: true, get: function () { return catalog_pipeline_3.unreachableRenameUnnamed; } });
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 CatalogRecordTransformFunction, type CatalogRecordTransformInput, type CatalogTransform, type CatalogTransformFunction, type CatalogTransformInput, 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, isTransformMode, type LoadExpectation, type RowCountBound, SOURCE_FORMATS, type SourceFormat, unreachableSourceFormat, type StoredLoadExpectation, readWorkflowCallOutput, REDACTED_SECRET, supportsLoadExpectations, supportsReusableNodes, supportsTransformPins, supportsTransformRevisions, supportsTransformStreaming, 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, isWorkflowRenameColumns, isWorkflowRenameUnnamed, isWorkflowSkipReason, isWorkflowStatus, liveWorkflowVersion, supportsWorkflowReleases, supportsWorkflows, supportsWorkflowStages, supportsStagePayloads, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, TRANSFORM_MODES, recordModeRefusal, transformMode, type TransformLanguage, type TransformMode, type TransformResult, type TransformRunner, type TransformStream, type TransformStreamSummary, unreachableFilterOperator, unreachableTransformMode, unreachableFilterPredicateKind, unreachableCallMode, unreachableNodeKind, unreachablePredicateKind, unreachableRenameUnnamed, 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_RENAME_MAX_COLUMNS, WORKFLOW_RENAME_UNNAMED, 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, workflowFilterColumns, 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, workflowKnownColumns, workflowNarrowedTypes, type WorkflowNodeOutcome, workflowNodeRuns, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowRunOrderEntry, type WorkflowPredicateKind, renameColumnRefusals, type WorkflowRenameNode, type WorkflowRenameUnnamed, workflowRenameUnnamed, 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, CATALOG_SOURCE_TYPE_KEY, CONNECTOR_KINDS, type CatalogLoadExpectations, type CatalogLoadExpectationStore, type CatalogPipelineStore, type CatalogStageStore, type CatalogRecordTransformFunction, type CatalogRecordTransformInput, type CatalogTransform, type CatalogTransformFunction, type CatalogTransformInput, 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, isTransformMode, type LoadExpectation, type RowCountBound, SOURCE_FORMATS, type SourceFormat, unreachableSourceFormat, type StoredLoadExpectation, readWorkflowCallOutput, REDACTED_SECRET, supportsLoadExpectations, supportsReusableNodes, supportsTransformPins, supportsTransformRevisions, supportsTransformStreaming, 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, isWorkflowRenameColumns, isWorkflowRenameUnnamed, isWorkflowSkipReason, isWorkflowStatus, liveWorkflowVersion, supportsWorkflowReleases, supportsWorkflows, supportsWorkflowStages, supportsStagePayloads, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, TRANSFORM_MODES, recordModeRefusal, transformMode, type TransformLanguage, type TransformMode, type TransformResult, type TransformRunner, type TransformStream, type TransformStreamSummary, unreachableFilterOperator, unreachableTransformMode, unreachableFilterPredicateKind, unreachableCallMode, unreachableConnectorKind, unreachableNodeKind, unreachablePredicateKind, unreachableRenameUnnamed, 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_RENAME_MAX_COLUMNS, WORKFLOW_RENAME_UNNAMED, WORKFLOW_ROW_GAP, WORKFLOW_SKIP_REASONS, WORKFLOW_STATUSES, type WorkflowBranchLabel, type WorkflowColumnKnowledge, workflowColumnX, workflowRowY, type WorkflowCallEnvelope, type WorkflowCallMode, workflowCallMode, type WorkflowCallNode, type WorkflowCallOutput, type WorkflowEdge, type WorkflowExecutionMode, type WorkflowFilterAll, type WorkflowFilterAny, type WorkflowFilterComparison, type WorkflowFilterGroup, workflowFilterColumns, 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, workflowKnownColumns, workflowNarrowedTypes, workflowSourceObjectType, type WorkflowNodeOutcome, workflowNodeRuns, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowRunOrderEntry, type WorkflowPredicateKind, renameColumnRefusals, type WorkflowRenameNode, type WorkflowRenameUnnamed, workflowRenameUnnamed, 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, renameStagePayload, type StageRenamePlan, type StageRenameResult, } from './catalog.stage-encoding';
13
13
  export * from './catalog.environment';
14
14
  export { QueryCache } from './catalog.query-cache';
@@ -22,7 +22,7 @@ export { type AuditQuery, CATALOG_REVISION_LIMIT, CATALOG_TRACE_OUTCOMES, CATALO
22
22
  export { CATALOG_PRINCIPAL_RESOLVER, type CatalogActor, type CatalogGrants, type CatalogPrincipal, type CatalogPrincipalResolver, type CatalogScope, composePrincipalId, delegatePrincipal, expandScopes, hasScope, parsePrincipalId, PRINCIPAL_ACTOR_SEPARATOR, maySeeClassification, mayRead, mayWrite, readableObjectPage, StaticKeyPrincipalResolver, } from './catalog.principal';
23
23
  export * from './catalog.access';
24
24
  export * from './catalog.filters';
25
- export { assertNoColumnCollisions, assertSafeIdentifier, CATALOG_RESERVED_COLUMNS, CATALOG_SNAPSHOT_MODES, CATALOG_STORE, type CarryForwardResult, type CatalogColumnCollision, CatalogColumnCollisionError, type CatalogFilteringReadStore, supportsObjectFilters, type CatalogMergeStore, type CatalogReadQuery, type CatalogReadResult, type CatalogReadStore, type CatalogReservedColumn, type CatalogSnapshotMode, type CatalogStoreCapabilities, type CatalogWriteStore, type ColumnCollisionOptions, findColumnCollisions, isCatalogStoreCapabilities, isReservedColumn, isSafeIdentifier, isWriteStore, outputAlias, physicalColumn, type SnapshotRef, supportsCarryForward, UnsafeIdentifierError, } from './catalog.store';
25
+ export { assertNoColumnCollisions, assertSafeIdentifier, CATALOG_RESERVED_COLUMNS, CATALOG_SNAPSHOT_MODES, CATALOG_STORE, type CarryForwardResult, type CatalogColumnCollision, CatalogColumnCollisionError, type CatalogFilteringReadStore, supportsObjectFilters, type CatalogMergeStore, type CatalogReadQuery, type CatalogReadResult, type CatalogReadStore, type CatalogReservedColumn, type CatalogSnapshotMode, type CatalogSnapshotStreamStore, type CatalogStoreCapabilities, type CatalogWriteStore, type ColumnCollisionOptions, findColumnCollisions, isCatalogStoreCapabilities, isReservedColumn, isSafeIdentifier, isWriteStore, outputAlias, physicalColumn, type SnapshotRef, supportsCarryForward, supportsSnapshotStreams, UnsafeIdentifierError, } from './catalog.store';
26
26
  export { MikroOrmReadStore } from './stores/mikro-orm-read.store';
27
27
  export type { CatalogGraph, CatalogObjectPage, CatalogObjectQuery, CatalogObjectTypeDef, CatalogOverlay, CatalogPropertyDef, CatalogRelationDef, CatalogSnapshot, RelationKind, ScalarType, } from './catalog.types';
28
28
  export { REQUIRED_SCOPES, REQUIRES_HUMAN, RequireHuman, RequireScopes, } from './catalog.route-auth';
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.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.supportsTransformStreaming = exports.supportsTransformRevisions = exports.supportsTransformPins = exports.supportsReusableNodes = exports.supportsLoadExpectations = exports.REDACTED_SECRET = exports.readWorkflowCallOutput = exports.unreachableSourceFormat = exports.SOURCE_FORMATS = exports.isTransformMode = 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.WORKFLOW_RENAME_MAX_COLUMNS = 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.unreachableRenameUnnamed = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableCallMode = exports.unreachableFilterPredicateKind = exports.unreachableTransformMode = exports.unreachableFilterOperator = exports.transformMode = exports.recordModeRefusal = exports.TRANSFORM_MODES = exports.TRANSFORM_LANGUAGES = exports.TRANSFORM_RUNNER = exports.supportsStagePayloads = exports.supportsWorkflowStages = exports.supportsWorkflows = exports.supportsWorkflowReleases = exports.liveWorkflowVersion = exports.isWorkflowStatus = exports.isWorkflowSkipReason = exports.isWorkflowRenameUnnamed = exports.isWorkflowRenameColumns = exports.isWorkflowPredicateKind = exports.isWorkflowNodeKind = exports.isWorkflowCallMode = exports.isWorkflowNode = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowExecutionMode = exports.isWorkflowEdge = void 0;
19
- 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.transformShapeHint = exports.transformShape = exports.transformDeclaresModule = exports.SubprocessTransformRunner = exports.toCsv = exports.guardFormula = exports.csvLines = exports.csvCell = exports.QueryCache = exports.renameStagePayload = exports.isColumnarStageBatch = exports.encodeStageRows = exports.decodeStageRows = exports.classifyStagePayload = exports.STAGE_ENCODING_VERSION = exports.STAGE_ENCODING = exports.workflowRenameUnnamed = exports.renameColumnRefusals = exports.workflowRunOrder = exports.workflowNodeRuns = exports.workflowNarrowedTypes = exports.workflowKnownColumns = exports.workflowGraphHash = exports.workflowFilterMatches = exports.workflowFilterColumns = exports.workflowCallMode = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_STATUSES = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_RENAME_UNNAMED = 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 = 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 = void 0;
17
+ 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.supportsTransformStreaming = exports.supportsTransformRevisions = exports.supportsTransformPins = exports.supportsReusableNodes = exports.supportsLoadExpectations = exports.REDACTED_SECRET = exports.readWorkflowCallOutput = exports.unreachableSourceFormat = exports.SOURCE_FORMATS = exports.isTransformMode = exports.isTransformLanguage = exports.isSourceFormat = exports.isPipelineStore = exports.isConnectorKind = exports.callableWorkflowBlock = exports.CONNECTOR_KINDS = exports.CATALOG_SOURCE_TYPE_KEY = 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.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.unreachableRenameUnnamed = exports.unreachablePredicateKind = exports.unreachableNodeKind = exports.unreachableConnectorKind = exports.unreachableCallMode = exports.unreachableFilterPredicateKind = exports.unreachableTransformMode = exports.unreachableFilterOperator = exports.transformMode = exports.recordModeRefusal = exports.TRANSFORM_MODES = exports.TRANSFORM_LANGUAGES = exports.TRANSFORM_RUNNER = exports.supportsStagePayloads = exports.supportsWorkflowStages = exports.supportsWorkflows = exports.supportsWorkflowReleases = exports.liveWorkflowVersion = exports.isWorkflowStatus = exports.isWorkflowSkipReason = exports.isWorkflowRenameUnnamed = exports.isWorkflowRenameColumns = exports.isWorkflowPredicateKind = exports.isWorkflowNodeKind = exports.isWorkflowCallMode = exports.isWorkflowNode = exports.isWorkflowIfPredicate = exports.isWorkflowFilterValue = exports.isWorkflowFilterPredicateKind = exports.isWorkflowFilterPredicate = exports.isWorkflowFilterOperator = exports.isWorkflowExecutionMode = exports.isWorkflowEdge = exports.isWorkflowBranchLabel = void 0;
19
+ 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.transformShapeHint = exports.transformShape = exports.transformDeclaresModule = exports.SubprocessTransformRunner = exports.toCsv = exports.guardFormula = exports.csvLines = exports.csvCell = exports.QueryCache = exports.renameStagePayload = exports.isColumnarStageBatch = exports.encodeStageRows = exports.decodeStageRows = exports.classifyStagePayload = exports.STAGE_ENCODING_VERSION = exports.STAGE_ENCODING = exports.workflowRenameUnnamed = exports.renameColumnRefusals = exports.workflowRunOrder = exports.workflowNodeRuns = exports.workflowSourceObjectType = exports.workflowNarrowedTypes = exports.workflowKnownColumns = exports.workflowGraphHash = exports.workflowFilterMatches = exports.workflowFilterColumns = exports.workflowCallMode = exports.workflowRowY = exports.workflowColumnX = exports.WORKFLOW_STATUSES = exports.WORKFLOW_SKIP_REASONS = exports.WORKFLOW_ROW_GAP = exports.WORKFLOW_RENAME_UNNAMED = exports.WORKFLOW_RENAME_MAX_COLUMNS = exports.WORKFLOW_PREDICATE_KINDS = void 0;
20
+ exports.RequireScopes = exports.RequireHuman = exports.REQUIRES_HUMAN = exports.REQUIRED_SCOPES = exports.MikroOrmReadStore = exports.UnsafeIdentifierError = exports.supportsSnapshotStreams = 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 = 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; } });
@@ -59,6 +59,7 @@ Object.defineProperty(exports, "CatalogRegistry", { enumerable: true, get: funct
59
59
  var catalog_pipeline_1 = require("./catalog.pipeline");
60
60
  Object.defineProperty(exports, "CATALOG_PIPELINE_STORE", { enumerable: true, get: function () { return catalog_pipeline_1.CATALOG_PIPELINE_STORE; } });
61
61
  Object.defineProperty(exports, "CODE_CONTEXT_CONTRACT", { enumerable: true, get: function () { return catalog_pipeline_1.CODE_CONTEXT_CONTRACT; } });
62
+ Object.defineProperty(exports, "CATALOG_SOURCE_TYPE_KEY", { enumerable: true, get: function () { return catalog_pipeline_1.CATALOG_SOURCE_TYPE_KEY; } });
62
63
  Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.CONNECTOR_KINDS; } });
63
64
  Object.defineProperty(exports, "callableWorkflowBlock", { enumerable: true, get: function () { return catalog_pipeline_1.callableWorkflowBlock; } });
64
65
  Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
@@ -115,6 +116,7 @@ Object.defineProperty(exports, "unreachableFilterOperator", { enumerable: true,
115
116
  Object.defineProperty(exports, "unreachableTransformMode", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableTransformMode; } });
116
117
  Object.defineProperty(exports, "unreachableFilterPredicateKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableFilterPredicateKind; } });
117
118
  Object.defineProperty(exports, "unreachableCallMode", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableCallMode; } });
119
+ Object.defineProperty(exports, "unreachableConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableConnectorKind; } });
118
120
  Object.defineProperty(exports, "unreachableNodeKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableNodeKind; } });
119
121
  Object.defineProperty(exports, "unreachablePredicateKind", { enumerable: true, get: function () { return catalog_pipeline_1.unreachablePredicateKind; } });
120
122
  Object.defineProperty(exports, "unreachableRenameUnnamed", { enumerable: true, get: function () { return catalog_pipeline_1.unreachableRenameUnnamed; } });
@@ -148,6 +150,7 @@ Object.defineProperty(exports, "workflowFilterMatches", { enumerable: true, get:
148
150
  Object.defineProperty(exports, "workflowGraphHash", { enumerable: true, get: function () { return catalog_pipeline_1.workflowGraphHash; } });
149
151
  Object.defineProperty(exports, "workflowKnownColumns", { enumerable: true, get: function () { return catalog_pipeline_1.workflowKnownColumns; } });
150
152
  Object.defineProperty(exports, "workflowNarrowedTypes", { enumerable: true, get: function () { return catalog_pipeline_1.workflowNarrowedTypes; } });
153
+ Object.defineProperty(exports, "workflowSourceObjectType", { enumerable: true, get: function () { return catalog_pipeline_1.workflowSourceObjectType; } });
151
154
  Object.defineProperty(exports, "workflowNodeRuns", { enumerable: true, get: function () { return catalog_pipeline_1.workflowNodeRuns; } });
152
155
  Object.defineProperty(exports, "workflowRunOrder", { enumerable: true, get: function () { return catalog_pipeline_1.workflowRunOrder; } });
153
156
  Object.defineProperty(exports, "renameColumnRefusals", { enumerable: true, get: function () { return catalog_pipeline_1.renameColumnRefusals; } });
@@ -257,6 +260,7 @@ Object.defineProperty(exports, "isWriteStore", { enumerable: true, get: function
257
260
  Object.defineProperty(exports, "outputAlias", { enumerable: true, get: function () { return catalog_store_1.outputAlias; } });
258
261
  Object.defineProperty(exports, "physicalColumn", { enumerable: true, get: function () { return catalog_store_1.physicalColumn; } });
259
262
  Object.defineProperty(exports, "supportsCarryForward", { enumerable: true, get: function () { return catalog_store_1.supportsCarryForward; } });
263
+ Object.defineProperty(exports, "supportsSnapshotStreams", { enumerable: true, get: function () { return catalog_store_1.supportsSnapshotStreams; } });
260
264
  Object.defineProperty(exports, "UnsafeIdentifierError", { enumerable: true, get: function () { return catalog_store_1.UnsafeIdentifierError; } });
261
265
  var mikro_orm_read_store_1 = require("./stores/mikro-orm-read.store");
262
266
  Object.defineProperty(exports, "MikroOrmReadStore", { enumerable: true, get: function () { return mikro_orm_read_store_1.MikroOrmReadStore; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-catalog",
3
- "version": "0.24.0",
3
+ "version": "0.26.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",