@dudousxd/nestjs-catalog 0.1.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/LICENSE +21 -0
- package/README.md +123 -0
- package/dist/catalog.controller.d.ts +8 -0
- package/dist/catalog.controller.js +482 -0
- package/dist/catalog.decorators.d.ts +37 -0
- package/dist/catalog.decorators.js +50 -0
- package/dist/catalog.environment.d.ts +442 -0
- package/dist/catalog.environment.js +645 -0
- package/dist/catalog.events.d.ts +179 -0
- package/dist/catalog.events.js +110 -0
- package/dist/catalog.module.d.ts +5 -0
- package/dist/catalog.module.js +71 -0
- package/dist/catalog.options.d.ts +79 -0
- package/dist/catalog.options.js +4 -0
- package/dist/catalog.overlay-store.d.ts +25 -0
- package/dist/catalog.overlay-store.js +44 -0
- package/dist/catalog.overlay-store.token.d.ts +1 -0
- package/dist/catalog.overlay-store.token.js +4 -0
- package/dist/catalog.pipeline.d.ts +800 -0
- package/dist/catalog.pipeline.js +606 -0
- package/dist/catalog.principal.d.ts +209 -0
- package/dist/catalog.principal.js +245 -0
- package/dist/catalog.query-cache.d.ts +25 -0
- package/dist/catalog.query-cache.js +0 -0
- package/dist/catalog.query.d.ts +76 -0
- package/dist/catalog.query.js +64 -0
- package/dist/catalog.registry.base.d.ts +21 -0
- package/dist/catalog.registry.base.js +17 -0
- package/dist/catalog.registry.d.ts +44 -0
- package/dist/catalog.registry.js +359 -0
- package/dist/catalog.service.d.ts +115 -0
- package/dist/catalog.service.js +366 -0
- package/dist/catalog.store.d.ts +419 -0
- package/dist/catalog.store.js +175 -0
- package/dist/catalog.types.d.ts +165 -0
- package/dist/catalog.types.js +19 -0
- package/dist/catalog.workspace.d.ts +426 -0
- package/dist/catalog.workspace.js +87 -0
- package/dist/client.d.ts +86 -0
- package/dist/client.js +83 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +109 -0
- package/dist/stores/mikro-orm-read.store.d.ts +20 -0
- package/dist/stores/mikro-orm-read.store.js +120 -0
- package/dist/transform-runner.d.ts +54 -0
- package/dist/transform-runner.js +280 -0
- package/package.json +54 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The things people make *with* a catalog, as opposed to the model itself:
|
|
4
|
+
* saved queries, dashboards, and the record of what happened to all of it.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from the store interfaces because these are optional in a
|
|
7
|
+
* different way. A store that cannot run SQL simply has no saved queries; a
|
|
8
|
+
* store with no event log still serves every read. A host should be able to
|
|
9
|
+
* mount the catalog without any of this and notice nothing missing.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CATALOG_WORKSPACE_STORE = exports.CATALOG_TRACE_STORE = exports.CATALOG_TRACE_OUTCOMES = void 0;
|
|
13
|
+
exports.isCatalogTraceOutcome = isCatalogTraceOutcome;
|
|
14
|
+
exports.traceOutcomeFilter = traceOutcomeFilter;
|
|
15
|
+
exports.isTraceStore = isTraceStore;
|
|
16
|
+
exports.isWorkspaceStore = isWorkspaceStore;
|
|
17
|
+
/**
|
|
18
|
+
* The same events, told as stories instead of as a list.
|
|
19
|
+
*
|
|
20
|
+
* A flat trail answers "what happened" and is useless for "what happened to
|
|
21
|
+
* *this load*" — the question anybody actually has when a number looks wrong.
|
|
22
|
+
* The spine of the answer is already in the data and needed no new plumbing:
|
|
23
|
+
* a connector run, the snapshot it writes, every batch, the commit and the
|
|
24
|
+
* finish all carry the same `snapshotId`, and when the durable engine schedules
|
|
25
|
+
* the run that id *is* the durable run id. So a trace is not something this
|
|
26
|
+
* library invents; it is the correlation that was always there, grouped.
|
|
27
|
+
*
|
|
28
|
+
* What is deliberately *not* here is a parent for events that carry no such id.
|
|
29
|
+
* A curation edit and a transform change are standalone acts, and the fact that
|
|
30
|
+
* one happened in the same second as a load is a coincidence, not causality —
|
|
31
|
+
* attaching them to the nearest run would fabricate a lineage that reads as
|
|
32
|
+
* evidence. They come back separately, as {@link CatalogTraceList.unlinked}.
|
|
33
|
+
*/
|
|
34
|
+
exports.CATALOG_TRACE_OUTCOMES = [
|
|
35
|
+
/**
|
|
36
|
+
* Something claimed to start and has not reported back. Never rendered as a
|
|
37
|
+
* result: a load still in flight has no rows anybody should be relying on.
|
|
38
|
+
*/
|
|
39
|
+
'running',
|
|
40
|
+
/** It reached a terminal event that said so. */
|
|
41
|
+
'succeeded',
|
|
42
|
+
/** It reached a terminal event that said it did not. */
|
|
43
|
+
'failed',
|
|
44
|
+
/**
|
|
45
|
+
* It stopped without ever saying how it went — batches written and never
|
|
46
|
+
* committed, a snapshot dropped, a process that died between the two.
|
|
47
|
+
*
|
|
48
|
+
* Its own outcome rather than being folded into "failed" or, far worse, left
|
|
49
|
+
* to look successful because rows did land. Uncommitted rows are invisible to
|
|
50
|
+
* readers, so a trace that ends here moved no data at all, and a screen that
|
|
51
|
+
* showed it in green would be reporting a silent data loss as a good night.
|
|
52
|
+
*/
|
|
53
|
+
'incomplete',
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Narrows an outcome that arrived as a string — a query parameter, a database
|
|
57
|
+
* column. Same reason as every other guard in this package: a second
|
|
58
|
+
* hand-maintained copy of these names is what drifts.
|
|
59
|
+
*/
|
|
60
|
+
function isCatalogTraceOutcome(value) {
|
|
61
|
+
return exports.CATALOG_TRACE_OUTCOMES.some((outcome) => outcome === value);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Normalises {@link TraceQuery.outcome} to a list, or `undefined` for no filter.
|
|
65
|
+
*
|
|
66
|
+
* Exported so a store and a controller narrow it the same way. The distinction
|
|
67
|
+
* that has to survive is `undefined` (no filter) versus `[]` (a filter nothing
|
|
68
|
+
* satisfies), and a store hand-rolling this is one `?? []` away from collapsing
|
|
69
|
+
* the two.
|
|
70
|
+
*/
|
|
71
|
+
function traceOutcomeFilter(outcome) {
|
|
72
|
+
if (outcome === undefined)
|
|
73
|
+
return undefined;
|
|
74
|
+
return Array.isArray(outcome) ? outcome : [outcome];
|
|
75
|
+
}
|
|
76
|
+
exports.CATALOG_TRACE_STORE = Symbol('CATALOG_TRACE_STORE');
|
|
77
|
+
function isTraceStore(store) {
|
|
78
|
+
return (typeof store === 'object' &&
|
|
79
|
+
store !== null &&
|
|
80
|
+
typeof Reflect.get(store, 'listTraces') === 'function');
|
|
81
|
+
}
|
|
82
|
+
function isWorkspaceStore(store) {
|
|
83
|
+
return (typeof store === 'object' &&
|
|
84
|
+
store !== null &&
|
|
85
|
+
typeof Reflect.get(store, 'listSavedQueries') === 'function');
|
|
86
|
+
}
|
|
87
|
+
exports.CATALOG_WORKSPACE_STORE = Symbol('CATALOG_WORKSPACE_STORE');
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser-facing entry point: `@dudousxd/nestjs-catalog/client`.
|
|
3
|
+
*
|
|
4
|
+
* Types and route builders only — nothing here imports NestJS, MikroORM or
|
|
5
|
+
* anything Node-only, so a browser bundle can take a dependency on it without
|
|
6
|
+
* pulling the server in.
|
|
7
|
+
*
|
|
8
|
+
* This exists so the HTTP surface is genuinely usable by someone writing their
|
|
9
|
+
* own UI. The endpoints alone are not an API; the endpoints plus the response
|
|
10
|
+
* types are.
|
|
11
|
+
*/
|
|
12
|
+
export type { AuditQuery, CatalogAuditEvent, Dashboard, DashboardCard, QueryVisualization, SaveQueryInput, SavedQuery, } from './catalog.workspace';
|
|
13
|
+
export type { CatalogQueryRelation, CatalogQueryRequest, CatalogQueryResult, } from './catalog.query';
|
|
14
|
+
export type { CatalogGraph, CatalogObjectPage, CatalogObjectQuery, CatalogObjectTypeDef, CatalogOverlay, CatalogPropertyDef, CatalogRelationDef, CatalogSnapshot, RelationKind, ScalarType, } from './catalog.types';
|
|
15
|
+
/** What a tier-0 edit to a type may change. */
|
|
16
|
+
export interface TypePatch {
|
|
17
|
+
displayName?: string;
|
|
18
|
+
pluralDisplayName?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
icon?: string;
|
|
21
|
+
group?: string;
|
|
22
|
+
titleProperty?: string;
|
|
23
|
+
}
|
|
24
|
+
/** What a tier-0 edit to a property may change. */
|
|
25
|
+
export interface PropertyPatch {
|
|
26
|
+
displayName?: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
hidden?: boolean;
|
|
29
|
+
order?: number;
|
|
30
|
+
classification?: string;
|
|
31
|
+
unit?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ObjectQueryParams {
|
|
34
|
+
page?: number;
|
|
35
|
+
size?: number;
|
|
36
|
+
search?: string;
|
|
37
|
+
sort?: string;
|
|
38
|
+
dir?: 'asc' | 'desc';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Builds the paths the catalog controller serves, relative to wherever it was
|
|
42
|
+
* mounted. Kept as string builders rather than a fetch wrapper so the host
|
|
43
|
+
* keeps its own HTTP client, interceptors and auth.
|
|
44
|
+
*/
|
|
45
|
+
export declare const catalogRoutes: {
|
|
46
|
+
readonly snapshot: () => string;
|
|
47
|
+
readonly graph: () => string;
|
|
48
|
+
readonly type: (name: string) => string;
|
|
49
|
+
readonly property: (name: string, property: string) => string;
|
|
50
|
+
readonly reset: () => string;
|
|
51
|
+
readonly objects: (name: string) => string;
|
|
52
|
+
readonly snapshots: (name: string) => string;
|
|
53
|
+
readonly queryRelations: () => string;
|
|
54
|
+
readonly query: () => string;
|
|
55
|
+
readonly workspaceCapabilities: () => string;
|
|
56
|
+
readonly savedQueries: () => string;
|
|
57
|
+
readonly savedQuery: (id: string) => string;
|
|
58
|
+
readonly runSavedQuery: (id: string) => string;
|
|
59
|
+
readonly exportSavedQuery: (id: string) => string;
|
|
60
|
+
readonly dashboards: () => string;
|
|
61
|
+
readonly dashboard: (id: string) => string;
|
|
62
|
+
readonly events: () => string;
|
|
63
|
+
readonly traces: () => string;
|
|
64
|
+
readonly trace: (id: string) => string;
|
|
65
|
+
};
|
|
66
|
+
export type { CatalogConnection, CatalogConnector, ConnectionCheck, CatalogTransform, CatalogWorkflow, CatalogWorkflowCapabilities, ConnectorKind, ConnectorRun, TransformLanguage, TransformResult, WorkflowEdge, WorkflowExecutionMode, WorkflowGraph, WorkflowIssueCode, WorkflowNode, WorkflowNodeKind, WorkflowNodeOutcome, WorkflowSinkNode, WorkflowSourceNode, WorkflowStageRef, WorkflowTransformNode, WorkflowValidationIssue, } from './catalog.pipeline';
|
|
67
|
+
export { CONNECTOR_KINDS, isConnectorKind, isTransformLanguage, isWorkflowEdge, isWorkflowNode, TRANSFORM_LANGUAGES, } from './catalog.pipeline';
|
|
68
|
+
/**
|
|
69
|
+
* The workflow validator, shipped to the browser deliberately.
|
|
70
|
+
*
|
|
71
|
+
* A canvas has to be able to say "this graph has a cycle" while somebody is
|
|
72
|
+
* drawing it, and the only way for that answer to match what the server will do
|
|
73
|
+
* is for both to run this function. The alternative — a canvas with its own
|
|
74
|
+
* copy of the rules — is a canvas that eventually lies: either it refuses
|
|
75
|
+
* something the server would take, or it accepts something the server rejects
|
|
76
|
+
* halfway through a load. This is the exception to "types only" on this entry
|
|
77
|
+
* point, and it is safe to make because these functions are pure and import
|
|
78
|
+
* nothing.
|
|
79
|
+
*
|
|
80
|
+
* `workflowGraphHash` is here for the same reason: a canvas can tell whether
|
|
81
|
+
* what is on screen still matches the saved version without asking.
|
|
82
|
+
* `WORKFLOW_NODE_ID_PATTERN` and `WORKFLOW_NODE_KINDS` are what a palette and an
|
|
83
|
+
* id field should be built from rather than from a second copy that drifts.
|
|
84
|
+
*/
|
|
85
|
+
export { validateWorkflow, WORKFLOW_EXECUTION_MODES, WORKFLOW_ISSUE_CODES, WORKFLOW_NODE_ID_PATTERN, WORKFLOW_NODE_KINDS, workflowGraphHash, workflowRunOrder, isWorkflowExecutionMode, isWorkflowNodeKind, } from './catalog.pipeline';
|
|
86
|
+
export type { CatalogTrace, CatalogTraceList, CatalogTraceOutcome, CatalogTraceSpan, TraceQuery, } from './catalog.workspace';
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The browser-facing entry point: `@dudousxd/nestjs-catalog/client`.
|
|
4
|
+
*
|
|
5
|
+
* Types and route builders only — nothing here imports NestJS, MikroORM or
|
|
6
|
+
* anything Node-only, so a browser bundle can take a dependency on it without
|
|
7
|
+
* pulling the server in.
|
|
8
|
+
*
|
|
9
|
+
* This exists so the HTTP surface is genuinely usable by someone writing their
|
|
10
|
+
* own UI. The endpoints alone are not an API; the endpoints plus the response
|
|
11
|
+
* types are.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.isWorkflowNodeKind = exports.isWorkflowExecutionMode = exports.workflowRunOrder = exports.workflowGraphHash = 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;
|
|
15
|
+
/**
|
|
16
|
+
* Builds the paths the catalog controller serves, relative to wherever it was
|
|
17
|
+
* mounted. Kept as string builders rather than a fetch wrapper so the host
|
|
18
|
+
* keeps its own HTTP client, interceptors and auth.
|
|
19
|
+
*/
|
|
20
|
+
exports.catalogRoutes = {
|
|
21
|
+
snapshot: () => '/catalog',
|
|
22
|
+
graph: () => '/catalog/graph',
|
|
23
|
+
type: (name) => `/catalog/types/${encodeURIComponent(name)}`,
|
|
24
|
+
property: (name, property) => `/catalog/types/${encodeURIComponent(name)}/properties/${encodeURIComponent(property)}`,
|
|
25
|
+
reset: () => '/catalog/reset',
|
|
26
|
+
objects: (name) => `/catalog/objects/${encodeURIComponent(name)}`,
|
|
27
|
+
snapshots: (name) => `/catalog/objects/${encodeURIComponent(name)}/snapshots`,
|
|
28
|
+
queryRelations: () => '/catalog/query/relations',
|
|
29
|
+
query: () => '/catalog/query',
|
|
30
|
+
workspaceCapabilities: () => '/catalog/workspace/capabilities',
|
|
31
|
+
savedQueries: () => '/catalog/saved-queries',
|
|
32
|
+
savedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}`,
|
|
33
|
+
runSavedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}/run`,
|
|
34
|
+
exportSavedQuery: (id) => `/catalog/saved-queries/${encodeURIComponent(id)}/export.csv`,
|
|
35
|
+
dashboards: () => '/catalog/dashboards',
|
|
36
|
+
dashboard: (id) => `/catalog/dashboards/${encodeURIComponent(id)}`,
|
|
37
|
+
events: () => '/catalog/events',
|
|
38
|
+
// Grouped into one causal story each, rather than the flat list `events`
|
|
39
|
+
// returns. Both exist because they answer different questions: "what happened
|
|
40
|
+
// recently" and "what happened during that load".
|
|
41
|
+
traces: () => '/catalog/events/traces',
|
|
42
|
+
trace: (id) => `/catalog/events/traces/${encodeURIComponent(id)}`,
|
|
43
|
+
};
|
|
44
|
+
// Values, not types: a form that offers the kinds should read them from here
|
|
45
|
+
// rather than keeping a copy that drifts.
|
|
46
|
+
var catalog_pipeline_1 = require("./catalog.pipeline");
|
|
47
|
+
Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.CONNECTOR_KINDS; } });
|
|
48
|
+
Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
|
|
49
|
+
Object.defineProperty(exports, "isTransformLanguage", { enumerable: true, get: function () { return catalog_pipeline_1.isTransformLanguage; } });
|
|
50
|
+
// The canvas narrows nodes and edges it reads back from HTTP. Without these
|
|
51
|
+
// it either imports them from the package root — dragging NestJS and MikroORM
|
|
52
|
+
// into a browser bundle — or writes its own copy of the checks, which is the
|
|
53
|
+
// drift this entry point exists to prevent.
|
|
54
|
+
Object.defineProperty(exports, "isWorkflowEdge", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowEdge; } });
|
|
55
|
+
Object.defineProperty(exports, "isWorkflowNode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowNode; } });
|
|
56
|
+
Object.defineProperty(exports, "TRANSFORM_LANGUAGES", { enumerable: true, get: function () { return catalog_pipeline_1.TRANSFORM_LANGUAGES; } });
|
|
57
|
+
/**
|
|
58
|
+
* The workflow validator, shipped to the browser deliberately.
|
|
59
|
+
*
|
|
60
|
+
* A canvas has to be able to say "this graph has a cycle" while somebody is
|
|
61
|
+
* drawing it, and the only way for that answer to match what the server will do
|
|
62
|
+
* is for both to run this function. The alternative — a canvas with its own
|
|
63
|
+
* copy of the rules — is a canvas that eventually lies: either it refuses
|
|
64
|
+
* something the server would take, or it accepts something the server rejects
|
|
65
|
+
* halfway through a load. This is the exception to "types only" on this entry
|
|
66
|
+
* point, and it is safe to make because these functions are pure and import
|
|
67
|
+
* nothing.
|
|
68
|
+
*
|
|
69
|
+
* `workflowGraphHash` is here for the same reason: a canvas can tell whether
|
|
70
|
+
* what is on screen still matches the saved version without asking.
|
|
71
|
+
* `WORKFLOW_NODE_ID_PATTERN` and `WORKFLOW_NODE_KINDS` are what a palette and an
|
|
72
|
+
* id field should be built from rather than from a second copy that drifts.
|
|
73
|
+
*/
|
|
74
|
+
var catalog_pipeline_2 = require("./catalog.pipeline");
|
|
75
|
+
Object.defineProperty(exports, "validateWorkflow", { enumerable: true, get: function () { return catalog_pipeline_2.validateWorkflow; } });
|
|
76
|
+
Object.defineProperty(exports, "WORKFLOW_EXECUTION_MODES", { enumerable: true, get: function () { return catalog_pipeline_2.WORKFLOW_EXECUTION_MODES; } });
|
|
77
|
+
Object.defineProperty(exports, "WORKFLOW_ISSUE_CODES", { enumerable: true, get: function () { return catalog_pipeline_2.WORKFLOW_ISSUE_CODES; } });
|
|
78
|
+
Object.defineProperty(exports, "WORKFLOW_NODE_ID_PATTERN", { enumerable: true, get: function () { return catalog_pipeline_2.WORKFLOW_NODE_ID_PATTERN; } });
|
|
79
|
+
Object.defineProperty(exports, "WORKFLOW_NODE_KINDS", { enumerable: true, get: function () { return catalog_pipeline_2.WORKFLOW_NODE_KINDS; } });
|
|
80
|
+
Object.defineProperty(exports, "workflowGraphHash", { enumerable: true, get: function () { return catalog_pipeline_2.workflowGraphHash; } });
|
|
81
|
+
Object.defineProperty(exports, "workflowRunOrder", { enumerable: true, get: function () { return catalog_pipeline_2.workflowRunOrder; } });
|
|
82
|
+
Object.defineProperty(exports, "isWorkflowExecutionMode", { enumerable: true, get: function () { return catalog_pipeline_2.isWorkflowExecutionMode; } });
|
|
83
|
+
Object.defineProperty(exports, "isWorkflowNodeKind", { enumerable: true, get: function () { return catalog_pipeline_2.isWorkflowNodeKind; } });
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { CatalogProperty, type CatalogPropertyOptions, CatalogType, type CatalogTypeOptions, } from './catalog.decorators';
|
|
2
|
+
export { CATALOG_EVENT_PHASE, CATALOG_EVENT_PHASE_FALLBACK, CATALOG_EVENTS, CATALOG_LIB, type CatalogEvent, type CatalogEventPayloads, catalogEventPhase, channelNameFor, emitCatalog, } from './catalog.events';
|
|
3
|
+
export { CatalogModule } from './catalog.module';
|
|
4
|
+
export { assertReadOnlyShape, type CatalogQueryRelation, type CatalogQueryRequest, type CatalogQueryResult, type CatalogQueryStore, isQueryStore, } from './catalog.query';
|
|
5
|
+
export { CATALOG_OPTIONS, type CatalogModuleOptions } from './catalog.options';
|
|
6
|
+
export { type CatalogOverlayStore, FileCatalogOverlayStore, InMemoryCatalogOverlayStore, } from './catalog.overlay-store';
|
|
7
|
+
export { CATALOG_OVERLAY_STORE } from './catalog.overlay-store.token';
|
|
8
|
+
export { MikroOrmCatalogRegistry } from './catalog.registry';
|
|
9
|
+
export { CatalogRegistry } from './catalog.registry.base';
|
|
10
|
+
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, 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, 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 WorkflowTransformNode, type WorkflowValidationIssue, } from './catalog.pipeline';
|
|
11
|
+
export * from './catalog.environment';
|
|
12
|
+
export { QueryCache, toCsv } from './catalog.query-cache';
|
|
13
|
+
export { SubprocessTransformRunner, type TransformRunnerOptions, } from './transform-runner';
|
|
14
|
+
export { CatalogService } from './catalog.service';
|
|
15
|
+
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, isCatalogTraceOutcome, isTraceStore, isWorkspaceStore, type QueryVisualization, type SaveQueryInput, type SavedQuery, type TraceQuery, traceOutcomeFilter, } from './catalog.workspace';
|
|
16
|
+
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, StaticKeyPrincipalResolver, } from './catalog.principal';
|
|
17
|
+
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';
|
|
18
|
+
export { MikroOrmReadStore } from './stores/mikro-orm-read.store';
|
|
19
|
+
export type { CatalogGraph, CatalogObjectPage, CatalogObjectQuery, CatalogObjectTypeDef, CatalogOverlay, CatalogPropertyDef, CatalogRelationDef, CatalogSnapshot, RelationKind, ScalarType, } from './catalog.types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.CATALOG_PRINCIPAL_RESOLVER = exports.traceOutcomeFilter = exports.isWorkspaceStore = exports.isTraceStore = exports.isCatalogTraceOutcome = exports.CATALOG_WORKSPACE_STORE = exports.CATALOG_TRACE_STORE = exports.CATALOG_TRACE_OUTCOMES = exports.CatalogService = exports.SubprocessTransformRunner = exports.toCsv = exports.QueryCache = exports.workflowRunOrder = exports.workflowGraphHash = exports.WORKFLOW_NODE_KINDS = exports.WORKFLOW_NODE_ID_PATTERN = exports.WORKFLOW_ISSUE_CODES = exports.WORKFLOW_EXECUTION_MODES = exports.validateWorkflow = exports.TRANSFORM_LANGUAGES = exports.TRANSFORM_RUNNER = exports.supportsWorkflowStages = exports.supportsWorkflows = exports.isWorkflowNodeKind = exports.isWorkflowNode = exports.isWorkflowExecutionMode = exports.isWorkflowEdge = exports.isTransformLanguage = exports.isPipelineStore = exports.isConnectorKind = exports.CONNECTOR_KINDS = exports.CATALOG_PIPELINE_STORE = exports.CatalogRegistry = exports.MikroOrmCatalogRegistry = exports.CATALOG_OVERLAY_STORE = exports.InMemoryCatalogOverlayStore = exports.FileCatalogOverlayStore = exports.CATALOG_OPTIONS = exports.isQueryStore = exports.assertReadOnlyShape = exports.CatalogModule = exports.emitCatalog = exports.channelNameFor = exports.catalogEventPhase = exports.CATALOG_LIB = exports.CATALOG_EVENTS = exports.CATALOG_EVENT_PHASE_FALLBACK = exports.CATALOG_EVENT_PHASE = exports.CatalogType = exports.CatalogProperty = void 0;
|
|
18
|
+
exports.MikroOrmReadStore = exports.supportsCarryForward = exports.isWriteStore = exports.isReservedColumn = exports.isCatalogStoreCapabilities = exports.findColumnCollisions = exports.CatalogColumnCollisionError = exports.CATALOG_STORE = exports.CATALOG_SNAPSHOT_MODES = exports.CATALOG_RESERVED_COLUMNS = exports.assertNoColumnCollisions = exports.StaticKeyPrincipalResolver = exports.mayWrite = exports.mayRead = exports.maySeeClassification = exports.PRINCIPAL_ACTOR_SEPARATOR = exports.parsePrincipalId = exports.hasScope = exports.expandScopes = exports.delegatePrincipal = exports.composePrincipalId = void 0;
|
|
19
|
+
var catalog_decorators_1 = require("./catalog.decorators");
|
|
20
|
+
Object.defineProperty(exports, "CatalogProperty", { enumerable: true, get: function () { return catalog_decorators_1.CatalogProperty; } });
|
|
21
|
+
Object.defineProperty(exports, "CatalogType", { enumerable: true, get: function () { return catalog_decorators_1.CatalogType; } });
|
|
22
|
+
var catalog_events_1 = require("./catalog.events");
|
|
23
|
+
Object.defineProperty(exports, "CATALOG_EVENT_PHASE", { enumerable: true, get: function () { return catalog_events_1.CATALOG_EVENT_PHASE; } });
|
|
24
|
+
Object.defineProperty(exports, "CATALOG_EVENT_PHASE_FALLBACK", { enumerable: true, get: function () { return catalog_events_1.CATALOG_EVENT_PHASE_FALLBACK; } });
|
|
25
|
+
Object.defineProperty(exports, "CATALOG_EVENTS", { enumerable: true, get: function () { return catalog_events_1.CATALOG_EVENTS; } });
|
|
26
|
+
Object.defineProperty(exports, "CATALOG_LIB", { enumerable: true, get: function () { return catalog_events_1.CATALOG_LIB; } });
|
|
27
|
+
Object.defineProperty(exports, "catalogEventPhase", { enumerable: true, get: function () { return catalog_events_1.catalogEventPhase; } });
|
|
28
|
+
Object.defineProperty(exports, "channelNameFor", { enumerable: true, get: function () { return catalog_events_1.channelNameFor; } });
|
|
29
|
+
Object.defineProperty(exports, "emitCatalog", { enumerable: true, get: function () { return catalog_events_1.emitCatalog; } });
|
|
30
|
+
var catalog_module_1 = require("./catalog.module");
|
|
31
|
+
Object.defineProperty(exports, "CatalogModule", { enumerable: true, get: function () { return catalog_module_1.CatalogModule; } });
|
|
32
|
+
var catalog_query_1 = require("./catalog.query");
|
|
33
|
+
Object.defineProperty(exports, "assertReadOnlyShape", { enumerable: true, get: function () { return catalog_query_1.assertReadOnlyShape; } });
|
|
34
|
+
Object.defineProperty(exports, "isQueryStore", { enumerable: true, get: function () { return catalog_query_1.isQueryStore; } });
|
|
35
|
+
var catalog_options_1 = require("./catalog.options");
|
|
36
|
+
Object.defineProperty(exports, "CATALOG_OPTIONS", { enumerable: true, get: function () { return catalog_options_1.CATALOG_OPTIONS; } });
|
|
37
|
+
var catalog_overlay_store_1 = require("./catalog.overlay-store");
|
|
38
|
+
Object.defineProperty(exports, "FileCatalogOverlayStore", { enumerable: true, get: function () { return catalog_overlay_store_1.FileCatalogOverlayStore; } });
|
|
39
|
+
Object.defineProperty(exports, "InMemoryCatalogOverlayStore", { enumerable: true, get: function () { return catalog_overlay_store_1.InMemoryCatalogOverlayStore; } });
|
|
40
|
+
var catalog_overlay_store_token_1 = require("./catalog.overlay-store.token");
|
|
41
|
+
Object.defineProperty(exports, "CATALOG_OVERLAY_STORE", { enumerable: true, get: function () { return catalog_overlay_store_token_1.CATALOG_OVERLAY_STORE; } });
|
|
42
|
+
var catalog_registry_1 = require("./catalog.registry");
|
|
43
|
+
Object.defineProperty(exports, "MikroOrmCatalogRegistry", { enumerable: true, get: function () { return catalog_registry_1.MikroOrmCatalogRegistry; } });
|
|
44
|
+
var catalog_registry_base_1 = require("./catalog.registry.base");
|
|
45
|
+
Object.defineProperty(exports, "CatalogRegistry", { enumerable: true, get: function () { return catalog_registry_base_1.CatalogRegistry; } });
|
|
46
|
+
var catalog_pipeline_1 = require("./catalog.pipeline");
|
|
47
|
+
Object.defineProperty(exports, "CATALOG_PIPELINE_STORE", { enumerable: true, get: function () { return catalog_pipeline_1.CATALOG_PIPELINE_STORE; } });
|
|
48
|
+
Object.defineProperty(exports, "CONNECTOR_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.CONNECTOR_KINDS; } });
|
|
49
|
+
Object.defineProperty(exports, "isConnectorKind", { enumerable: true, get: function () { return catalog_pipeline_1.isConnectorKind; } });
|
|
50
|
+
Object.defineProperty(exports, "isPipelineStore", { enumerable: true, get: function () { return catalog_pipeline_1.isPipelineStore; } });
|
|
51
|
+
Object.defineProperty(exports, "isTransformLanguage", { enumerable: true, get: function () { return catalog_pipeline_1.isTransformLanguage; } });
|
|
52
|
+
Object.defineProperty(exports, "isWorkflowEdge", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowEdge; } });
|
|
53
|
+
Object.defineProperty(exports, "isWorkflowExecutionMode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowExecutionMode; } });
|
|
54
|
+
Object.defineProperty(exports, "isWorkflowNode", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowNode; } });
|
|
55
|
+
Object.defineProperty(exports, "isWorkflowNodeKind", { enumerable: true, get: function () { return catalog_pipeline_1.isWorkflowNodeKind; } });
|
|
56
|
+
Object.defineProperty(exports, "supportsWorkflows", { enumerable: true, get: function () { return catalog_pipeline_1.supportsWorkflows; } });
|
|
57
|
+
Object.defineProperty(exports, "supportsWorkflowStages", { enumerable: true, get: function () { return catalog_pipeline_1.supportsWorkflowStages; } });
|
|
58
|
+
Object.defineProperty(exports, "TRANSFORM_RUNNER", { enumerable: true, get: function () { return catalog_pipeline_1.TRANSFORM_RUNNER; } });
|
|
59
|
+
Object.defineProperty(exports, "TRANSFORM_LANGUAGES", { enumerable: true, get: function () { return catalog_pipeline_1.TRANSFORM_LANGUAGES; } });
|
|
60
|
+
Object.defineProperty(exports, "validateWorkflow", { enumerable: true, get: function () { return catalog_pipeline_1.validateWorkflow; } });
|
|
61
|
+
Object.defineProperty(exports, "WORKFLOW_EXECUTION_MODES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_EXECUTION_MODES; } });
|
|
62
|
+
Object.defineProperty(exports, "WORKFLOW_ISSUE_CODES", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_ISSUE_CODES; } });
|
|
63
|
+
Object.defineProperty(exports, "WORKFLOW_NODE_ID_PATTERN", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_NODE_ID_PATTERN; } });
|
|
64
|
+
Object.defineProperty(exports, "WORKFLOW_NODE_KINDS", { enumerable: true, get: function () { return catalog_pipeline_1.WORKFLOW_NODE_KINDS; } });
|
|
65
|
+
Object.defineProperty(exports, "workflowGraphHash", { enumerable: true, get: function () { return catalog_pipeline_1.workflowGraphHash; } });
|
|
66
|
+
Object.defineProperty(exports, "workflowRunOrder", { enumerable: true, get: function () { return catalog_pipeline_1.workflowRunOrder; } });
|
|
67
|
+
// The environment surface: which catalog database a call is served from, and
|
|
68
|
+
// how a connector or a transform is promoted between them.
|
|
69
|
+
__exportStar(require("./catalog.environment"), exports);
|
|
70
|
+
var catalog_query_cache_1 = require("./catalog.query-cache");
|
|
71
|
+
Object.defineProperty(exports, "QueryCache", { enumerable: true, get: function () { return catalog_query_cache_1.QueryCache; } });
|
|
72
|
+
Object.defineProperty(exports, "toCsv", { enumerable: true, get: function () { return catalog_query_cache_1.toCsv; } });
|
|
73
|
+
var transform_runner_1 = require("./transform-runner");
|
|
74
|
+
Object.defineProperty(exports, "SubprocessTransformRunner", { enumerable: true, get: function () { return transform_runner_1.SubprocessTransformRunner; } });
|
|
75
|
+
var catalog_service_1 = require("./catalog.service");
|
|
76
|
+
Object.defineProperty(exports, "CatalogService", { enumerable: true, get: function () { return catalog_service_1.CatalogService; } });
|
|
77
|
+
var catalog_workspace_1 = require("./catalog.workspace");
|
|
78
|
+
Object.defineProperty(exports, "CATALOG_TRACE_OUTCOMES", { enumerable: true, get: function () { return catalog_workspace_1.CATALOG_TRACE_OUTCOMES; } });
|
|
79
|
+
Object.defineProperty(exports, "CATALOG_TRACE_STORE", { enumerable: true, get: function () { return catalog_workspace_1.CATALOG_TRACE_STORE; } });
|
|
80
|
+
Object.defineProperty(exports, "CATALOG_WORKSPACE_STORE", { enumerable: true, get: function () { return catalog_workspace_1.CATALOG_WORKSPACE_STORE; } });
|
|
81
|
+
Object.defineProperty(exports, "isCatalogTraceOutcome", { enumerable: true, get: function () { return catalog_workspace_1.isCatalogTraceOutcome; } });
|
|
82
|
+
Object.defineProperty(exports, "isTraceStore", { enumerable: true, get: function () { return catalog_workspace_1.isTraceStore; } });
|
|
83
|
+
Object.defineProperty(exports, "isWorkspaceStore", { enumerable: true, get: function () { return catalog_workspace_1.isWorkspaceStore; } });
|
|
84
|
+
Object.defineProperty(exports, "traceOutcomeFilter", { enumerable: true, get: function () { return catalog_workspace_1.traceOutcomeFilter; } });
|
|
85
|
+
var catalog_principal_1 = require("./catalog.principal");
|
|
86
|
+
Object.defineProperty(exports, "CATALOG_PRINCIPAL_RESOLVER", { enumerable: true, get: function () { return catalog_principal_1.CATALOG_PRINCIPAL_RESOLVER; } });
|
|
87
|
+
Object.defineProperty(exports, "composePrincipalId", { enumerable: true, get: function () { return catalog_principal_1.composePrincipalId; } });
|
|
88
|
+
Object.defineProperty(exports, "delegatePrincipal", { enumerable: true, get: function () { return catalog_principal_1.delegatePrincipal; } });
|
|
89
|
+
Object.defineProperty(exports, "expandScopes", { enumerable: true, get: function () { return catalog_principal_1.expandScopes; } });
|
|
90
|
+
Object.defineProperty(exports, "hasScope", { enumerable: true, get: function () { return catalog_principal_1.hasScope; } });
|
|
91
|
+
Object.defineProperty(exports, "parsePrincipalId", { enumerable: true, get: function () { return catalog_principal_1.parsePrincipalId; } });
|
|
92
|
+
Object.defineProperty(exports, "PRINCIPAL_ACTOR_SEPARATOR", { enumerable: true, get: function () { return catalog_principal_1.PRINCIPAL_ACTOR_SEPARATOR; } });
|
|
93
|
+
Object.defineProperty(exports, "maySeeClassification", { enumerable: true, get: function () { return catalog_principal_1.maySeeClassification; } });
|
|
94
|
+
Object.defineProperty(exports, "mayRead", { enumerable: true, get: function () { return catalog_principal_1.mayRead; } });
|
|
95
|
+
Object.defineProperty(exports, "mayWrite", { enumerable: true, get: function () { return catalog_principal_1.mayWrite; } });
|
|
96
|
+
Object.defineProperty(exports, "StaticKeyPrincipalResolver", { enumerable: true, get: function () { return catalog_principal_1.StaticKeyPrincipalResolver; } });
|
|
97
|
+
var catalog_store_1 = require("./catalog.store");
|
|
98
|
+
Object.defineProperty(exports, "assertNoColumnCollisions", { enumerable: true, get: function () { return catalog_store_1.assertNoColumnCollisions; } });
|
|
99
|
+
Object.defineProperty(exports, "CATALOG_RESERVED_COLUMNS", { enumerable: true, get: function () { return catalog_store_1.CATALOG_RESERVED_COLUMNS; } });
|
|
100
|
+
Object.defineProperty(exports, "CATALOG_SNAPSHOT_MODES", { enumerable: true, get: function () { return catalog_store_1.CATALOG_SNAPSHOT_MODES; } });
|
|
101
|
+
Object.defineProperty(exports, "CATALOG_STORE", { enumerable: true, get: function () { return catalog_store_1.CATALOG_STORE; } });
|
|
102
|
+
Object.defineProperty(exports, "CatalogColumnCollisionError", { enumerable: true, get: function () { return catalog_store_1.CatalogColumnCollisionError; } });
|
|
103
|
+
Object.defineProperty(exports, "findColumnCollisions", { enumerable: true, get: function () { return catalog_store_1.findColumnCollisions; } });
|
|
104
|
+
Object.defineProperty(exports, "isCatalogStoreCapabilities", { enumerable: true, get: function () { return catalog_store_1.isCatalogStoreCapabilities; } });
|
|
105
|
+
Object.defineProperty(exports, "isReservedColumn", { enumerable: true, get: function () { return catalog_store_1.isReservedColumn; } });
|
|
106
|
+
Object.defineProperty(exports, "isWriteStore", { enumerable: true, get: function () { return catalog_store_1.isWriteStore; } });
|
|
107
|
+
Object.defineProperty(exports, "supportsCarryForward", { enumerable: true, get: function () { return catalog_store_1.supportsCarryForward; } });
|
|
108
|
+
var mikro_orm_read_store_1 = require("./stores/mikro-orm-read.store");
|
|
109
|
+
Object.defineProperty(exports, "MikroOrmReadStore", { enumerable: true, get: function () { return mikro_orm_read_store_1.MikroOrmReadStore; } });
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EntityManager } from '@mikro-orm/core';
|
|
2
|
+
import { MikroOrmCatalogRegistry } from '../catalog.registry';
|
|
3
|
+
import type { CatalogReadQuery, CatalogReadResult, CatalogReadStore, CatalogStoreCapabilities } from '../catalog.store';
|
|
4
|
+
import type { CatalogObjectTypeDef } from '../catalog.types';
|
|
5
|
+
/**
|
|
6
|
+
* Reads objects straight out of the application's own tables, through the ORM
|
|
7
|
+
* that already maps them.
|
|
8
|
+
*
|
|
9
|
+
* The default store, and the one that needs no infrastructure: there is no copy
|
|
10
|
+
* to keep in sync and no load to schedule, so the catalog is never stale. The
|
|
11
|
+
* trade is that there is also no history — the tables hold current state, and
|
|
12
|
+
* nothing here can show you last Tuesday.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MikroOrmReadStore implements CatalogReadStore {
|
|
15
|
+
private readonly registry;
|
|
16
|
+
private readonly em;
|
|
17
|
+
readonly capabilities: CatalogStoreCapabilities;
|
|
18
|
+
constructor(registry: MikroOrmCatalogRegistry, em: EntityManager);
|
|
19
|
+
read(type: CatalogObjectTypeDef, fields: string[], query: CatalogReadQuery): Promise<CatalogReadResult>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MikroOrmReadStore = void 0;
|
|
13
|
+
const core_1 = require("@mikro-orm/core");
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const catalog_registry_1 = require("../catalog.registry");
|
|
16
|
+
/**
|
|
17
|
+
* Reads objects straight out of the application's own tables, through the ORM
|
|
18
|
+
* that already maps them.
|
|
19
|
+
*
|
|
20
|
+
* The default store, and the one that needs no infrastructure: there is no copy
|
|
21
|
+
* to keep in sync and no load to schedule, so the catalog is never stale. The
|
|
22
|
+
* trade is that there is also no history — the tables hold current state, and
|
|
23
|
+
* nothing here can show you last Tuesday.
|
|
24
|
+
*/
|
|
25
|
+
let MikroOrmReadStore = class MikroOrmReadStore {
|
|
26
|
+
registry;
|
|
27
|
+
em;
|
|
28
|
+
capabilities = {
|
|
29
|
+
snapshots: 'none',
|
|
30
|
+
writable: false,
|
|
31
|
+
timeTravel: false,
|
|
32
|
+
};
|
|
33
|
+
constructor(registry, em) {
|
|
34
|
+
this.registry = registry;
|
|
35
|
+
this.em = em;
|
|
36
|
+
}
|
|
37
|
+
async read(type, fields, query) {
|
|
38
|
+
const em = this.em.fork();
|
|
39
|
+
// The constructor, not the name: `EntityName` dropped `string` in MikroORM
|
|
40
|
+
// 7. The registry only holds classes for types that survived the include /
|
|
41
|
+
// exclude filter, so an excluded entity cannot be reached by guessing.
|
|
42
|
+
const entityClass = this.registry.getEntityClass(type.name);
|
|
43
|
+
if (!entityClass) {
|
|
44
|
+
throw new common_1.NotFoundException(`Unknown object type: ${type.name}`);
|
|
45
|
+
}
|
|
46
|
+
const size = query.size ?? 25;
|
|
47
|
+
const page = query.page ?? 1;
|
|
48
|
+
// No explicit type arguments: `findAndCount` declares `Fields extends string
|
|
49
|
+
// = never`, so naming even one generic makes the rest fall back to their
|
|
50
|
+
// defaults and types `fields` as `never[]`. Inference gets it right.
|
|
51
|
+
const [rows, total] = await em.findAndCount(entityClass, buildWhere(type, query.search), {
|
|
52
|
+
limit: size,
|
|
53
|
+
offset: (page - 1) * size,
|
|
54
|
+
orderBy: buildOrderBy(type, query.sort, query.dir),
|
|
55
|
+
fields,
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
total,
|
|
59
|
+
rows: rows.map((row) => serialize(row, fields)),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.MikroOrmReadStore = MikroOrmReadStore;
|
|
64
|
+
exports.MikroOrmReadStore = MikroOrmReadStore = __decorate([
|
|
65
|
+
(0, common_1.Injectable)(),
|
|
66
|
+
__metadata("design:paramtypes", [catalog_registry_1.MikroOrmCatalogRegistry,
|
|
67
|
+
core_1.EntityManager])
|
|
68
|
+
], MikroOrmReadStore);
|
|
69
|
+
/**
|
|
70
|
+
* Only string columns the catalog says are visible.
|
|
71
|
+
*
|
|
72
|
+
* A search that reached a classified column would leak it through row
|
|
73
|
+
* membership even though the value is never rendered.
|
|
74
|
+
*/
|
|
75
|
+
function buildWhere(type, search) {
|
|
76
|
+
const term = search?.trim();
|
|
77
|
+
if (!term)
|
|
78
|
+
return {};
|
|
79
|
+
const searchable = type.properties.filter((p) => !p.hidden && p.type === 'string' && !p.classification);
|
|
80
|
+
if (searchable.length === 0)
|
|
81
|
+
return {};
|
|
82
|
+
return { $or: searchable.map((p) => ({ [p.name]: { $like: `%${term}%` } })) };
|
|
83
|
+
}
|
|
84
|
+
/** Only ever a column the catalog vouched for; falls back to the key. */
|
|
85
|
+
function buildOrderBy(type, sort, dir) {
|
|
86
|
+
const direction = dir === 'desc' ? 'desc' : 'asc';
|
|
87
|
+
const known = sort ? type.properties.find((p) => p.name === sort && !p.hidden) : undefined;
|
|
88
|
+
if (known)
|
|
89
|
+
return { [known.name]: direction };
|
|
90
|
+
const [pk] = type.primaryKey;
|
|
91
|
+
return pk ? { [pk]: direction } : {};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Make one column value safe for `JSON.stringify`.
|
|
95
|
+
*
|
|
96
|
+
* BigInt is the case that matters: `JSON.stringify` throws outright on it, so a
|
|
97
|
+
* single `bigint` column anywhere in a table turns the whole generic read into
|
|
98
|
+
* a 500. It becomes a string rather than a number on purpose — a value is only
|
|
99
|
+
* stored as BigInt when it might exceed `Number.MAX_SAFE_INTEGER`, and silently
|
|
100
|
+
* rounding it would be worse than the type change.
|
|
101
|
+
*/
|
|
102
|
+
function toJsonValue(value) {
|
|
103
|
+
if (typeof value === 'bigint')
|
|
104
|
+
return value.toString();
|
|
105
|
+
if (value instanceof Date)
|
|
106
|
+
return value.toISOString();
|
|
107
|
+
if (Buffer.isBuffer(value))
|
|
108
|
+
return value.toString('base64');
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
/** Whitelist by field, so a column the catalog hides can never be returned. */
|
|
112
|
+
function serialize(row, fields) {
|
|
113
|
+
const out = {};
|
|
114
|
+
if (!row || typeof row !== 'object')
|
|
115
|
+
return out;
|
|
116
|
+
for (const field of fields) {
|
|
117
|
+
out[field] = toJsonValue(Reflect.get(row, field));
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { CatalogTransform, TransformLanguage, TransformResult, TransformRunner } from './catalog.pipeline';
|
|
2
|
+
export interface TransformRunnerOptions {
|
|
3
|
+
/**
|
|
4
|
+
* A Python virtualenv whose interpreter runs transforms.
|
|
5
|
+
*
|
|
6
|
+
* The supported way to give transforms libraries. PEP 668 stops a service
|
|
7
|
+
* installing into the system Python, and it is right to: a transform that
|
|
8
|
+
* can `pip install` is a transform that can change what every other
|
|
9
|
+
* transform sees. An image provisions a venv, points this at it, and the set
|
|
10
|
+
* of available libraries becomes a deployment decision with a Dockerfile line
|
|
11
|
+
* behind it rather than something code negotiates at runtime.
|
|
12
|
+
*/
|
|
13
|
+
pythonVenv?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Runs a transform in a child process, with a clock on it.
|
|
17
|
+
*
|
|
18
|
+
* **This is not a security boundary.** It stops accidents — an infinite loop, a
|
|
19
|
+
* runaway allocation, a stray read of `process.env.DATABASE_PASSWORD` — because
|
|
20
|
+
* the child gets a timeout and an empty environment. It does not stop code
|
|
21
|
+
* written to escape it: a child process can still open sockets and read the
|
|
22
|
+
* filesystem as whatever user the service runs as.
|
|
23
|
+
*
|
|
24
|
+
* That is a deliberate trade for the case this is built for, where transforms
|
|
25
|
+
* are written by the same people who already have database access. A catalog
|
|
26
|
+
* that accepts transforms from anyone else needs a container, gVisor, or a WASM
|
|
27
|
+
* runtime — and `TransformRunner` is an interface precisely so that swap is a
|
|
28
|
+
* provider change rather than a rewrite.
|
|
29
|
+
*
|
|
30
|
+
* `node:vm` was the other option and is worse on both counts: it is famously
|
|
31
|
+
* not an isolation boundary either, and it cannot be killed mid-loop.
|
|
32
|
+
*/
|
|
33
|
+
export declare class SubprocessTransformRunner implements TransformRunner {
|
|
34
|
+
private readonly options;
|
|
35
|
+
private readonly logger;
|
|
36
|
+
private pythonPath;
|
|
37
|
+
private packages;
|
|
38
|
+
constructor(options?: TransformRunnerOptions);
|
|
39
|
+
available(): Promise<TransformLanguage[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Which Python libraries a transform can import here.
|
|
42
|
+
*
|
|
43
|
+
* Reported rather than assumed. "pandas is available" is a property of the
|
|
44
|
+
* image, and a UI that promises it on an image without it turns a deployment
|
|
45
|
+
* difference into a runtime traceback the author cannot act on.
|
|
46
|
+
*/
|
|
47
|
+
pythonPackages(): Promise<string[]>;
|
|
48
|
+
run(transform: Pick<CatalogTransform, 'language' | 'code'>, records: unknown[], options?: {
|
|
49
|
+
timeoutMs?: number;
|
|
50
|
+
}): Promise<TransformResult>;
|
|
51
|
+
private spawn;
|
|
52
|
+
/** Cached, including the negative answer — probing on every run is wasteful. */
|
|
53
|
+
private resolvePython;
|
|
54
|
+
}
|