ai-database 2.1.3 → 2.3.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/CHANGELOG.md +35 -1
- package/README.md +880 -669
- package/dist/actions.d.ts +2 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -1
- package/dist/actions.js.map +1 -1
- package/dist/ai-promise-db.d.ts +49 -23
- package/dist/ai-promise-db.d.ts.map +1 -1
- package/dist/ai-promise-db.js +91 -63
- package/dist/ai-promise-db.js.map +1 -1
- package/dist/authorization.d.ts.map +1 -1
- package/dist/authorization.js +38 -30
- package/dist/authorization.js.map +1 -1
- package/dist/cascade-orchestrator.d.ts +404 -0
- package/dist/cascade-orchestrator.d.ts.map +1 -0
- package/dist/cascade-orchestrator.js +828 -0
- package/dist/cascade-orchestrator.js.map +1 -0
- package/dist/cascade-write-strategy.d.ts +584 -0
- package/dist/cascade-write-strategy.d.ts.map +1 -0
- package/dist/cascade-write-strategy.js +590 -0
- package/dist/cascade-write-strategy.js.map +1 -0
- package/dist/ch-adapter.d.ts +358 -0
- package/dist/ch-adapter.d.ts.map +1 -0
- package/dist/ch-adapter.js +929 -0
- package/dist/ch-adapter.js.map +1 -0
- package/dist/client/index.d.ts +42 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +43 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client.d.ts +266 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +81 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +64 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +52 -2
- package/dist/constants.js.map +1 -1
- package/dist/dataloader.d.ts +99 -0
- package/dist/dataloader.d.ts.map +1 -0
- package/dist/dataloader.js +225 -0
- package/dist/dataloader.js.map +1 -0
- package/dist/db-provider-port.d.ts +501 -0
- package/dist/db-provider-port.d.ts.map +1 -0
- package/dist/db-provider-port.js +113 -0
- package/dist/db-provider-port.js.map +1 -0
- package/dist/digital-objects-provider.d.ts +49 -0
- package/dist/digital-objects-provider.d.ts.map +1 -0
- package/dist/digital-objects-provider.js +55 -0
- package/dist/digital-objects-provider.js.map +1 -0
- package/dist/do-sqlite-adapter.d.ts +402 -0
- package/dist/do-sqlite-adapter.d.ts.map +1 -0
- package/dist/do-sqlite-adapter.js +745 -0
- package/dist/do-sqlite-adapter.js.map +1 -0
- package/dist/docs-rels/custom-types.d.ts +134 -0
- package/dist/docs-rels/custom-types.d.ts.map +1 -0
- package/dist/docs-rels/custom-types.js +70 -0
- package/dist/docs-rels/custom-types.js.map +1 -0
- package/dist/docs-rels/index.d.ts +16 -0
- package/dist/docs-rels/index.d.ts.map +1 -0
- package/dist/docs-rels/index.js +16 -0
- package/dist/docs-rels/index.js.map +1 -0
- package/dist/docs-rels/migrations/index.d.ts +30 -0
- package/dist/docs-rels/migrations/index.d.ts.map +1 -0
- package/dist/docs-rels/migrations/index.js +128 -0
- package/dist/docs-rels/migrations/index.js.map +1 -0
- package/dist/docs-rels/schema.d.ts +2961 -0
- package/dist/docs-rels/schema.d.ts.map +1 -0
- package/dist/docs-rels/schema.js +244 -0
- package/dist/docs-rels/schema.js.map +1 -0
- package/dist/durable-clickhouse.d.ts.map +1 -1
- package/dist/durable-clickhouse.js +16 -13
- package/dist/durable-clickhouse.js.map +1 -1
- package/dist/durable-promise.d.ts.map +1 -1
- package/dist/durable-promise.js +34 -15
- package/dist/durable-promise.js.map +1 -1
- package/dist/errors.d.ts +127 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +210 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventbridge.d.ts +117 -0
- package/dist/eventbridge.d.ts.map +1 -0
- package/dist/eventbridge.js +238 -0
- package/dist/eventbridge.js.map +1 -0
- package/dist/events.d.ts +2 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +1 -1
- package/dist/events.js.map +1 -1
- package/dist/execution-queue.d.ts.map +1 -1
- package/dist/execution-queue.js +4 -5
- package/dist/execution-queue.js.map +1 -1
- package/dist/index.d.ts +35 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +106 -6
- package/dist/index.js.map +1 -1
- package/dist/linguistic.d.ts +3 -108
- package/dist/linguistic.d.ts.map +1 -1
- package/dist/linguistic.js +3 -372
- package/dist/linguistic.js.map +1 -1
- package/dist/logger.d.ts +132 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +137 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory-provider.d.ts +128 -0
- package/dist/memory-provider.d.ts.map +1 -1
- package/dist/memory-provider.js +592 -257
- package/dist/memory-provider.js.map +1 -1
- package/dist/pg-adapter.d.ts +424 -0
- package/dist/pg-adapter.d.ts.map +1 -0
- package/dist/pg-adapter.js +921 -0
- package/dist/pg-adapter.js.map +1 -0
- package/dist/pipelines-iceberg-emitter.d.ts +327 -0
- package/dist/pipelines-iceberg-emitter.d.ts.map +1 -0
- package/dist/pipelines-iceberg-emitter.js +351 -0
- package/dist/pipelines-iceberg-emitter.js.map +1 -0
- package/dist/provider-capabilities.d.ts +146 -0
- package/dist/provider-capabilities.d.ts.map +1 -0
- package/dist/provider-capabilities.js +214 -0
- package/dist/provider-capabilities.js.map +1 -0
- package/dist/rdb-provider-adapter.d.ts +195 -0
- package/dist/rdb-provider-adapter.d.ts.map +1 -0
- package/dist/rdb-provider-adapter.js +291 -0
- package/dist/rdb-provider-adapter.js.map +1 -0
- package/dist/schema/cascade.d.ts +48 -17
- package/dist/schema/cascade.d.ts.map +1 -1
- package/dist/schema/cascade.js +477 -278
- package/dist/schema/cascade.js.map +1 -1
- package/dist/schema/definition-caches.d.ts +24 -0
- package/dist/schema/definition-caches.d.ts.map +1 -0
- package/dist/schema/definition-caches.js +26 -0
- package/dist/schema/definition-caches.js.map +1 -0
- package/dist/schema/dependency-graph.d.ts +21 -109
- package/dist/schema/dependency-graph.d.ts.map +1 -1
- package/dist/schema/dependency-graph.js +25 -333
- package/dist/schema/dependency-graph.js.map +1 -1
- package/dist/schema/diff.d.ts +103 -0
- package/dist/schema/diff.d.ts.map +1 -0
- package/dist/schema/diff.js +329 -0
- package/dist/schema/diff.js.map +1 -0
- package/dist/schema/entity-operations.d.ts +99 -0
- package/dist/schema/entity-operations.d.ts.map +1 -0
- package/dist/schema/entity-operations.js +818 -0
- package/dist/schema/entity-operations.js.map +1 -0
- package/dist/schema/index.d.ts +28 -34
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +454 -521
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/migration.d.ts +205 -0
- package/dist/schema/migration.d.ts.map +1 -0
- package/dist/schema/migration.js +327 -0
- package/dist/schema/migration.js.map +1 -0
- package/dist/schema/nl-query-generator.d.ts +68 -0
- package/dist/schema/nl-query-generator.d.ts.map +1 -0
- package/dist/schema/nl-query-generator.js +362 -0
- package/dist/schema/nl-query-generator.js.map +1 -0
- package/dist/schema/nl-query.d.ts +65 -0
- package/dist/schema/nl-query.d.ts.map +1 -0
- package/dist/schema/nl-query.js +178 -0
- package/dist/schema/nl-query.js.map +1 -0
- package/dist/schema/parse.d.ts.map +1 -1
- package/dist/schema/parse.js +144 -89
- package/dist/schema/parse.js.map +1 -1
- package/dist/schema/provider.d.ts +37 -0
- package/dist/schema/provider.d.ts.map +1 -1
- package/dist/schema/provider.js +15 -7
- package/dist/schema/provider.js.map +1 -1
- package/dist/schema/resolve.d.ts +46 -5
- package/dist/schema/resolve.d.ts.map +1 -1
- package/dist/schema/resolve.js +237 -95
- package/dist/schema/resolve.js.map +1 -1
- package/dist/schema/search-utils.d.ts +76 -0
- package/dist/schema/search-utils.d.ts.map +1 -0
- package/dist/schema/search-utils.js +86 -0
- package/dist/schema/search-utils.js.map +1 -0
- package/dist/schema/seed.d.ts +53 -0
- package/dist/schema/seed.d.ts.map +1 -0
- package/dist/schema/seed.js +94 -0
- package/dist/schema/seed.js.map +1 -0
- package/dist/schema/semantic.d.ts +10 -0
- package/dist/schema/semantic.d.ts.map +1 -1
- package/dist/schema/semantic.js +192 -86
- package/dist/schema/semantic.js.map +1 -1
- package/dist/schema/sub-apis.d.ts +52 -0
- package/dist/schema/sub-apis.d.ts.map +1 -0
- package/dist/schema/sub-apis.js +216 -0
- package/dist/schema/sub-apis.js.map +1 -0
- package/dist/schema/system-entities.d.ts +42 -0
- package/dist/schema/system-entities.d.ts.map +1 -0
- package/dist/schema/system-entities.js +101 -0
- package/dist/schema/system-entities.js.map +1 -0
- package/dist/schema/types.d.ts +91 -9
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/union-fallback.d.ts.map +1 -1
- package/dist/schema/union-fallback.js +21 -15
- package/dist/schema/union-fallback.js.map +1 -1
- package/dist/schema/value-generators/ai.d.ts +54 -0
- package/dist/schema/value-generators/ai.d.ts.map +1 -0
- package/dist/schema/value-generators/ai.js +136 -0
- package/dist/schema/value-generators/ai.js.map +1 -0
- package/dist/schema/value-generators/index.d.ts +126 -0
- package/dist/schema/value-generators/index.d.ts.map +1 -0
- package/dist/schema/value-generators/index.js +219 -0
- package/dist/schema/value-generators/index.js.map +1 -0
- package/dist/schema/value-generators/placeholder.d.ts +52 -0
- package/dist/schema/value-generators/placeholder.d.ts.map +1 -0
- package/dist/schema/value-generators/placeholder.js +328 -0
- package/dist/schema/value-generators/placeholder.js.map +1 -0
- package/dist/schema/value-generators/types.d.ts +116 -0
- package/dist/schema/value-generators/types.d.ts.map +1 -0
- package/dist/schema/value-generators/types.js +11 -0
- package/dist/schema/value-generators/types.js.map +1 -0
- package/dist/schema/version.d.ts +111 -0
- package/dist/schema/version.d.ts.map +1 -0
- package/dist/schema/version.js +190 -0
- package/dist/schema/version.js.map +1 -0
- package/dist/schema.d.ts +1095 -24
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2852 -40
- package/dist/schema.js.map +1 -1
- package/dist/semantic-vectors.d.ts +39 -0
- package/dist/semantic-vectors.d.ts.map +1 -0
- package/dist/semantic-vectors.js +334 -0
- package/dist/semantic-vectors.js.map +1 -0
- package/dist/semantic.d.ts +29 -1
- package/dist/semantic.d.ts.map +1 -1
- package/dist/semantic.js +26 -16
- package/dist/semantic.js.map +1 -1
- package/dist/telemetry.d.ts +128 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +305 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tests.d.ts.map +1 -1
- package/dist/tests.js +30 -22
- package/dist/tests.js.map +1 -1
- package/dist/type-guards.d.ts +50 -5
- package/dist/type-guards.d.ts.map +1 -1
- package/dist/type-guards.js +87 -16
- package/dist/type-guards.js.map +1 -1
- package/dist/types.d.ts +33 -245
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +62 -72
- package/dist/types.js.map +1 -1
- package/dist/validation.d.ts +2 -5
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +65 -93
- package/dist/validation.js.map +1 -1
- package/dist/worker/db-provider.d.ts +168 -0
- package/dist/worker/db-provider.d.ts.map +1 -0
- package/dist/worker/db-provider.js +277 -0
- package/dist/worker/db-provider.js.map +1 -0
- package/dist/worker/index.d.ts +35 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +37 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker.d.ts +779 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +2786 -0
- package/dist/worker.js.map +1 -0
- package/package.json +46 -16
- package/src/docs-rels/migrations/0001-init.sql +125 -0
- package/LICENSE +0 -21
|
@@ -1,355 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dependency Graph - builds and manages type dependencies for cascade generation
|
|
3
3
|
*
|
|
4
|
-
* This module
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* This module re-exports the dependency graph functionality from @graphdl/core
|
|
5
|
+
* with type aliases for backward compatibility. The ai-database package uses
|
|
6
|
+
* slightly different type names (SchemaDepNode, SchemaDepEdge, SchemaDepGraph)
|
|
7
|
+
* compared to graphdl (DependencyNode, DependencyEdge, DependencyGraph).
|
|
8
|
+
*
|
|
9
|
+
* Additionally, ai-database's buildDependencyGraph takes a ParsedSchema while
|
|
10
|
+
* graphdl's takes a ParsedGraph. This module provides an adapter function to
|
|
11
|
+
* bridge this difference.
|
|
9
12
|
*
|
|
10
13
|
* @packageDocumentation
|
|
11
14
|
*/
|
|
15
|
+
import { buildDependencyGraph as buildDependencyGraphCore, topologicalSort, detectCycles, getParallelGroups, getAllDependencies, hasCycles, visualizeGraph, CircularDependencyError, PRIMITIVE_TYPES, } from '@graphdl/core';
|
|
12
16
|
// =============================================================================
|
|
13
|
-
//
|
|
17
|
+
// Re-exports from @graphdl/core
|
|
14
18
|
// =============================================================================
|
|
15
|
-
|
|
16
|
-
* Primitive types that don't create dependencies
|
|
17
|
-
*/
|
|
18
|
-
export const PRIMITIVE_TYPES = new Set([
|
|
19
|
-
'string',
|
|
20
|
-
'number',
|
|
21
|
-
'boolean',
|
|
22
|
-
'date',
|
|
23
|
-
'datetime',
|
|
24
|
-
'json',
|
|
25
|
-
'markdown',
|
|
26
|
-
'url',
|
|
27
|
-
'email',
|
|
28
|
-
'object',
|
|
29
|
-
'array',
|
|
30
|
-
]);
|
|
19
|
+
export { topologicalSort, detectCycles, getParallelGroups, getAllDependencies, hasCycles, visualizeGraph, CircularDependencyError, PRIMITIVE_TYPES, };
|
|
31
20
|
// =============================================================================
|
|
32
|
-
//
|
|
21
|
+
// Adapter Function
|
|
33
22
|
// =============================================================================
|
|
34
23
|
/**
|
|
35
|
-
*
|
|
24
|
+
* Convert ParsedSchema to ParsedGraph for use with @graphdl/core functions
|
|
25
|
+
*
|
|
26
|
+
* The main difference is that ParsedGraph has an additional `typeUris` field.
|
|
27
|
+
* For ai-database's ParsedSchema, we just add an empty typeUris map.
|
|
36
28
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
super(`Circular dependency detected: ${cycleStr}`);
|
|
43
|
-
this.name = 'CircularDependencyError';
|
|
44
|
-
this.cyclePath = cyclePath;
|
|
45
|
-
}
|
|
29
|
+
function toGraphdlParsedGraph(schema) {
|
|
30
|
+
return {
|
|
31
|
+
entities: schema.entities,
|
|
32
|
+
typeUris: new Map(),
|
|
33
|
+
};
|
|
46
34
|
}
|
|
47
|
-
// =============================================================================
|
|
48
|
-
// Graph Construction
|
|
49
|
-
// =============================================================================
|
|
50
35
|
/**
|
|
51
36
|
* Build a dependency graph from a parsed schema
|
|
52
37
|
*
|
|
38
|
+
* This is a wrapper around @graphdl/core's buildDependencyGraph that
|
|
39
|
+
* accepts ai-database's ParsedSchema type.
|
|
40
|
+
*
|
|
53
41
|
* @param schema - The parsed schema from parseSchema()
|
|
54
42
|
* @returns The dependency graph with nodes and edges
|
|
55
43
|
*/
|
|
56
44
|
export function buildDependencyGraph(schema) {
|
|
57
|
-
|
|
58
|
-
const edges = [];
|
|
59
|
-
// Initialize nodes for all entity types
|
|
60
|
-
for (const [typeName] of schema.entities) {
|
|
61
|
-
nodes[typeName] = {
|
|
62
|
-
name: typeName,
|
|
63
|
-
dependsOn: [],
|
|
64
|
-
dependedOnBy: [],
|
|
65
|
-
softDependsOn: [],
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
// Process fields to build edges
|
|
69
|
-
for (const [typeName, entity] of schema.entities) {
|
|
70
|
-
for (const [fieldName, field] of entity.fields) {
|
|
71
|
-
// Skip non-relation fields
|
|
72
|
-
if (!field.isRelation || !field.relatedType)
|
|
73
|
-
continue;
|
|
74
|
-
// Skip primitive types
|
|
75
|
-
if (PRIMITIVE_TYPES.has(field.relatedType))
|
|
76
|
-
continue;
|
|
77
|
-
const target = field.relatedType;
|
|
78
|
-
const operator = field.operator;
|
|
79
|
-
const isArray = field.isArray ?? false;
|
|
80
|
-
const isSoft = operator === '~>' || operator === '<~';
|
|
81
|
-
const isBackward = operator === '<-' || operator === '<~';
|
|
82
|
-
const isOptionalField = field.isOptional;
|
|
83
|
-
// Add edge (mark optional in fieldName for cycle detection)
|
|
84
|
-
edges.push({
|
|
85
|
-
from: typeName,
|
|
86
|
-
to: target,
|
|
87
|
-
isArray,
|
|
88
|
-
operator: operator ?? '->',
|
|
89
|
-
fieldName: isOptionalField ? `${fieldName}?` : fieldName,
|
|
90
|
-
});
|
|
91
|
-
// Ensure target node exists (might be external/not in schema)
|
|
92
|
-
if (!nodes[target]) {
|
|
93
|
-
nodes[target] = {
|
|
94
|
-
name: target,
|
|
95
|
-
dependsOn: [],
|
|
96
|
-
dependedOnBy: [],
|
|
97
|
-
softDependsOn: [],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
// Determine dependency type based on operator
|
|
101
|
-
const sourceNode = nodes[typeName];
|
|
102
|
-
const targetNode = nodes[target];
|
|
103
|
-
if (isSoft || isOptionalField) {
|
|
104
|
-
// Soft dependency (fuzzy search) or optional field
|
|
105
|
-
if (!sourceNode.softDependsOn.includes(target)) {
|
|
106
|
-
sourceNode.softDependsOn.push(target);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
else if (!isBackward) {
|
|
110
|
-
// Hard dependency for forward exact references (->)
|
|
111
|
-
// Backward references (<-) don't create generation dependencies
|
|
112
|
-
// because the parent creates the child, not vice versa
|
|
113
|
-
if (!sourceNode.dependsOn.includes(target)) {
|
|
114
|
-
sourceNode.dependsOn.push(target);
|
|
115
|
-
}
|
|
116
|
-
if (!targetNode.dependedOnBy.includes(typeName)) {
|
|
117
|
-
targetNode.dependedOnBy.push(typeName);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return { nodes, edges };
|
|
123
|
-
}
|
|
124
|
-
// =============================================================================
|
|
125
|
-
// Topological Sort
|
|
126
|
-
// =============================================================================
|
|
127
|
-
/**
|
|
128
|
-
* Compute topological order for generating types
|
|
129
|
-
*
|
|
130
|
-
* Returns types in order such that dependencies come before dependents.
|
|
131
|
-
* This is essential for cascade generation - we need to create referenced
|
|
132
|
-
* entities before the entities that reference them.
|
|
133
|
-
*
|
|
134
|
-
* @param graph - The dependency graph
|
|
135
|
-
* @param rootType - The root type to start from
|
|
136
|
-
* @param ignoreOptional - If true, optional dependencies don't contribute to ordering
|
|
137
|
-
* @returns Array of type names in generation order (dependencies first, root last)
|
|
138
|
-
* @throws CircularDependencyError if a cycle is detected
|
|
139
|
-
*/
|
|
140
|
-
export function topologicalSort(graph, rootType, ignoreOptional = false) {
|
|
141
|
-
const visited = new Set();
|
|
142
|
-
const visiting = new Set();
|
|
143
|
-
const result = [];
|
|
144
|
-
function visit(typeName, path) {
|
|
145
|
-
if (visited.has(typeName))
|
|
146
|
-
return;
|
|
147
|
-
if (visiting.has(typeName)) {
|
|
148
|
-
// Circular dependency detected
|
|
149
|
-
const cycleStart = path.indexOf(typeName);
|
|
150
|
-
const cyclePath = [...path.slice(cycleStart), typeName];
|
|
151
|
-
throw new CircularDependencyError(cyclePath);
|
|
152
|
-
}
|
|
153
|
-
visiting.add(typeName);
|
|
154
|
-
const node = graph.nodes[typeName];
|
|
155
|
-
if (node) {
|
|
156
|
-
for (const dep of node.dependsOn) {
|
|
157
|
-
// Check if this dependency is optional and should be ignored
|
|
158
|
-
if (ignoreOptional) {
|
|
159
|
-
const edge = graph.edges.find((e) => e.from === typeName && e.to === dep);
|
|
160
|
-
if (edge && graph.nodes[dep]) {
|
|
161
|
-
// Check if field has optional marker
|
|
162
|
-
const fieldIsOptional = edge.fieldName.endsWith('?');
|
|
163
|
-
if (fieldIsOptional)
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
visit(dep, [...path, typeName]);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
visiting.delete(typeName);
|
|
171
|
-
visited.add(typeName);
|
|
172
|
-
result.push(typeName);
|
|
173
|
-
}
|
|
174
|
-
visit(rootType, []);
|
|
175
|
-
return result;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Detect all cycles in the dependency graph
|
|
179
|
-
*
|
|
180
|
-
* @param graph - The dependency graph to check
|
|
181
|
-
* @param options - Detection options
|
|
182
|
-
* @returns Array of cycles, where each cycle is an array of type names
|
|
183
|
-
* The first and last element of each cycle are the same (showing the loop)
|
|
184
|
-
*/
|
|
185
|
-
export function detectCycles(graph, options = {}) {
|
|
186
|
-
const cycles = [];
|
|
187
|
-
const visited = new Set();
|
|
188
|
-
const recStack = new Set();
|
|
189
|
-
function dfs(node, path) {
|
|
190
|
-
if (recStack.has(node)) {
|
|
191
|
-
// Found a cycle
|
|
192
|
-
const cycleStart = path.indexOf(node);
|
|
193
|
-
const cycle = [...path.slice(cycleStart), node];
|
|
194
|
-
cycles.push(cycle);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
if (visited.has(node))
|
|
198
|
-
return;
|
|
199
|
-
visited.add(node);
|
|
200
|
-
recStack.add(node);
|
|
201
|
-
const nodeInfo = graph.nodes[node];
|
|
202
|
-
if (nodeInfo) {
|
|
203
|
-
for (const dep of nodeInfo.dependsOn) {
|
|
204
|
-
// Skip optional dependencies if configured
|
|
205
|
-
if (options.ignoreOptional) {
|
|
206
|
-
const edge = graph.edges.find((e) => e.from === node && e.to === dep);
|
|
207
|
-
if (edge) {
|
|
208
|
-
// Check if fieldName ends with ?
|
|
209
|
-
if (edge.fieldName.endsWith('?'))
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
dfs(dep, [...path, node]);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
recStack.delete(node);
|
|
217
|
-
}
|
|
218
|
-
for (const node of Object.keys(graph.nodes)) {
|
|
219
|
-
dfs(node, []);
|
|
220
|
-
}
|
|
221
|
-
return cycles;
|
|
222
|
-
}
|
|
223
|
-
// =============================================================================
|
|
224
|
-
// Parallel Groups
|
|
225
|
-
// =============================================================================
|
|
226
|
-
/**
|
|
227
|
-
* Get parallel generation groups - types that can be generated concurrently
|
|
228
|
-
*
|
|
229
|
-
* Returns an array of arrays, where each inner array contains types that
|
|
230
|
-
* can be generated in parallel (they have no dependencies on each other).
|
|
231
|
-
* Groups are ordered so that earlier groups must complete before later ones.
|
|
232
|
-
*
|
|
233
|
-
* @param graph - The dependency graph
|
|
234
|
-
* @param rootType - The root type to start from
|
|
235
|
-
* @returns Array of parallel groups, in execution order
|
|
236
|
-
*/
|
|
237
|
-
export function getParallelGroups(graph, rootType) {
|
|
238
|
-
const inDegree = {};
|
|
239
|
-
const relevantNodes = new Set();
|
|
240
|
-
// First, find all nodes reachable from root
|
|
241
|
-
function findReachable(node) {
|
|
242
|
-
if (relevantNodes.has(node))
|
|
243
|
-
return;
|
|
244
|
-
relevantNodes.add(node);
|
|
245
|
-
const nodeInfo = graph.nodes[node];
|
|
246
|
-
if (nodeInfo) {
|
|
247
|
-
for (const dep of nodeInfo.dependsOn) {
|
|
248
|
-
findReachable(dep);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
findReachable(rootType);
|
|
253
|
-
// Initialize in-degrees for relevant nodes only
|
|
254
|
-
for (const node of relevantNodes) {
|
|
255
|
-
inDegree[node] = 0;
|
|
256
|
-
}
|
|
257
|
-
// Count incoming edges (dependencies)
|
|
258
|
-
for (const node of relevantNodes) {
|
|
259
|
-
const nodeInfo = graph.nodes[node];
|
|
260
|
-
if (nodeInfo) {
|
|
261
|
-
for (const dep of nodeInfo.dependsOn) {
|
|
262
|
-
if (relevantNodes.has(dep)) {
|
|
263
|
-
const currentDegree = inDegree[node] ?? 0;
|
|
264
|
-
inDegree[node] = currentDegree + 1;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
const groups = [];
|
|
270
|
-
while (Object.keys(inDegree).length > 0) {
|
|
271
|
-
// Find all nodes with in-degree 0 (no remaining dependencies)
|
|
272
|
-
const group = Object.entries(inDegree)
|
|
273
|
-
.filter(([, degree]) => degree === 0)
|
|
274
|
-
.map(([node]) => node);
|
|
275
|
-
if (group.length === 0) {
|
|
276
|
-
// Remaining nodes have cycles - break to avoid infinite loop
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
279
|
-
groups.push(group);
|
|
280
|
-
// Remove processed nodes and update in-degrees
|
|
281
|
-
for (const node of group) {
|
|
282
|
-
delete inDegree[node];
|
|
283
|
-
// Reduce in-degree of nodes that depend on this node
|
|
284
|
-
for (const dependent of graph.nodes[node]?.dependedOnBy ?? []) {
|
|
285
|
-
if (dependent in inDegree) {
|
|
286
|
-
const currentDegree = inDegree[dependent] ?? 0;
|
|
287
|
-
inDegree[dependent] = currentDegree - 1;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return groups;
|
|
293
|
-
}
|
|
294
|
-
// =============================================================================
|
|
295
|
-
// Utility Functions
|
|
296
|
-
// =============================================================================
|
|
297
|
-
/**
|
|
298
|
-
* Get all dependencies for a specific type (including transitive)
|
|
299
|
-
*
|
|
300
|
-
* @param graph - The dependency graph
|
|
301
|
-
* @param typeName - The type to get dependencies for
|
|
302
|
-
* @returns Set of all type names this type depends on
|
|
303
|
-
*/
|
|
304
|
-
export function getAllDependencies(graph, typeName) {
|
|
305
|
-
const deps = new Set();
|
|
306
|
-
function collect(node) {
|
|
307
|
-
const nodeInfo = graph.nodes[node];
|
|
308
|
-
if (!nodeInfo)
|
|
309
|
-
return;
|
|
310
|
-
for (const dep of nodeInfo.dependsOn) {
|
|
311
|
-
if (!deps.has(dep)) {
|
|
312
|
-
deps.add(dep);
|
|
313
|
-
collect(dep);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
collect(typeName);
|
|
318
|
-
return deps;
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Check if the graph has any cycles
|
|
322
|
-
*
|
|
323
|
-
* @param graph - The dependency graph
|
|
324
|
-
* @returns true if cycles exist, false otherwise
|
|
325
|
-
*/
|
|
326
|
-
export function hasCycles(graph) {
|
|
327
|
-
return detectCycles(graph).length > 0;
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Get a human-readable visualization of the dependency graph
|
|
331
|
-
*
|
|
332
|
-
* @param graph - The dependency graph
|
|
333
|
-
* @returns Multi-line string showing the graph structure
|
|
334
|
-
*/
|
|
335
|
-
export function visualizeGraph(graph) {
|
|
336
|
-
const lines = ['Dependency Graph:', ''];
|
|
337
|
-
for (const [name, node] of Object.entries(graph.nodes)) {
|
|
338
|
-
lines.push(`${name}:`);
|
|
339
|
-
if (node.dependsOn.length > 0) {
|
|
340
|
-
lines.push(` -> ${node.dependsOn.join(', ')} (hard deps)`);
|
|
341
|
-
}
|
|
342
|
-
if (node.softDependsOn.length > 0) {
|
|
343
|
-
lines.push(` ~> ${node.softDependsOn.join(', ')} (soft deps)`);
|
|
344
|
-
}
|
|
345
|
-
if (node.dependedOnBy.length > 0) {
|
|
346
|
-
lines.push(` <- ${node.dependedOnBy.join(', ')} (depended on by)`);
|
|
347
|
-
}
|
|
348
|
-
if (node.dependsOn.length === 0 && node.softDependsOn.length === 0) {
|
|
349
|
-
lines.push(` (no dependencies)`);
|
|
350
|
-
}
|
|
351
|
-
lines.push('');
|
|
352
|
-
}
|
|
353
|
-
return lines.join('\n');
|
|
45
|
+
return buildDependencyGraphCore(toGraphdlParsedGraph(schema));
|
|
354
46
|
}
|
|
355
47
|
//# sourceMappingURL=dependency-graph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../src/schema/dependency-graph.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../src/schema/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EACL,oBAAoB,IAAI,wBAAwB,EAChD,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,uBAAuB,EACvB,eAAe,GAChB,MAAM,eAAe,CAAA;AAwBtB,gFAAgF;AAChF,gCAAgC;AAChC,gFAAgF;AAEhF,OAAO,EACL,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,uBAAuB,EACvB,eAAe,GAChB,CAAA;AAID,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,MAAoB;IAChD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,IAAI,GAAG,EAAE;KACpB,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,OAAO,wBAAwB,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAA;AAC/D,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Diff Engine
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for comparing two parsed schemas and detecting
|
|
5
|
+
* added, removed, and modified entities and fields.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import type { ParsedSchema, ParsedField } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Describes a change to a single field
|
|
12
|
+
*/
|
|
13
|
+
export interface FieldChange {
|
|
14
|
+
/** Name of the field */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Previous field definition (for modifications) */
|
|
17
|
+
oldField?: ParsedField;
|
|
18
|
+
/** New field definition (for modifications) */
|
|
19
|
+
newField?: ParsedField;
|
|
20
|
+
/** Type of change */
|
|
21
|
+
changeType: 'type' | 'optional' | 'array' | 'relation' | 'operator' | 'multiple';
|
|
22
|
+
/** Human-readable description of the change */
|
|
23
|
+
description: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Possible rename detection for a removed+added field pair
|
|
27
|
+
*/
|
|
28
|
+
export interface PossibleRename {
|
|
29
|
+
/** The old field name that was removed */
|
|
30
|
+
oldName: string;
|
|
31
|
+
/** The new field name that was added */
|
|
32
|
+
newName: string;
|
|
33
|
+
/** Confidence score (0-1) based on type similarity */
|
|
34
|
+
confidence: number;
|
|
35
|
+
/** Why this might be a rename */
|
|
36
|
+
reason: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Diff result for a single entity
|
|
40
|
+
*/
|
|
41
|
+
export interface EntityDiff {
|
|
42
|
+
/** Name of the entity */
|
|
43
|
+
entityName: string;
|
|
44
|
+
/** Fields that were added */
|
|
45
|
+
addedFields: ParsedField[];
|
|
46
|
+
/** Fields that were removed */
|
|
47
|
+
removedFields: ParsedField[];
|
|
48
|
+
/** Fields that were modified */
|
|
49
|
+
changedFields: FieldChange[];
|
|
50
|
+
/** Possible field renames (removed+added with similar types) */
|
|
51
|
+
possibleRenames: PossibleRename[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Complete diff between two schemas
|
|
55
|
+
*/
|
|
56
|
+
export interface SchemaDiff {
|
|
57
|
+
/** Entities that were added to the new schema */
|
|
58
|
+
addedEntities: string[];
|
|
59
|
+
/** Entities that were removed from the old schema */
|
|
60
|
+
removedEntities: string[];
|
|
61
|
+
/** Entities that were modified */
|
|
62
|
+
modifiedEntities: EntityDiff[];
|
|
63
|
+
/** Whether there are any changes at all */
|
|
64
|
+
hasChanges: boolean;
|
|
65
|
+
/** Summary of changes */
|
|
66
|
+
summary: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Compare two parsed schemas and detect all differences
|
|
70
|
+
*
|
|
71
|
+
* This function performs a comprehensive comparison between two schemas,
|
|
72
|
+
* identifying:
|
|
73
|
+
* - Added entities (in new schema but not old)
|
|
74
|
+
* - Removed entities (in old schema but not new)
|
|
75
|
+
* - Modified entities (field changes within entities)
|
|
76
|
+
* - Possible field renames (based on type similarity)
|
|
77
|
+
*
|
|
78
|
+
* @param oldParsed - The old parsed schema
|
|
79
|
+
* @param newParsed - The new parsed schema
|
|
80
|
+
* @returns Complete diff with all detected changes
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const oldSchema = parseSchema({ User: { name: 'string' } })
|
|
85
|
+
* const newSchema = parseSchema({
|
|
86
|
+
* User: { name: 'string', email: 'string' },
|
|
87
|
+
* Post: { title: 'string' }
|
|
88
|
+
* })
|
|
89
|
+
*
|
|
90
|
+
* const diff = diffSchemas(oldSchema, newSchema)
|
|
91
|
+
* // diff.addedEntities = ['Post']
|
|
92
|
+
* // diff.modifiedEntities[0].addedFields[0].name = 'email'
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function diffSchemas(oldParsed: ParsedSchema, newParsed: ParsedSchema): SchemaDiff;
|
|
96
|
+
/**
|
|
97
|
+
* Get a human-readable description of a schema diff
|
|
98
|
+
*
|
|
99
|
+
* @param diff - The schema diff to describe
|
|
100
|
+
* @returns Multi-line string describing all changes
|
|
101
|
+
*/
|
|
102
|
+
export declare function describeDiff(diff: SchemaDiff): string;
|
|
103
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/schema/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAgB,WAAW,EAAE,MAAM,aAAa,CAAA;AAM1E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,qBAAqB;IACrB,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;IAChF,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,6BAA6B;IAC7B,WAAW,EAAE,WAAW,EAAE,CAAA;IAC1B,+BAA+B;IAC/B,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,gCAAgC;IAChC,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,gEAAgE;IAChE,eAAe,EAAE,cAAc,EAAE,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,qDAAqD;IACrD,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,kCAAkC;IAClC,gBAAgB,EAAE,UAAU,EAAE,CAAA;IAC9B,2CAA2C;IAC3C,UAAU,EAAE,OAAO,CAAA;IACnB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAA;CAChB;AAsOD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,GAAG,UAAU,CAwExF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAyDrD"}
|