@dudousxd/nestjs-catalog 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog.controller.js +36 -2
- package/dist/catalog.events.d.ts +10 -3
- package/dist/catalog.pipeline.d.ts +357 -11
- package/dist/catalog.pipeline.js +62 -6
- package/dist/catalog.store.d.ts +25 -0
- package/dist/catalog.store.js +70 -1
- package/dist/catalog.workspace.d.ts +154 -0
- package/dist/catalog.workspace.js +59 -1
- package/dist/client.d.ts +120 -1
- package/dist/client.js +70 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -2
- package/package.json +1 -1
package/dist/catalog.store.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CATALOG_STORE = exports.CatalogColumnCollisionError = exports.CATALOG_RESERVED_COLUMNS = exports.CATALOG_SNAPSHOT_MODES = void 0;
|
|
3
|
+
exports.CATALOG_STORE = exports.CatalogColumnCollisionError = exports.UnsafeIdentifierError = exports.CATALOG_RESERVED_COLUMNS = exports.CATALOG_SNAPSHOT_MODES = void 0;
|
|
4
4
|
exports.isCatalogStoreCapabilities = isCatalogStoreCapabilities;
|
|
5
5
|
exports.isReservedColumn = isReservedColumn;
|
|
6
|
+
exports.isSafeIdentifier = isSafeIdentifier;
|
|
7
|
+
exports.assertSafeIdentifier = assertSafeIdentifier;
|
|
6
8
|
exports.findColumnCollisions = findColumnCollisions;
|
|
7
9
|
exports.assertNoColumnCollisions = assertNoColumnCollisions;
|
|
8
10
|
exports.isWriteStore = isWriteStore;
|
|
@@ -72,6 +74,73 @@ exports.CATALOG_RESERVED_COLUMNS = [
|
|
|
72
74
|
function isReservedColumn(column) {
|
|
73
75
|
return exports.CATALOG_RESERVED_COLUMNS.some((reserved) => reserved === column.toLowerCase());
|
|
74
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* What a name has to look like before a store will write it into SQL.
|
|
79
|
+
*
|
|
80
|
+
* Identifiers are *rejected*, never escaped and never sanitised. Every table
|
|
81
|
+
* and column name a store emits arrives from another application over HTTP and
|
|
82
|
+
* ends up in DDL and in SELECT lists, where no placeholder can stand in for it,
|
|
83
|
+
* so anything outside this character set never becomes SQL at all.
|
|
84
|
+
*
|
|
85
|
+
* Here, beside {@link CATALOG_RESERVED_COLUMNS}, for the same reason: it is
|
|
86
|
+
* part of what the catalog promises a *publisher*. Refuse a property name and
|
|
87
|
+
* the sentence explaining why is the only statement of the rule most people
|
|
88
|
+
* will ever read, so it belongs to the contract rather than to whichever
|
|
89
|
+
* adapter happens to be mounted.
|
|
90
|
+
*
|
|
91
|
+
* And for one more reason. It used to be two copies — `store-mikro-orm` and
|
|
92
|
+
* `store-clickhouse` each carried this pattern and this sentence, byte for
|
|
93
|
+
* byte — and the publish-time refusal in the pipeline package borrowed the
|
|
94
|
+
* MySQL one so that publish-time and DDL-time could not disagree about the
|
|
95
|
+
* character set, the length or the wording. That bought the guarantee for a
|
|
96
|
+
* MySQL deployment and left a ClickHouse-only one trusting two files to be
|
|
97
|
+
* edited together. One definition is the guarantee; two identical ones are a
|
|
98
|
+
* habit.
|
|
99
|
+
*
|
|
100
|
+
* 63 characters because it is under MySQL's 64-character ceiling and no engine
|
|
101
|
+
* a store here targets refuses a name that short, and because the number is
|
|
102
|
+
* quoted in the refusal below: a per-store limit would mean a publisher being
|
|
103
|
+
* told a different rule depending on what is mounted, for a name the catalog
|
|
104
|
+
* would then be unable to promise anything about across a fan-out.
|
|
105
|
+
*
|
|
106
|
+
* Not exported. A `RegExp` is mutable and shared state, and the two questions
|
|
107
|
+
* anyone has of it — "may I?" and "why not?" — are {@link isSafeIdentifier} and
|
|
108
|
+
* {@link UnsafeIdentifierError}.
|
|
109
|
+
*/
|
|
110
|
+
const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/;
|
|
111
|
+
/**
|
|
112
|
+
* Why a name cannot be written into SQL, in the words a publisher is given.
|
|
113
|
+
*
|
|
114
|
+
* One class for the whole ecosystem rather than one per adapter, so
|
|
115
|
+
* `instanceof` is a usable question across packages. The publish-time check in
|
|
116
|
+
* the pipeline package catches this to tell "that name cannot be an identifier"
|
|
117
|
+
* from "something else failed inside the store", and with a class per adapter
|
|
118
|
+
* that check would re-throw the moment the mounted store was not the one it
|
|
119
|
+
* imported — turning a 400 that names the property into a 500 that names
|
|
120
|
+
* nothing.
|
|
121
|
+
*/
|
|
122
|
+
class UnsafeIdentifierError extends Error {
|
|
123
|
+
constructor(value) {
|
|
124
|
+
super(`Refusing to use "${value}" as a SQL identifier: letters, digits and underscore only, starting with a letter or underscore, 63 characters max.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.UnsafeIdentifierError = UnsafeIdentifierError;
|
|
128
|
+
/** Whether a name can be written into SQL as it stands. */
|
|
129
|
+
function isSafeIdentifier(value) {
|
|
130
|
+
return SAFE_IDENTIFIER.test(value);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Refuse a name that cannot be a SQL identifier.
|
|
134
|
+
*
|
|
135
|
+
* Throws rather than answering, because the caller's next line writes the value
|
|
136
|
+
* into a statement: a boolean that can be ignored is a boolean that eventually
|
|
137
|
+
* is. {@link isSafeIdentifier} is there for the callers that are asking rather
|
|
138
|
+
* than about to build.
|
|
139
|
+
*/
|
|
140
|
+
function assertSafeIdentifier(value) {
|
|
141
|
+
if (!isSafeIdentifier(value))
|
|
142
|
+
throw new UnsafeIdentifierError(value);
|
|
143
|
+
}
|
|
75
144
|
/**
|
|
76
145
|
* Every way a type's properties would fight over a physical column.
|
|
77
146
|
*
|
|
@@ -11,6 +11,16 @@ export interface SavedQuery {
|
|
|
11
11
|
id: string;
|
|
12
12
|
name: string;
|
|
13
13
|
description?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The statement, as it is now.
|
|
16
|
+
*
|
|
17
|
+
* Overwritten in place by {@link CatalogWorkspaceStore.updateSavedQuery}, and
|
|
18
|
+
* for a long time that was the end of it — a report that started answering
|
|
19
|
+
* differently left nothing to compare against, not even a version number. What
|
|
20
|
+
* it used to say is kept as {@link CatalogRevision}s now, read through
|
|
21
|
+
* {@link CatalogWorkspaceStore.listSavedQueryRevisions}; this field stays the
|
|
22
|
+
* one a run of the query executes.
|
|
23
|
+
*/
|
|
14
24
|
sql: string;
|
|
15
25
|
/** Free-form grouping, the way a folder would work without being one. */
|
|
16
26
|
folder?: string;
|
|
@@ -71,6 +81,122 @@ export interface SaveQueryInput {
|
|
|
71
81
|
visualization?: QueryVisualization;
|
|
72
82
|
shared?: boolean;
|
|
73
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* One recorded revision of something whose text a person edits.
|
|
86
|
+
*
|
|
87
|
+
* The same shape for a transform's code and for a saved query's SQL, and that is
|
|
88
|
+
* the point rather than a saving: the two are edited the same way and go wrong
|
|
89
|
+
* the same way — somebody changes the text, a load or a report starts coming out
|
|
90
|
+
* different, and the question afterwards is what the text used to say. `body` is
|
|
91
|
+
* named for that. `code` would have been a lie on half of its uses.
|
|
92
|
+
*
|
|
93
|
+
* ## What this exists to fix
|
|
94
|
+
*
|
|
95
|
+
* A {@link ConnectorRun} has always recorded `transformVersion`, so the catalog
|
|
96
|
+
* already knew *which* version produced a given load. What it did not keep was
|
|
97
|
+
* the text of that version: one row per transform, overwritten in place, the
|
|
98
|
+
* counter bumped and the previous code gone. A saved query had not even the
|
|
99
|
+
* counter. Meanwhile the runs list renders `code v3`, which reads as a reference
|
|
100
|
+
* to something retrievable — so an operator was told a version number, believed
|
|
101
|
+
* the source was recoverable, and it was not.
|
|
102
|
+
*
|
|
103
|
+
* The number on the run and the {@link version} here are **the same number**.
|
|
104
|
+
* That is the whole contract: "this load ran v3" becomes something a person can
|
|
105
|
+
* open.
|
|
106
|
+
*
|
|
107
|
+
* ## No `kind` field, deliberately
|
|
108
|
+
*
|
|
109
|
+
* A revision is always read through a route that already names its subject —
|
|
110
|
+
* `transforms/:id/revisions`, `saved-queries/:id/revisions` — so a discriminator
|
|
111
|
+
* here would be a field whose only possible value the caller had just supplied.
|
|
112
|
+
* The *store* keys by one, because one table holds both kinds; that is a storage
|
|
113
|
+
* concern and it stays in the store.
|
|
114
|
+
*
|
|
115
|
+
* ## What is NOT revisioned, and why
|
|
116
|
+
*
|
|
117
|
+
* A workflow graph, which has the identical "latest only" limitation and is
|
|
118
|
+
* deliberately left with it. See {@link CatalogWorkflow}, which makes the
|
|
119
|
+
* argument where somebody looking for the missing feature will find it.
|
|
120
|
+
*/
|
|
121
|
+
export interface CatalogRevision {
|
|
122
|
+
/**
|
|
123
|
+
* Stable id of this revision.
|
|
124
|
+
*
|
|
125
|
+
* Derived from the subject and the version rather than random — see
|
|
126
|
+
* `revisionKey` in the MikroORM store — so recording the same version twice
|
|
127
|
+
* replaces it instead of appending a second copy, and a screen may key a list
|
|
128
|
+
* on it across refetches.
|
|
129
|
+
*/
|
|
130
|
+
id: string;
|
|
131
|
+
/** What it belongs to — a transform id or a saved-query id. */
|
|
132
|
+
subjectId: string;
|
|
133
|
+
/** The version this revision IS. Matches `transformVersion` on a run. */
|
|
134
|
+
version: number;
|
|
135
|
+
/** The text as it was: the transform's code, or the query's SQL. */
|
|
136
|
+
body: string;
|
|
137
|
+
/**
|
|
138
|
+
* Who saved it.
|
|
139
|
+
*
|
|
140
|
+
* Exact for a transform, which is saved through a store method that is given
|
|
141
|
+
* the actor. **Approximate for a saved query**, whose update path is given
|
|
142
|
+
* none — `updateSavedQuery` takes an id and a patch, and `CatalogService`
|
|
143
|
+
* keeps the actor for the audit event it emits — so a saved query's revisions
|
|
144
|
+
* are attributed to the query's `createdBy`. That is who created it, not
|
|
145
|
+
* necessarily who last edited it, and it is recorded that way rather than
|
|
146
|
+
* invented: a name here that was picked to fill the field would be read as
|
|
147
|
+
* evidence. Threading the editor through `updateSavedQuery` is what would fix
|
|
148
|
+
* it, and it is a change to that method's contract rather than to this one.
|
|
149
|
+
*/
|
|
150
|
+
authoredBy: string;
|
|
151
|
+
authoredAt: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* How many revisions are kept per subject. Writing a newer one drops the oldest
|
|
155
|
+
* beyond this.
|
|
156
|
+
*
|
|
157
|
+
* ## Why there is a cap at all
|
|
158
|
+
*
|
|
159
|
+
* This is append-only text that grows forever, and it is the fourth append-only
|
|
160
|
+
* table in the bundled store. The other three earn their unboundedness and this
|
|
161
|
+
* one does not. An audit event and a connector run are each one small row per
|
|
162
|
+
* *thing that happened*, at a rate an operator can read off their own load
|
|
163
|
+
* schedule; staged rows are dropped the moment the run that produced them is
|
|
164
|
+
* finished with. A revision is neither: it grows with how often somebody edits,
|
|
165
|
+
* which nobody meters, and every row carries a whole code body rather than a
|
|
166
|
+
* counter. Unpredictable in rate *and* large per row is the combination worth
|
|
167
|
+
* bounding — and "this grows; here is the query to prune it" would have been a
|
|
168
|
+
* fourth unbounded table with a paragraph in front of it.
|
|
169
|
+
*
|
|
170
|
+
* ## Why a count per subject rather than an age bound
|
|
171
|
+
*
|
|
172
|
+
* An age bound keys the wrong thing. A transform edited twice in 2019 and relied
|
|
173
|
+
* on ever since would lose both revisions, while one edited daily keeps
|
|
174
|
+
* everything — exactly backwards. What makes a revision unrecoverable is being
|
|
175
|
+
* superseded, so that is what the bound counts.
|
|
176
|
+
*
|
|
177
|
+
* ## What it costs, stated rather than implied
|
|
178
|
+
*
|
|
179
|
+
* A run's `transformVersion` can name a revision that has been evicted: a
|
|
180
|
+
* transform saved more than this many times can no longer produce its earliest
|
|
181
|
+
* code. That loss is real. It is strictly smaller than the one it replaces —
|
|
182
|
+
* where every version but the newest was unrecoverable — and it is visible
|
|
183
|
+
* rather than silent, because a caller holding a version older than the oldest
|
|
184
|
+
* revision in the list can see that the list does not reach that far.
|
|
185
|
+
*
|
|
186
|
+
* At the cap a 4 KB body costs 200 KB per subject, so a thousand heavily-edited
|
|
187
|
+
* subjects cost roughly 200 MB. That is a ceiling, which is the point of having
|
|
188
|
+
* one.
|
|
189
|
+
*
|
|
190
|
+
* ## Why a constant and not a module option
|
|
191
|
+
*
|
|
192
|
+
* The number is part of what this table promises, and a console should be able
|
|
193
|
+
* to print "the last 50 are kept" without a round trip to ask which deployment
|
|
194
|
+
* it is talking to. A knob is also a promise to support every value of it,
|
|
195
|
+
* including the one that switches the feature off and is then reported as a bug.
|
|
196
|
+
* It becomes an option on the day there is a deployment it is wrong for, rather
|
|
197
|
+
* than in anticipation of one.
|
|
198
|
+
*/
|
|
199
|
+
export declare const CATALOG_REVISION_LIMIT = 50;
|
|
74
200
|
export interface Dashboard {
|
|
75
201
|
id: string;
|
|
76
202
|
name: string;
|
|
@@ -480,6 +606,26 @@ export interface CatalogWorkspaceStore {
|
|
|
480
606
|
* first and decides.
|
|
481
607
|
*/
|
|
482
608
|
deleteSavedQuery(id: string): Promise<boolean>;
|
|
609
|
+
/**
|
|
610
|
+
* Every SQL this saved query has ever been, newest first.
|
|
611
|
+
*
|
|
612
|
+
* **Optional**, and mixed in here rather than made a member every store must
|
|
613
|
+
* have, for the reason {@link CatalogWorkflowStore} gives about the same
|
|
614
|
+
* decision: a store written against the previous shape of this interface —
|
|
615
|
+
* including the routing proxy in the MikroORM package — implements
|
|
616
|
+
* `CatalogWorkspaceStore` today, and turning that into a compile error would
|
|
617
|
+
* be a breaking change for a feature that is purely additive.
|
|
618
|
+
* {@link supportsSavedQueryRevisions} is how a caller asks, so "this store
|
|
619
|
+
* keeps no revisions" is a sentence a route can say rather than a method that
|
|
620
|
+
* is missing at run time.
|
|
621
|
+
*
|
|
622
|
+
* An EMPTY list is a real answer and never an error: a query nobody has edited
|
|
623
|
+
* since this shipped may genuinely have nothing recorded. What the bundled
|
|
624
|
+
* store does about that — see `readRevisions` — is a store's decision, and a
|
|
625
|
+
* consumer must read "nothing recorded" as itself rather than as "nothing has
|
|
626
|
+
* changed".
|
|
627
|
+
*/
|
|
628
|
+
listSavedQueryRevisions?(id: string): Promise<CatalogRevision[]>;
|
|
483
629
|
listDashboards(): Promise<Dashboard[]>;
|
|
484
630
|
getDashboard(id: string): Promise<Dashboard | undefined>;
|
|
485
631
|
saveDashboard(input: {
|
|
@@ -498,5 +644,13 @@ export interface CatalogWorkspaceStore {
|
|
|
498
644
|
recordEvent(event: Omit<CatalogAuditEvent, 'id'>): Promise<void>;
|
|
499
645
|
listEvents(query: AuditQuery): Promise<CatalogAuditEvent[]>;
|
|
500
646
|
}
|
|
647
|
+
/**
|
|
648
|
+
* Whether this store keeps a saved query's history.
|
|
649
|
+
*
|
|
650
|
+
* Checks the method rather than a flag, the same way {@link isWorkspaceStore}
|
|
651
|
+
* and `supportsWorkflows` do: a flag is a claim and a method is the thing
|
|
652
|
+
* itself.
|
|
653
|
+
*/
|
|
654
|
+
export declare function supportsSavedQueryRevisions(store: CatalogWorkspaceStore): store is CatalogWorkspaceStore & Required<Pick<CatalogWorkspaceStore, 'listSavedQueryRevisions'>>;
|
|
501
655
|
export declare function isWorkspaceStore(store: unknown): store is CatalogWorkspaceStore;
|
|
502
656
|
export declare const CATALOG_WORKSPACE_STORE: unique symbol;
|
|
@@ -9,12 +9,60 @@
|
|
|
9
9
|
* mount the catalog without any of this and notice nothing missing.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.CATALOG_WORKSPACE_STORE = exports.CATALOG_TRACE_STORE = exports.CATALOG_TRACE_OUTCOMES = void 0;
|
|
12
|
+
exports.CATALOG_WORKSPACE_STORE = exports.CATALOG_TRACE_STORE = exports.CATALOG_TRACE_OUTCOMES = exports.CATALOG_REVISION_LIMIT = void 0;
|
|
13
13
|
exports.isCatalogTraceOutcome = isCatalogTraceOutcome;
|
|
14
14
|
exports.traceOutcomeFilter = traceOutcomeFilter;
|
|
15
15
|
exports.isTraceStore = isTraceStore;
|
|
16
16
|
exports.embeddedVisualization = embeddedVisualization;
|
|
17
|
+
exports.supportsSavedQueryRevisions = supportsSavedQueryRevisions;
|
|
17
18
|
exports.isWorkspaceStore = isWorkspaceStore;
|
|
19
|
+
/**
|
|
20
|
+
* How many revisions are kept per subject. Writing a newer one drops the oldest
|
|
21
|
+
* beyond this.
|
|
22
|
+
*
|
|
23
|
+
* ## Why there is a cap at all
|
|
24
|
+
*
|
|
25
|
+
* This is append-only text that grows forever, and it is the fourth append-only
|
|
26
|
+
* table in the bundled store. The other three earn their unboundedness and this
|
|
27
|
+
* one does not. An audit event and a connector run are each one small row per
|
|
28
|
+
* *thing that happened*, at a rate an operator can read off their own load
|
|
29
|
+
* schedule; staged rows are dropped the moment the run that produced them is
|
|
30
|
+
* finished with. A revision is neither: it grows with how often somebody edits,
|
|
31
|
+
* which nobody meters, and every row carries a whole code body rather than a
|
|
32
|
+
* counter. Unpredictable in rate *and* large per row is the combination worth
|
|
33
|
+
* bounding — and "this grows; here is the query to prune it" would have been a
|
|
34
|
+
* fourth unbounded table with a paragraph in front of it.
|
|
35
|
+
*
|
|
36
|
+
* ## Why a count per subject rather than an age bound
|
|
37
|
+
*
|
|
38
|
+
* An age bound keys the wrong thing. A transform edited twice in 2019 and relied
|
|
39
|
+
* on ever since would lose both revisions, while one edited daily keeps
|
|
40
|
+
* everything — exactly backwards. What makes a revision unrecoverable is being
|
|
41
|
+
* superseded, so that is what the bound counts.
|
|
42
|
+
*
|
|
43
|
+
* ## What it costs, stated rather than implied
|
|
44
|
+
*
|
|
45
|
+
* A run's `transformVersion` can name a revision that has been evicted: a
|
|
46
|
+
* transform saved more than this many times can no longer produce its earliest
|
|
47
|
+
* code. That loss is real. It is strictly smaller than the one it replaces —
|
|
48
|
+
* where every version but the newest was unrecoverable — and it is visible
|
|
49
|
+
* rather than silent, because a caller holding a version older than the oldest
|
|
50
|
+
* revision in the list can see that the list does not reach that far.
|
|
51
|
+
*
|
|
52
|
+
* At the cap a 4 KB body costs 200 KB per subject, so a thousand heavily-edited
|
|
53
|
+
* subjects cost roughly 200 MB. That is a ceiling, which is the point of having
|
|
54
|
+
* one.
|
|
55
|
+
*
|
|
56
|
+
* ## Why a constant and not a module option
|
|
57
|
+
*
|
|
58
|
+
* The number is part of what this table promises, and a console should be able
|
|
59
|
+
* to print "the last 50 are kept" without a round trip to ask which deployment
|
|
60
|
+
* it is talking to. A knob is also a promise to support every value of it,
|
|
61
|
+
* including the one that switches the feature off and is then reported as a bug.
|
|
62
|
+
* It becomes an option on the day there is a deployment it is wrong for, rather
|
|
63
|
+
* than in anticipation of one.
|
|
64
|
+
*/
|
|
65
|
+
exports.CATALOG_REVISION_LIMIT = 50;
|
|
18
66
|
/**
|
|
19
67
|
* The same events, told as stories instead of as a list.
|
|
20
68
|
*
|
|
@@ -102,6 +150,16 @@ function embeddedVisualization(saved, cardLibrary) {
|
|
|
102
150
|
const base = saved ?? { kind: 'table' };
|
|
103
151
|
return cardLibrary ? { ...base, library: cardLibrary } : base;
|
|
104
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Whether this store keeps a saved query's history.
|
|
155
|
+
*
|
|
156
|
+
* Checks the method rather than a flag, the same way {@link isWorkspaceStore}
|
|
157
|
+
* and `supportsWorkflows` do: a flag is a claim and a method is the thing
|
|
158
|
+
* itself.
|
|
159
|
+
*/
|
|
160
|
+
function supportsSavedQueryRevisions(store) {
|
|
161
|
+
return typeof store.listSavedQueryRevisions === 'function';
|
|
162
|
+
}
|
|
105
163
|
function isWorkspaceStore(store) {
|
|
106
164
|
return (typeof store === 'object' &&
|
|
107
165
|
store !== null &&
|
package/dist/client.d.ts
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* own UI. The endpoints alone are not an API; the endpoints plus the response
|
|
10
10
|
* types are.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
import type { DeleteReconciliation, LoadExpectation, RowCountBound, StoredLoadExpectation } from './catalog.pipeline';
|
|
13
|
+
export type { AuditQuery, CatalogAuditEvent, CatalogRevision, Dashboard, DashboardCard, QueryVisualization, SaveQueryInput, SavedQuery, } from './catalog.workspace';
|
|
14
|
+
export { CATALOG_REVISION_LIMIT } from './catalog.workspace';
|
|
13
15
|
export type { CatalogQueryRelation, CatalogQueryRequest, CatalogQueryResult, } from './catalog.query';
|
|
14
16
|
export type { CatalogSearchField, CatalogSearchHit, CatalogSearchKind, CatalogSearchRank, CatalogSearchResult, } from './search.types';
|
|
15
17
|
export type { CatalogGraph, CatalogObjectPage, CatalogObjectQuery, CatalogObjectTypeDef, CatalogOverlay, CatalogPropertyDef, CatalogRelationDef, CatalogSnapshot, RelationKind, ScalarType, } from './catalog.types';
|
|
@@ -66,6 +68,15 @@ export declare const catalogRoutes: {
|
|
|
66
68
|
readonly workspaceCapabilities: () => string;
|
|
67
69
|
readonly savedQueries: () => string;
|
|
68
70
|
readonly savedQuery: (id: string) => string;
|
|
71
|
+
/**
|
|
72
|
+
* Every SQL this query has ever been.
|
|
73
|
+
*
|
|
74
|
+
* A sub-resource of the saved query rather than a `?version=` on it, because
|
|
75
|
+
* the question a diff screen asks first is "what were all of them" — it has to
|
|
76
|
+
* see the list before it knows which two to compare, and one request that
|
|
77
|
+
* answers that beats a list plus two fetches.
|
|
78
|
+
*/
|
|
79
|
+
readonly savedQueryRevisions: (id: string) => string;
|
|
69
80
|
readonly runSavedQuery: (id: string) => string;
|
|
70
81
|
readonly exportSavedQuery: (id: string) => string;
|
|
71
82
|
readonly dashboards: () => string;
|
|
@@ -96,3 +107,111 @@ export { CONNECTOR_KINDS, isConnectorKind, isTransformLanguage, isWorkflowEdge,
|
|
|
96
107
|
export { validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_STATUSES, workflowGraphHash, workflowRunOrder, isWorkflowExecutionMode, isWorkflowNodeKind, isWorkflowStatus, } from './catalog.pipeline';
|
|
97
108
|
export type { WorkflowStatus } from './catalog.pipeline';
|
|
98
109
|
export type { CatalogTrace, CatalogTraceList, CatalogTraceOutcome, CatalogTraceSpan, TraceQuery, } from './catalog.workspace';
|
|
110
|
+
export type { CatalogLoadExpectations, DeleteReconciliation, LoadExpectation, RowCountBound, StoredLoadExpectation, } from './catalog.pipeline';
|
|
111
|
+
/**
|
|
112
|
+
* The three answers to "how do deletions at the source reach this type", as a
|
|
113
|
+
* value.
|
|
114
|
+
*
|
|
115
|
+
* A list rather than only the union, because the editor on the Model screen has
|
|
116
|
+
* to offer them and a hand-written array in a component is the copy that drifts
|
|
117
|
+
* — the same argument {@link CONNECTOR_KINDS} makes one screen over. The server
|
|
118
|
+
* validates against this too: a `strategy` off the wire is `string` until
|
|
119
|
+
* something checks it, and the check and the dropdown reading one list is what
|
|
120
|
+
* stops the two from disagreeing about what is acceptable.
|
|
121
|
+
*
|
|
122
|
+
* **There are three and there is deliberately no fourth.** Tombstones off a
|
|
123
|
+
* change feed is the correct answer and needs machinery nothing here has; a
|
|
124
|
+
* strategy name that nothing implements is a dropdown with a lie in it. See
|
|
125
|
+
* `DeleteReconciliation` for the whole argument.
|
|
126
|
+
*/
|
|
127
|
+
export declare const DELETE_RECONCILIATION_STRATEGIES: readonly ["accepted", "soft-deleted-at-source", "periodic-full-reload"];
|
|
128
|
+
export type DeleteReconciliationStrategy = (typeof DELETE_RECONCILIATION_STRATEGIES)[number];
|
|
129
|
+
/** Whether a value off the wire names one of the three. */
|
|
130
|
+
export declare function isDeleteReconciliationStrategy(value: unknown): value is DeleteReconciliationStrategy;
|
|
131
|
+
/**
|
|
132
|
+
* What an operator sends to set a type's expectation.
|
|
133
|
+
*
|
|
134
|
+
* Both fields optional and both meaning "leave this alone" when absent, which is
|
|
135
|
+
* why they are not simply `LoadExpectation`: a request that omits `rowCount`
|
|
136
|
+
* has said nothing about row counts, and reading that as "clear it" would let a
|
|
137
|
+
* form that only renders the delete strategy silently drop a bound somebody set.
|
|
138
|
+
* Clearing the whole stored row is `DELETE`, which is a decision with a verb on
|
|
139
|
+
* it.
|
|
140
|
+
*/
|
|
141
|
+
export interface LoadExpectationInput {
|
|
142
|
+
deletes?: DeleteReconciliation;
|
|
143
|
+
rowCount?: Partial<RowCountBound>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The resolved expectation for one type, and which layer won each field.
|
|
147
|
+
*
|
|
148
|
+
* The provenance is the whole reason this is not just a `LoadExpectation`. The
|
|
149
|
+
* policy is sourced from three layers — `host.byType[type]`, then the stored row
|
|
150
|
+
* an operator set, then `host.default` — and a screen that showed only the
|
|
151
|
+
* answer would let somebody edit a field this deployment has pinned in code and
|
|
152
|
+
* watch the edit vanish on the next read, with nothing anywhere saying why.
|
|
153
|
+
* {@link hostLocked} is what lets it say "this deployment fixed it" instead.
|
|
154
|
+
*/
|
|
155
|
+
export interface ResolvedLoadExpectation {
|
|
156
|
+
typeName: string;
|
|
157
|
+
/** The three layers merged, field by field. What the load is actually judged against. */
|
|
158
|
+
resolved: LoadExpectation;
|
|
159
|
+
/**
|
|
160
|
+
* Which layer supplied the delete strategy.
|
|
161
|
+
*
|
|
162
|
+
* `'default'` means the host's house-wide `default` did. `'none'` means
|
|
163
|
+
* nothing did, anywhere — which is not a gap to be filled in silently: it is
|
|
164
|
+
* the state that refuses every incremental load of this type, and the one the
|
|
165
|
+
* screen most needs to name.
|
|
166
|
+
*/
|
|
167
|
+
deletesFrom: 'host' | 'stored' | 'default' | 'none';
|
|
168
|
+
/**
|
|
169
|
+
* Which layer supplied the row-count bound — the strongest one that set any
|
|
170
|
+
* field of it, since the three are merged key by key rather than replaced
|
|
171
|
+
* whole.
|
|
172
|
+
*
|
|
173
|
+
* There is no `'none'`, and that is a statement rather than an omission: a
|
|
174
|
+
* bound always applies. Where no layer says anything the built-in
|
|
175
|
+
* `DEFAULT_ROW_COUNT_BOUND` does, and that is what `'default'` covers as well
|
|
176
|
+
* as the host's own `default`.
|
|
177
|
+
*/
|
|
178
|
+
rowCountFrom: 'host' | 'stored' | 'default';
|
|
179
|
+
/** The operator's row, present whether or not it won anything. */
|
|
180
|
+
stored?: StoredLoadExpectation;
|
|
181
|
+
/**
|
|
182
|
+
* Which fields this deployment declared in code, per field.
|
|
183
|
+
*
|
|
184
|
+
* True means a stored value for that field would never apply, so the editor
|
|
185
|
+
* shows it disabled and says so. Only `host.byType[type]` locks: `host.default`
|
|
186
|
+
* is the weakest layer and an operator's row beats it, so a house-wide default
|
|
187
|
+
* is not a lock and must not be drawn as one.
|
|
188
|
+
*/
|
|
189
|
+
hostLocked: {
|
|
190
|
+
deletes: boolean;
|
|
191
|
+
rowCount: boolean;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Where the per-type expectations sit, relative to wherever the pipeline
|
|
196
|
+
* controller was mounted.
|
|
197
|
+
*
|
|
198
|
+
* A function of the base path rather than a frozen object like
|
|
199
|
+
* {@link catalogRoutes}, and the difference is the one `routes.ts` in the React
|
|
200
|
+
* package draws: the catalog controller's paths cannot move, and these move with
|
|
201
|
+
* whatever `path` the host passed to `CatalogPipelineModule.forRoot` — the
|
|
202
|
+
* routes below are `<path>/pipeline/expectations`, and `/pipeline` is only the
|
|
203
|
+
* default.
|
|
204
|
+
*
|
|
205
|
+
* Two builders for four routes: `PUT` and `DELETE` address the same path a `GET`
|
|
206
|
+
* of one type does, and a builder per verb would be three names for one string.
|
|
207
|
+
*/
|
|
208
|
+
export declare function pipelineExpectationRoutes(basePath?: string): {
|
|
209
|
+
/** Every stored row, plus the types the host has locked. `GET`, `catalog:read`. */
|
|
210
|
+
readonly expectations: () => string;
|
|
211
|
+
/**
|
|
212
|
+
* One type: `GET` for the resolved expectation and its provenance, `PUT` to
|
|
213
|
+
* set the stored row, `DELETE` to drop it. The writes need `catalog:curate`
|
|
214
|
+
* and a signed-in person.
|
|
215
|
+
*/
|
|
216
|
+
readonly expectation: (typeName: string) => string;
|
|
217
|
+
};
|
package/dist/client.js
CHANGED
|
@@ -11,7 +11,14 @@
|
|
|
11
11
|
* types are.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.isWorkflowStatus = exports.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_STATUSES = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_EXECUTION_MODES = exports.validateWorkflow = exports.TRANSFORM_LANGUAGES = exports.isWorkflowNode = exports.isWorkflowEdge = exports.isTransformLanguage = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.catalogRoutes = void 0;
|
|
14
|
+
exports.DELETE_RECONCILIATION_STRATEGIES = exports.isWorkflowStatus = exports.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_STATUSES = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_EXECUTION_MODES = exports.validateWorkflow = exports.TRANSFORM_LANGUAGES = exports.isWorkflowNode = exports.isWorkflowEdge = exports.isTransformLanguage = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.catalogRoutes = exports.CATALOG_REVISION_LIMIT = void 0;
|
|
15
|
+
exports.isDeleteReconciliationStrategy = isDeleteReconciliationStrategy;
|
|
16
|
+
exports.pipelineExpectationRoutes = pipelineExpectationRoutes;
|
|
17
|
+
// A value, not a type: a screen saying how far back the history goes should read
|
|
18
|
+
// the number rather than print one of its own. See its docblock for what the cap
|
|
19
|
+
// costs.
|
|
20
|
+
var catalog_workspace_1 = require("./catalog.workspace");
|
|
21
|
+
Object.defineProperty(exports, "CATALOG_REVISION_LIMIT", { enumerable: true, get: function () { return catalog_workspace_1.CATALOG_REVISION_LIMIT; } });
|
|
15
22
|
/**
|
|
16
23
|
* Builds the paths the catalog controller serves, relative to wherever it was
|
|
17
24
|
* mounted. Kept as string builders rather than a fetch wrapper so the host
|
|
@@ -40,6 +47,15 @@ exports.catalogRoutes = {
|
|
|
40
47
|
workspaceCapabilities: () => '/catalog/workspace/capabilities',
|
|
41
48
|
savedQueries: () => '/catalog/saved-queries',
|
|
42
49
|
savedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}`,
|
|
50
|
+
/**
|
|
51
|
+
* Every SQL this query has ever been.
|
|
52
|
+
*
|
|
53
|
+
* A sub-resource of the saved query rather than a `?version=` on it, because
|
|
54
|
+
* the question a diff screen asks first is "what were all of them" — it has to
|
|
55
|
+
* see the list before it knows which two to compare, and one request that
|
|
56
|
+
* answers that beats a list plus two fetches.
|
|
57
|
+
*/
|
|
58
|
+
savedQueryRevisions: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}/revisions`,
|
|
43
59
|
runSavedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}/run`,
|
|
44
60
|
exportSavedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}/export.csv`,
|
|
45
61
|
dashboards: () => '/catalog/dashboards',
|
|
@@ -99,3 +115,56 @@ Object.defineProperty(exports, "workflowRunOrder", { enumerable: true, get: func
|
|
|
99
115
|
Object.defineProperty(exports, "isWorkflowExecutionMode", { enumerable: true, get: function () { return catalog_pipeline_2.isWorkflowExecutionMode; } });
|
|
100
116
|
Object.defineProperty(exports, "isWorkflowNodeKind", { enumerable: true, get: function () { return catalog_pipeline_2.isWorkflowNodeKind; } });
|
|
101
117
|
Object.defineProperty(exports, "isWorkflowStatus", { enumerable: true, get: function () { return catalog_pipeline_2.isWorkflowStatus; } });
|
|
118
|
+
/**
|
|
119
|
+
* The three answers to "how do deletions at the source reach this type", as a
|
|
120
|
+
* value.
|
|
121
|
+
*
|
|
122
|
+
* A list rather than only the union, because the editor on the Model screen has
|
|
123
|
+
* to offer them and a hand-written array in a component is the copy that drifts
|
|
124
|
+
* — the same argument {@link CONNECTOR_KINDS} makes one screen over. The server
|
|
125
|
+
* validates against this too: a `strategy` off the wire is `string` until
|
|
126
|
+
* something checks it, and the check and the dropdown reading one list is what
|
|
127
|
+
* stops the two from disagreeing about what is acceptable.
|
|
128
|
+
*
|
|
129
|
+
* **There are three and there is deliberately no fourth.** Tombstones off a
|
|
130
|
+
* change feed is the correct answer and needs machinery nothing here has; a
|
|
131
|
+
* strategy name that nothing implements is a dropdown with a lie in it. See
|
|
132
|
+
* `DeleteReconciliation` for the whole argument.
|
|
133
|
+
*/
|
|
134
|
+
exports.DELETE_RECONCILIATION_STRATEGIES = [
|
|
135
|
+
'accepted',
|
|
136
|
+
'soft-deleted-at-source',
|
|
137
|
+
'periodic-full-reload',
|
|
138
|
+
];
|
|
139
|
+
/** Whether a value off the wire names one of the three. */
|
|
140
|
+
function isDeleteReconciliationStrategy(value) {
|
|
141
|
+
return (typeof value === 'string' &&
|
|
142
|
+
exports.DELETE_RECONCILIATION_STRATEGIES.includes(value));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Where the per-type expectations sit, relative to wherever the pipeline
|
|
146
|
+
* controller was mounted.
|
|
147
|
+
*
|
|
148
|
+
* A function of the base path rather than a frozen object like
|
|
149
|
+
* {@link catalogRoutes}, and the difference is the one `routes.ts` in the React
|
|
150
|
+
* package draws: the catalog controller's paths cannot move, and these move with
|
|
151
|
+
* whatever `path` the host passed to `CatalogPipelineModule.forRoot` — the
|
|
152
|
+
* routes below are `<path>/pipeline/expectations`, and `/pipeline` is only the
|
|
153
|
+
* default.
|
|
154
|
+
*
|
|
155
|
+
* Two builders for four routes: `PUT` and `DELETE` address the same path a `GET`
|
|
156
|
+
* of one type does, and a builder per verb would be three names for one string.
|
|
157
|
+
*/
|
|
158
|
+
function pipelineExpectationRoutes(basePath = '/pipeline') {
|
|
159
|
+
const base = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;
|
|
160
|
+
return {
|
|
161
|
+
/** Every stored row, plus the types the host has locked. `GET`, `catalog:read`. */
|
|
162
|
+
expectations: () => `${base}/expectations`,
|
|
163
|
+
/**
|
|
164
|
+
* One type: `GET` for the resolved expectation and its provenance, `PUT` to
|
|
165
|
+
* set the stored row, `DELETE` to drop it. The writes need `catalog:curate`
|
|
166
|
+
* and a signed-in person.
|
|
167
|
+
*/
|
|
168
|
+
expectation: (typeName) => `${base}/expectations/${encodeURIComponent(typeName)}`,
|
|
169
|
+
};
|
|
170
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,17 +8,17 @@ 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, type CatalogConnection, type CatalogConnector, type ConnectionCheck, CONNECTOR_KINDS, type CatalogPipelineStore, type CatalogStageStore, type CatalogTransform, type CatalogWorkflow, type CatalogWorkflowCapabilities, type CatalogWorkflowStore, type ConnectorKind, type ConnectorRun, isConnectorKind, isPipelineStore, isTransformLanguage, isWorkflowEdge, isWorkflowExecutionMode, isWorkflowNode, isWorkflowNodeKind, isWorkflowStatus, supportsWorkflows, supportsWorkflowStages, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, type TransformLanguage, type TransformResult, type TransformRunner, validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_STATUSES, type WorkflowEdge, type WorkflowExecutionMode, type WorkflowGraph, workflowGraphHash, type WorkflowIssueCode, type WorkflowNode, type WorkflowNodeKind, type WorkflowNodeOutcome, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowSinkNode, type WorkflowSourceNode, type WorkflowStageRef, type WorkflowStatus, type WorkflowTransformNode, type WorkflowValidationIssue, } from './catalog.pipeline';
|
|
11
|
+
export { CATALOG_PIPELINE_STORE, type CatalogConnection, type CatalogConnector, type ConnectionCheck, CONNECTOR_KINDS, type CatalogLoadExpectations, type CatalogLoadExpectationStore, type CatalogPipelineStore, type CatalogStageStore, type CatalogTransform, type CatalogWorkflow, type CatalogWorkflowCapabilities, type CatalogWorkflowStore, type ConnectorKind, type ConnectorRun, type DeleteReconciliation, isConnectorKind, isPipelineStore, isTransformLanguage, type LoadExpectation, type RowCountBound, type StoredLoadExpectation, supportsLoadExpectations, supportsTransformRevisions, isWorkflowEdge, isWorkflowExecutionMode, isWorkflowNode, isWorkflowNodeKind, isWorkflowStatus, supportsWorkflows, supportsWorkflowStages, TRANSFORM_RUNNER, TRANSFORM_LANGUAGES, type TransformLanguage, type TransformResult, type TransformRunner, validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, WORKFLOW_STATUSES, type WorkflowEdge, type WorkflowExecutionMode, type WorkflowGraph, workflowGraphHash, type WorkflowIssueCode, type WorkflowNode, type WorkflowNodeKind, type WorkflowNodeOutcome, type WorkflowNodeStepInput, type WorkflowNodeStepOutput, workflowRunOrder, type WorkflowSinkNode, type WorkflowSourceNode, type WorkflowStageRef, type WorkflowStatus, type WorkflowTransformNode, type WorkflowValidationIssue, } from './catalog.pipeline';
|
|
12
12
|
export * from './catalog.environment';
|
|
13
13
|
export { QueryCache, toCsv } from './catalog.query-cache';
|
|
14
14
|
export { SubprocessTransformRunner, type TransformRunnerOptions, } from './transform-runner';
|
|
15
15
|
export { CatalogService } from './catalog.service';
|
|
16
16
|
export { DEFAULT_SEARCH_LIMIT, MAX_SEARCH_LIMIT, bestMatch, emptySearch, maySearch, type SearchInput, type SearchableDashboard, type SearchableSavedQuery, searchCatalog, visibleToPrincipal, } from './search';
|
|
17
17
|
export type { CatalogSearchField, CatalogSearchHit, CatalogSearchKind, CatalogSearchRank, CatalogSearchResult, } from './search.types';
|
|
18
|
-
export { type AuditQuery, CATALOG_TRACE_OUTCOMES, CATALOG_TRACE_STORE, CATALOG_WORKSPACE_STORE, type CatalogAuditEvent, type CatalogTrace, type CatalogTraceList, type CatalogTraceOutcome, type CatalogTraceSpan, type CatalogTraceStore, type CatalogTraceTotals, type CatalogUnlinkedList, type CatalogWorkspaceStore, type Dashboard, type DashboardCard, type EmbeddedChart, type EmbeddedChartPlacement, type EmbeddedDashboard, embeddedVisualization, isCatalogTraceOutcome, isTraceStore, isWorkspaceStore, type QueryVisualization, type SaveQueryInput, type SavedQuery, type TraceQuery, traceOutcomeFilter, } from './catalog.workspace';
|
|
18
|
+
export { type AuditQuery, CATALOG_REVISION_LIMIT, CATALOG_TRACE_OUTCOMES, CATALOG_TRACE_STORE, CATALOG_WORKSPACE_STORE, type CatalogAuditEvent, type CatalogRevision, type CatalogTrace, type CatalogTraceList, type CatalogTraceOutcome, type CatalogTraceSpan, type CatalogTraceStore, type CatalogTraceTotals, type CatalogUnlinkedList, type CatalogWorkspaceStore, type Dashboard, type DashboardCard, type EmbeddedChart, type EmbeddedChartPlacement, type EmbeddedDashboard, embeddedVisualization, isCatalogTraceOutcome, isTraceStore, isWorkspaceStore, type QueryVisualization, type SaveQueryInput, type SavedQuery, supportsSavedQueryRevisions, type TraceQuery, traceOutcomeFilter, } from './catalog.workspace';
|
|
19
19
|
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';
|
|
20
20
|
export * from './catalog.access';
|
|
21
|
-
export { assertNoColumnCollisions, CATALOG_RESERVED_COLUMNS, CATALOG_SNAPSHOT_MODES, CATALOG_STORE, type CarryForwardResult, type CatalogColumnCollision, CatalogColumnCollisionError, type CatalogMergeStore, type CatalogReadQuery, type CatalogReadResult, type CatalogReadStore, type CatalogReservedColumn, type CatalogSnapshotMode, type CatalogStoreCapabilities, type CatalogWriteStore, type ColumnCollisionOptions, findColumnCollisions, isCatalogStoreCapabilities, isReservedColumn, isWriteStore, type SnapshotRef, supportsCarryForward, } from './catalog.store';
|
|
21
|
+
export { assertNoColumnCollisions, assertSafeIdentifier, CATALOG_RESERVED_COLUMNS, CATALOG_SNAPSHOT_MODES, CATALOG_STORE, type CarryForwardResult, type CatalogColumnCollision, CatalogColumnCollisionError, type CatalogMergeStore, type CatalogReadQuery, type CatalogReadResult, type CatalogReadStore, type CatalogReservedColumn, type CatalogSnapshotMode, type CatalogStoreCapabilities, type CatalogWriteStore, type ColumnCollisionOptions, findColumnCollisions, isCatalogStoreCapabilities, isReservedColumn, isSafeIdentifier, isWriteStore, type SnapshotRef, supportsCarryForward, UnsafeIdentifierError, } from './catalog.store';
|
|
22
22
|
export { MikroOrmReadStore } from './stores/mikro-orm-read.store';
|
|
23
23
|
export type { CatalogGraph, CatalogObjectPage, CatalogObjectQuery, CatalogObjectTypeDef, CatalogOverlay, CatalogPropertyDef, CatalogRelationDef, CatalogSnapshot, RelationKind, ScalarType, } from './catalog.types';
|
|
24
24
|
export { REQUIRED_SCOPES, REQUIRES_HUMAN, RequireHuman, RequireScopes, } from './catalog.route-auth';
|