ai-database 2.0.2 → 2.1.1
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 +36 -0
- package/dist/actions.d.ts +247 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +260 -0
- package/dist/actions.js.map +1 -0
- package/dist/ai-promise-db.d.ts +34 -2
- package/dist/ai-promise-db.d.ts.map +1 -1
- package/dist/ai-promise-db.js +511 -66
- package/dist/ai-promise-db.js.map +1 -1
- package/dist/constants.d.ts +16 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -0
- package/dist/events.d.ts +153 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +154 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/memory-provider.d.ts +144 -2
- package/dist/memory-provider.d.ts.map +1 -1
- package/dist/memory-provider.js +569 -13
- package/dist/memory-provider.js.map +1 -1
- package/dist/schema/cascade.d.ts +96 -0
- package/dist/schema/cascade.d.ts.map +1 -0
- package/dist/schema/cascade.js +528 -0
- package/dist/schema/cascade.js.map +1 -0
- package/dist/schema/index.d.ts +197 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +1211 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/parse.d.ts +225 -0
- package/dist/schema/parse.d.ts.map +1 -0
- package/dist/schema/parse.js +732 -0
- package/dist/schema/parse.js.map +1 -0
- package/dist/schema/provider.d.ts +176 -0
- package/dist/schema/provider.d.ts.map +1 -0
- package/dist/schema/provider.js +258 -0
- package/dist/schema/provider.js.map +1 -0
- package/dist/schema/resolve.d.ts +87 -0
- package/dist/schema/resolve.d.ts.map +1 -0
- package/dist/schema/resolve.js +474 -0
- package/dist/schema/resolve.js.map +1 -0
- package/dist/schema/semantic.d.ts +53 -0
- package/dist/schema/semantic.d.ts.map +1 -0
- package/dist/schema/semantic.js +247 -0
- package/dist/schema/semantic.js.map +1 -0
- package/dist/schema/types.d.ts +528 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +9 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/schema.d.ts +24 -867
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +41 -1124
- package/dist/schema.js.map +1 -1
- package/dist/semantic.d.ts +175 -0
- package/dist/semantic.d.ts.map +1 -0
- package/dist/semantic.js +338 -0
- package/dist/semantic.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +13 -4
- package/.turbo/turbo-build.log +0 -5
- package/TESTING.md +0 -410
- package/TEST_SUMMARY.md +0 -250
- package/TODO.md +0 -128
- package/src/ai-promise-db.ts +0 -1243
- package/src/authorization.ts +0 -1102
- package/src/durable-clickhouse.ts +0 -596
- package/src/durable-promise.ts +0 -582
- package/src/execution-queue.ts +0 -608
- package/src/index.test.ts +0 -868
- package/src/index.ts +0 -337
- package/src/linguistic.ts +0 -404
- package/src/memory-provider.test.ts +0 -1036
- package/src/memory-provider.ts +0 -1119
- package/src/schema.test.ts +0 -1254
- package/src/schema.ts +0 -2296
- package/src/tests.ts +0 -725
- package/src/types.ts +0 -1177
- package/test/README.md +0 -153
- package/test/edge-cases.test.ts +0 -646
- package/test/provider-resolution.test.ts +0 -402
- package/tsconfig.json +0 -9
- package/vitest.config.ts +0 -19
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference Resolution Functions
|
|
3
|
+
*
|
|
4
|
+
* Contains forward/backward resolution functions for relationships,
|
|
5
|
+
* context resolution, and entity hydration.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { hasSemanticSearch } from './provider.js';
|
|
10
|
+
import { isPrimitiveType } from './parse.js';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Context Resolution - Template Variables and $instructions
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Check if a string looks like an entity ID (UUID format or type-prefixed)
|
|
16
|
+
*/
|
|
17
|
+
export function isEntityId(value) {
|
|
18
|
+
// UUID pattern
|
|
19
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
|
+
if (uuidPattern.test(value))
|
|
21
|
+
return true;
|
|
22
|
+
// Type-prefixed ID pattern (e.g., "post-123")
|
|
23
|
+
if (/^[a-z]+-[a-z0-9-]+$/i.test(value))
|
|
24
|
+
return true;
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Infer the entity type from a field name using schema relationships
|
|
29
|
+
*/
|
|
30
|
+
export function inferTypeFromField(fieldName, entity, schema) {
|
|
31
|
+
// First check if field is a relation in the current entity
|
|
32
|
+
const field = entity.fields.get(fieldName);
|
|
33
|
+
if (field?.isRelation && field.relatedType) {
|
|
34
|
+
return field.relatedType;
|
|
35
|
+
}
|
|
36
|
+
// Check for camelCase field name that might match a type (e.g., "occupation" -> "Occupation")
|
|
37
|
+
const capitalizedName = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
|
|
38
|
+
if (schema.entities.has(capitalizedName)) {
|
|
39
|
+
return capitalizedName;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a context path like "task.occupation.industry.name" against an entity
|
|
45
|
+
*
|
|
46
|
+
* This traverses relationships and fetches related entities as needed.
|
|
47
|
+
*/
|
|
48
|
+
export async function resolveContextPath(path, entity, currentTypeName, schema, provider) {
|
|
49
|
+
const parts = path.split('.');
|
|
50
|
+
let current = entity;
|
|
51
|
+
let currentType = schema.entities.get(currentTypeName);
|
|
52
|
+
for (let i = 0; i < parts.length; i++) {
|
|
53
|
+
const part = parts[i];
|
|
54
|
+
if (current == null || typeof current !== 'object')
|
|
55
|
+
return undefined;
|
|
56
|
+
const record = current;
|
|
57
|
+
const value = record[part];
|
|
58
|
+
// If it's a string that looks like an entity ID, try to fetch the entity
|
|
59
|
+
if (typeof value === 'string' && isEntityId(value) && currentType) {
|
|
60
|
+
const typeName = inferTypeFromField(part, currentType, schema);
|
|
61
|
+
if (typeName) {
|
|
62
|
+
const fetched = await provider.get(typeName, value);
|
|
63
|
+
if (fetched) {
|
|
64
|
+
current = fetched;
|
|
65
|
+
currentType = schema.entities.get(typeName);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
current = value;
|
|
71
|
+
// Update currentType for next iteration if we have a valid field reference
|
|
72
|
+
if (currentType) {
|
|
73
|
+
const nextTypeName = inferTypeFromField(part, currentType, schema);
|
|
74
|
+
if (nextTypeName) {
|
|
75
|
+
currentType = schema.entities.get(nextTypeName);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return current;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve template variables in $instructions
|
|
83
|
+
*
|
|
84
|
+
* Template variables use the syntax {path.to.field} where the path
|
|
85
|
+
* can traverse relationships (e.g., {task.occupation.title})
|
|
86
|
+
*
|
|
87
|
+
* @param instructions - The instruction string with template variables
|
|
88
|
+
* @param entity - The current entity data
|
|
89
|
+
* @param typeName - The current entity type name
|
|
90
|
+
* @param schema - The parsed schema
|
|
91
|
+
* @param provider - The database provider for fetching related entities
|
|
92
|
+
* @returns The instructions with all template variables resolved
|
|
93
|
+
*/
|
|
94
|
+
export async function resolveInstructions(instructions, entity, typeName, schema, provider) {
|
|
95
|
+
const pattern = /\{([^}]+)\}/g;
|
|
96
|
+
let resolved = instructions;
|
|
97
|
+
// Find all matches first to avoid issues with modifying string during iteration
|
|
98
|
+
const matches = [...instructions.matchAll(pattern)];
|
|
99
|
+
for (const match of matches) {
|
|
100
|
+
const path = match[1];
|
|
101
|
+
const value = await resolveContextPath(path, entity, typeName, schema, provider);
|
|
102
|
+
resolved = resolved.replace(match[0], String(value ?? ''));
|
|
103
|
+
}
|
|
104
|
+
return resolved;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Pre-fetch context dependencies declared in $context
|
|
108
|
+
*
|
|
109
|
+
* The $context field declares explicit context dependencies that should
|
|
110
|
+
* be pre-fetched before generating AI fields. This ensures all referenced
|
|
111
|
+
* entities are available for template variable resolution.
|
|
112
|
+
*
|
|
113
|
+
* @param contextDeps - Array of context dependency types (e.g., ['Startup', 'ICP'])
|
|
114
|
+
* @param entity - The current entity data
|
|
115
|
+
* @param typeName - The current entity type name
|
|
116
|
+
* @param schema - The parsed schema
|
|
117
|
+
* @param provider - The database provider for fetching related entities
|
|
118
|
+
* @returns Map of context name to fetched entity data
|
|
119
|
+
*/
|
|
120
|
+
export async function prefetchContext(contextDeps, entity, typeName, schema, provider) {
|
|
121
|
+
const contextData = new Map();
|
|
122
|
+
const currentEntity = schema.entities.get(typeName);
|
|
123
|
+
if (!currentEntity)
|
|
124
|
+
return contextData;
|
|
125
|
+
for (const dep of contextDeps) {
|
|
126
|
+
// Convert to camelCase for field lookup (e.g., "Startup" -> "startup")
|
|
127
|
+
const fieldName = dep.charAt(0).toLowerCase() + dep.slice(1);
|
|
128
|
+
// Check if we have a field that references this type
|
|
129
|
+
const field = currentEntity.fields.get(fieldName);
|
|
130
|
+
if (field?.isRelation && field.relatedType) {
|
|
131
|
+
const entityId = entity[fieldName];
|
|
132
|
+
if (typeof entityId === 'string') {
|
|
133
|
+
const fetched = await provider.get(field.relatedType, entityId);
|
|
134
|
+
if (fetched) {
|
|
135
|
+
contextData.set(fieldName, fetched);
|
|
136
|
+
// Also store nested relationships
|
|
137
|
+
const relatedEntity = schema.entities.get(field.relatedType);
|
|
138
|
+
if (relatedEntity) {
|
|
139
|
+
for (const [nestedFieldName, nestedField] of relatedEntity.fields) {
|
|
140
|
+
if (nestedField.isRelation && nestedField.relatedType) {
|
|
141
|
+
const nestedId = fetched[nestedFieldName];
|
|
142
|
+
if (typeof nestedId === 'string') {
|
|
143
|
+
const nestedFetched = await provider.get(nestedField.relatedType, nestedId);
|
|
144
|
+
if (nestedFetched) {
|
|
145
|
+
contextData.set(`${fieldName}.${nestedFieldName}`, nestedFetched);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return contextData;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if a field type is a prompt (contains spaces, indicating AI generation)
|
|
159
|
+
*/
|
|
160
|
+
export function isPromptField(field) {
|
|
161
|
+
// Fields with spaces in their type are prompts for AI generation
|
|
162
|
+
return field.type.includes(' ') ||
|
|
163
|
+
(field.type === 'string' && !field.isRelation && !isPrimitiveType(field.type));
|
|
164
|
+
}
|
|
165
|
+
// =============================================================================
|
|
166
|
+
// Nested Pending Resolution
|
|
167
|
+
// =============================================================================
|
|
168
|
+
/**
|
|
169
|
+
* Resolve pending nested relations in generated data
|
|
170
|
+
*
|
|
171
|
+
* When generateEntity encounters nested -> relations, it stores them as
|
|
172
|
+
* _pending_fieldName entries. This function creates those entities and
|
|
173
|
+
* replaces the pending entries with actual IDs.
|
|
174
|
+
*/
|
|
175
|
+
export async function resolveNestedPending(data, entity, schema, provider) {
|
|
176
|
+
const resolved = { ...data };
|
|
177
|
+
for (const key of Object.keys(resolved)) {
|
|
178
|
+
if (key.startsWith('_pending_')) {
|
|
179
|
+
const fieldName = key.replace('_pending_', '');
|
|
180
|
+
const pending = resolved[key];
|
|
181
|
+
delete resolved[key];
|
|
182
|
+
// Get the related entity to resolve its nested pending relations too
|
|
183
|
+
const relatedEntity = schema.entities.get(pending.type);
|
|
184
|
+
if (relatedEntity) {
|
|
185
|
+
const resolvedNested = await resolveNestedPending(pending.data, relatedEntity, schema, provider);
|
|
186
|
+
const created = await provider.create(pending.type, undefined, resolvedNested);
|
|
187
|
+
resolved[fieldName] = created.$id;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return resolved;
|
|
192
|
+
}
|
|
193
|
+
// =============================================================================
|
|
194
|
+
// Reference Resolution
|
|
195
|
+
// =============================================================================
|
|
196
|
+
/**
|
|
197
|
+
* Resolve a single reference specification to an entity ID
|
|
198
|
+
*
|
|
199
|
+
* For exact matches (-> and <-), creates new entities.
|
|
200
|
+
* For fuzzy matches (~> and <~), searches for existing entities first.
|
|
201
|
+
*/
|
|
202
|
+
export async function resolveReferenceSpec(spec, contextData, schema, provider, generateContextAwareValue) {
|
|
203
|
+
const targetEntity = schema.entities.get(spec.type);
|
|
204
|
+
if (!targetEntity) {
|
|
205
|
+
throw new Error(`Unknown target type: ${spec.type}`);
|
|
206
|
+
}
|
|
207
|
+
if (spec.matchMode === 'fuzzy') {
|
|
208
|
+
// For fuzzy references, try to find an existing entity first
|
|
209
|
+
if (hasSemanticSearch(provider)) {
|
|
210
|
+
const searchQuery = spec.generatedText || spec.prompt || spec.field;
|
|
211
|
+
const matches = await provider.semanticSearch(spec.type, searchQuery, {
|
|
212
|
+
minScore: 0.5,
|
|
213
|
+
limit: 1,
|
|
214
|
+
});
|
|
215
|
+
const firstMatch = matches[0];
|
|
216
|
+
if (firstMatch) {
|
|
217
|
+
return firstMatch.$id;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// If no match found for fuzzy, fall through to create
|
|
221
|
+
}
|
|
222
|
+
// Create a new entity
|
|
223
|
+
const generatedData = {};
|
|
224
|
+
// Build context for generation
|
|
225
|
+
const hint = spec.generatedText || spec.prompt || spec.field;
|
|
226
|
+
const parentContextFields = [];
|
|
227
|
+
for (const [key, value] of Object.entries(contextData)) {
|
|
228
|
+
if (!key.startsWith('$') && !key.startsWith('_') && typeof value === 'string' && value) {
|
|
229
|
+
parentContextFields.push(`${key}: ${value}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const fullContext = [hint, ...parentContextFields].filter(Boolean).join(' | ');
|
|
233
|
+
// Generate default values for the target entity's fields
|
|
234
|
+
for (const [fieldName, field] of targetEntity.fields) {
|
|
235
|
+
if (!field.isRelation && !field.isOptional) {
|
|
236
|
+
if (field.type === 'string') {
|
|
237
|
+
generatedData[fieldName] = generateContextAwareValue(fieldName, spec.type, fullContext, hint, contextData);
|
|
238
|
+
}
|
|
239
|
+
else if (field.type === 'number') {
|
|
240
|
+
generatedData[fieldName] = 0;
|
|
241
|
+
}
|
|
242
|
+
else if (field.type === 'boolean') {
|
|
243
|
+
generatedData[fieldName] = false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (field.isRelation && field.operator === '->' && !field.isArray && !field.isOptional) {
|
|
247
|
+
// Recursively resolve nested forward exact relations
|
|
248
|
+
const nestedSpec = {
|
|
249
|
+
field: fieldName,
|
|
250
|
+
operator: '->',
|
|
251
|
+
type: field.relatedType,
|
|
252
|
+
matchMode: 'exact',
|
|
253
|
+
resolved: false,
|
|
254
|
+
prompt: field.prompt,
|
|
255
|
+
};
|
|
256
|
+
const nestedId = await resolveReferenceSpec(nestedSpec, generatedData, schema, provider, generateContextAwareValue);
|
|
257
|
+
if (nestedId) {
|
|
258
|
+
generatedData[fieldName] = nestedId;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Use parent ID if available, otherwise use a descriptive string
|
|
263
|
+
const parentId = contextData.$id;
|
|
264
|
+
const created = await provider.create(spec.type, undefined, {
|
|
265
|
+
...generatedData,
|
|
266
|
+
$generated: true,
|
|
267
|
+
$generatedBy: parentId || (spec.matchMode === 'fuzzy' ? 'fuzzy-resolution' : 'reference-resolution'),
|
|
268
|
+
$sourceField: spec.field,
|
|
269
|
+
});
|
|
270
|
+
return created.$id;
|
|
271
|
+
}
|
|
272
|
+
// =============================================================================
|
|
273
|
+
// Entity Hydration
|
|
274
|
+
// =============================================================================
|
|
275
|
+
/**
|
|
276
|
+
* Hydrate an entity with lazy-loaded relations
|
|
277
|
+
*
|
|
278
|
+
* For backward edges (direction === 'backward'), we query for entities
|
|
279
|
+
* of the related type that have a reference pointing TO this entity.
|
|
280
|
+
* This enables reverse lookups like "get all comments for a post".
|
|
281
|
+
*
|
|
282
|
+
* Backward reference resolution:
|
|
283
|
+
* - Single backward ref with stored ID: resolve directly (e.g., member.team = teamId -> get Team by ID)
|
|
284
|
+
* - Single backward ref without stored ID: find related entity that points to us via relations
|
|
285
|
+
* - Array backward ref: find all entities of related type where their forward ref points to us
|
|
286
|
+
*/
|
|
287
|
+
export function hydrateEntity(data, entity, schema, resolveProvider) {
|
|
288
|
+
const hydrated = { ...data };
|
|
289
|
+
const id = (data.$id || data.id);
|
|
290
|
+
const typeName = entity.name;
|
|
291
|
+
// Add lazy getters for relations
|
|
292
|
+
for (const [fieldName, field] of entity.fields) {
|
|
293
|
+
if (field.isRelation && field.relatedType) {
|
|
294
|
+
const relatedEntity = schema.entities.get(field.relatedType);
|
|
295
|
+
if (!relatedEntity)
|
|
296
|
+
continue;
|
|
297
|
+
// Check if this is a backward edge
|
|
298
|
+
const isBackward = field.direction === 'backward';
|
|
299
|
+
// For forward single relations with stored IDs, create a proxy that:
|
|
300
|
+
// - Acts like a string (for .toMatch(), String(), etc.)
|
|
301
|
+
// - Can be awaited to get the related entity (thenable)
|
|
302
|
+
if (!isBackward && !field.isArray && data[fieldName]) {
|
|
303
|
+
const storedId = data[fieldName];
|
|
304
|
+
const thenableProxy = new Proxy({}, {
|
|
305
|
+
get(target, prop) {
|
|
306
|
+
if (prop === 'then') {
|
|
307
|
+
return (resolve, reject) => {
|
|
308
|
+
return (async () => {
|
|
309
|
+
const provider = await resolveProvider();
|
|
310
|
+
const result = await provider.get(field.relatedType, storedId);
|
|
311
|
+
return result ? hydrateEntity(result, relatedEntity, schema, resolveProvider) : null;
|
|
312
|
+
})().then(resolve, reject);
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (prop === Symbol.toPrimitive || prop === 'valueOf') {
|
|
316
|
+
return () => storedId;
|
|
317
|
+
}
|
|
318
|
+
if (prop === 'toString') {
|
|
319
|
+
return () => storedId;
|
|
320
|
+
}
|
|
321
|
+
if (prop === 'match') {
|
|
322
|
+
return (regex) => storedId.match(regex);
|
|
323
|
+
}
|
|
324
|
+
if (prop === '$type') {
|
|
325
|
+
return field.relatedType;
|
|
326
|
+
}
|
|
327
|
+
return undefined;
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
hydrated[fieldName] = thenableProxy;
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
// For forward array relations with stored IDs, create a thenable array that:
|
|
334
|
+
// - Behaves like a normal array of IDs (has length, can be iterated, etc.)
|
|
335
|
+
// - Can be awaited to fetch and hydrate the full entities
|
|
336
|
+
// Note: we create the proxy even for empty arrays so they have $type for batch loading detection
|
|
337
|
+
if (!isBackward && field.isArray && Array.isArray(data[fieldName])) {
|
|
338
|
+
const storedIds = data[fieldName];
|
|
339
|
+
// Create a proxy that wraps the array but adds thenable behavior
|
|
340
|
+
const thenableArray = new Proxy(storedIds, {
|
|
341
|
+
get(target, prop) {
|
|
342
|
+
if (prop === 'then') {
|
|
343
|
+
return (resolve, reject) => {
|
|
344
|
+
return (async () => {
|
|
345
|
+
const provider = await resolveProvider();
|
|
346
|
+
const results = await Promise.all(storedIds.map(targetId => provider.get(field.relatedType, targetId)));
|
|
347
|
+
return results.filter(r => r !== null).map((r) => hydrateEntity(r, relatedEntity, schema, resolveProvider));
|
|
348
|
+
})().then(resolve, reject);
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// Expose $type for batch loading detection
|
|
352
|
+
if (prop === '$type') {
|
|
353
|
+
return field.relatedType;
|
|
354
|
+
}
|
|
355
|
+
// Expose $isArrayRelation marker for batch loading
|
|
356
|
+
if (prop === '$isArrayRelation') {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
// For all other properties, delegate to the actual array
|
|
360
|
+
const value = Reflect.get(target, prop);
|
|
361
|
+
// Bind methods to the target array
|
|
362
|
+
if (typeof value === 'function') {
|
|
363
|
+
return value.bind(target);
|
|
364
|
+
}
|
|
365
|
+
return value;
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
hydrated[fieldName] = thenableArray;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
// Define lazy getter
|
|
372
|
+
Object.defineProperty(hydrated, fieldName, {
|
|
373
|
+
get: () => {
|
|
374
|
+
// Check if this is a backward edge
|
|
375
|
+
if (isBackward && !field.isArray) {
|
|
376
|
+
// Case 1: Single backward ref
|
|
377
|
+
// Returns a Promise that resolves to the related entity
|
|
378
|
+
const storedId = data[fieldName];
|
|
379
|
+
return (async () => {
|
|
380
|
+
const provider = await resolveProvider();
|
|
381
|
+
if (storedId) {
|
|
382
|
+
// Has stored ID - directly fetch the related entity
|
|
383
|
+
const result = await provider.get(field.relatedType, storedId);
|
|
384
|
+
return result
|
|
385
|
+
? hydrateEntity(result, relatedEntity, schema, resolveProvider)
|
|
386
|
+
: null;
|
|
387
|
+
}
|
|
388
|
+
// No stored ID - find via inverse relation lookup
|
|
389
|
+
// Find entities of relatedType that have this entity in their relations
|
|
390
|
+
for (const [relFieldName, relField] of relatedEntity.fields) {
|
|
391
|
+
if (relField.isRelation &&
|
|
392
|
+
relField.relatedType === typeName &&
|
|
393
|
+
relField.direction !== 'backward' &&
|
|
394
|
+
relField.isArray) {
|
|
395
|
+
// Found a forward array relation on related entity pointing to us
|
|
396
|
+
// Check if any entity of relatedType has this entity in that relation
|
|
397
|
+
const allRelated = await provider.list(field.relatedType);
|
|
398
|
+
for (const candidate of allRelated) {
|
|
399
|
+
const candidateId = (candidate.$id || candidate.id);
|
|
400
|
+
const related = await provider.related(field.relatedType, candidateId, relFieldName);
|
|
401
|
+
if (related.some(r => (r.$id || r.id) === id)) {
|
|
402
|
+
return hydrateEntity(candidate, relatedEntity, schema, resolveProvider);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return null;
|
|
408
|
+
})();
|
|
409
|
+
}
|
|
410
|
+
// For forward relations and backward arrays, return async resolver
|
|
411
|
+
return (async () => {
|
|
412
|
+
const provider = await resolveProvider();
|
|
413
|
+
if (isBackward) {
|
|
414
|
+
// Case 2: Array backward ref
|
|
415
|
+
// Check if we have stored IDs (e.g., from backward fuzzy resolution)
|
|
416
|
+
const storedIds = data[fieldName];
|
|
417
|
+
if (Array.isArray(storedIds) && storedIds.length > 0) {
|
|
418
|
+
// Use stored IDs directly - this handles backward fuzzy (<~) array fields
|
|
419
|
+
const results = await Promise.all(storedIds.map(targetId => provider.get(field.relatedType, targetId)));
|
|
420
|
+
return Promise.all(results.filter(r => r !== null).map((r) => hydrateEntity(r, relatedEntity, schema, resolveProvider)));
|
|
421
|
+
}
|
|
422
|
+
// No stored IDs - use backref lookup
|
|
423
|
+
// e.g., Blog.posts: ['<-Post'] - find Posts where post.blog === blog.$id
|
|
424
|
+
// The backref tells us which field on the related type stores our ID
|
|
425
|
+
// If no explicit backref, infer from schema relationships
|
|
426
|
+
let backrefField = field.backref;
|
|
427
|
+
if (!backrefField) {
|
|
428
|
+
// Infer backref: look for a field on related entity that points to us
|
|
429
|
+
for (const [relFieldName, relField] of relatedEntity.fields) {
|
|
430
|
+
if (relField.isRelation &&
|
|
431
|
+
relField.relatedType === typeName &&
|
|
432
|
+
relField.direction !== 'backward' &&
|
|
433
|
+
!relField.isArray) {
|
|
434
|
+
// Found a forward single relation pointing to us - use its name
|
|
435
|
+
backrefField = relFieldName;
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// Fallback to entity name lowercase if no explicit relation found
|
|
440
|
+
if (!backrefField) {
|
|
441
|
+
backrefField = typeName.toLowerCase();
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
// Query the related type for entities that reference this entity
|
|
445
|
+
const results = await provider.list(field.relatedType, {
|
|
446
|
+
where: { [backrefField]: id },
|
|
447
|
+
});
|
|
448
|
+
return Promise.all(results.map((r) => hydrateEntity(r, relatedEntity, schema, resolveProvider)));
|
|
449
|
+
}
|
|
450
|
+
else if (field.isArray) {
|
|
451
|
+
// Forward array relation - get related entities via relationship
|
|
452
|
+
const results = await provider.related(entity.name, id, fieldName);
|
|
453
|
+
return Promise.all(results.map((r) => hydrateEntity(r, relatedEntity, schema, resolveProvider)));
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
// Forward single relation - get the stored ID and fetch
|
|
457
|
+
const relatedId = data[fieldName];
|
|
458
|
+
if (!relatedId)
|
|
459
|
+
return null;
|
|
460
|
+
const result = await provider.get(field.relatedType, relatedId);
|
|
461
|
+
return result
|
|
462
|
+
? hydrateEntity(result, relatedEntity, schema, resolveProvider)
|
|
463
|
+
: null;
|
|
464
|
+
}
|
|
465
|
+
})();
|
|
466
|
+
},
|
|
467
|
+
enumerable: true,
|
|
468
|
+
configurable: true,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return hydrated;
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/schema/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Search and Matching
|
|
3
|
+
*
|
|
4
|
+
* Contains backward fuzzy (<~) and forward fuzzy (~>) resolution functions
|
|
5
|
+
* for semantic search-based relationship matching.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import type { ParsedEntity, ParsedSchema } from '../types.js';
|
|
10
|
+
import type { DBProvider } from './provider.js';
|
|
11
|
+
/**
|
|
12
|
+
* Resolve backward fuzzy (<~) fields by using semantic search to find existing entities
|
|
13
|
+
*
|
|
14
|
+
* The <~ operator differs from <- in that it uses semantic/fuzzy matching:
|
|
15
|
+
* - Uses AI/embedding-based similarity to find the best match from existing entities
|
|
16
|
+
* - Does NOT generate new entities - only grounds to existing reference data
|
|
17
|
+
* - Uses hint fields (e.g., categoryHint for category field) to guide matching
|
|
18
|
+
*
|
|
19
|
+
* @param typeName - The type of entity being created
|
|
20
|
+
* @param data - The input data including hint fields
|
|
21
|
+
* @param entity - The parsed entity definition
|
|
22
|
+
* @param schema - The parsed schema
|
|
23
|
+
* @param provider - The database provider (must support semanticSearch)
|
|
24
|
+
* @returns The resolved data with backward fuzzy fields populated with matched entity IDs
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveBackwardFuzzy(typeName: string, data: Record<string, unknown>, entity: ParsedEntity, schema: ParsedSchema, provider: DBProvider): Promise<Record<string, unknown>>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve forward fuzzy (~>) fields via semantic search then generation
|
|
29
|
+
*
|
|
30
|
+
* The ~> operator differs from -> in that it first attempts semantic search:
|
|
31
|
+
* - Searches existing entities via embedding similarity
|
|
32
|
+
* - If a match is found above threshold, reuses the existing entity
|
|
33
|
+
* - If no match is found, generates a new entity
|
|
34
|
+
* - Respects configurable similarity threshold ($fuzzyThreshold or field-level)
|
|
35
|
+
*
|
|
36
|
+
* @param typeName - The type of entity being created
|
|
37
|
+
* @param data - The input data including hint fields
|
|
38
|
+
* @param entity - The parsed entity definition
|
|
39
|
+
* @param schema - The parsed schema
|
|
40
|
+
* @param provider - The database provider (must support semanticSearch)
|
|
41
|
+
* @param parentId - Pre-generated ID of the parent entity for backward refs
|
|
42
|
+
* @returns Object with resolved data and pending relations for array fields
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveForwardFuzzy(typeName: string, data: Record<string, unknown>, entity: ParsedEntity, schema: ParsedSchema, provider: DBProvider, parentId: string): Promise<{
|
|
45
|
+
data: Record<string, unknown>;
|
|
46
|
+
pendingRelations: Array<{
|
|
47
|
+
fieldName: string;
|
|
48
|
+
targetType: string;
|
|
49
|
+
targetId: string;
|
|
50
|
+
similarity?: number;
|
|
51
|
+
}>;
|
|
52
|
+
}>;
|
|
53
|
+
//# sourceMappingURL=semantic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/schema/semantic.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EAEb,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,eAAe,CAAA;AA+BrE;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiDlC;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,gBAAgB,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAoKvJ"}
|