latticesql 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -716,6 +716,19 @@ function resolveEntitySource(source, entityRow, entityPk, adapter) {
716
716
  }
717
717
  case "custom":
718
718
  return source.query(entityRow, adapter);
719
+ case "enriched": {
720
+ const enriched = { ...entityRow };
721
+ for (const [key, lookup] of Object.entries(source.include)) {
722
+ const fieldName = `_${key}`;
723
+ if (lookup.type === "custom") {
724
+ enriched[fieldName] = JSON.stringify(lookup.query(entityRow, adapter));
725
+ } else {
726
+ const resolved = resolveEntitySource(lookup, entityRow, entityPk, adapter);
727
+ enriched[fieldName] = JSON.stringify(resolved);
728
+ }
729
+ }
730
+ return [enriched];
731
+ }
719
732
  }
720
733
  }
721
734
  function truncateContent(content, budget) {
@@ -928,7 +941,8 @@ var RenderEngine = class {
928
941
  mkdirSync3(entityDir, { recursive: true });
929
942
  const renderedFiles = /* @__PURE__ */ new Map();
930
943
  for (const [filename, spec] of Object.entries(def.files)) {
931
- const source = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" ? { ...def.sourceDefaults, ...spec.source } : spec.source;
944
+ const mergeDefaults = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" && spec.source.type !== "enriched";
945
+ const source = mergeDefaults ? { ...def.sourceDefaults, ...spec.source } : spec.source;
932
946
  const rows = resolveEntitySource(source, entityRow, entityPk, this._adapter);
933
947
  if (spec.omitIfEmpty && rows.length === 0) continue;
934
948
  const content = truncateContent(spec.render(rows), spec.budget);
package/dist/index.cjs CHANGED
@@ -458,6 +458,19 @@ function resolveEntitySource(source, entityRow, entityPk, adapter) {
458
458
  }
459
459
  case "custom":
460
460
  return source.query(entityRow, adapter);
461
+ case "enriched": {
462
+ const enriched = { ...entityRow };
463
+ for (const [key, lookup] of Object.entries(source.include)) {
464
+ const fieldName = `_${key}`;
465
+ if (lookup.type === "custom") {
466
+ enriched[fieldName] = JSON.stringify(lookup.query(entityRow, adapter));
467
+ } else {
468
+ const resolved = resolveEntitySource(lookup, entityRow, entityPk, adapter);
469
+ enriched[fieldName] = JSON.stringify(resolved);
470
+ }
471
+ }
472
+ return [enriched];
473
+ }
461
474
  }
462
475
  }
463
476
  function truncateContent(content, budget) {
@@ -670,7 +683,8 @@ var RenderEngine = class {
670
683
  (0, import_node_fs4.mkdirSync)(entityDir, { recursive: true });
671
684
  const renderedFiles = /* @__PURE__ */ new Map();
672
685
  for (const [filename, spec] of Object.entries(def.files)) {
673
- const source = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" ? { ...def.sourceDefaults, ...spec.source } : spec.source;
686
+ const mergeDefaults = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" && spec.source.type !== "enriched";
687
+ const source = mergeDefaults ? { ...def.sourceDefaults, ...spec.source } : spec.source;
674
688
  const rows = resolveEntitySource(source, entityRow, entityPk, this._adapter);
675
689
  if (spec.omitIfEmpty && rows.length === 0) continue;
676
690
  const content = truncateContent(spec.render(rows), spec.budget);
package/dist/index.d.cts CHANGED
@@ -167,8 +167,57 @@ interface CustomSource {
167
167
  type: 'custom';
168
168
  query: (row: Row, adapter: StorageAdapter) => Row[];
169
169
  }
170
+ /**
171
+ * Sub-lookup definition for an {@link EnrichedSource}.
172
+ * Each lookup resolves related rows and attaches them to the entity row
173
+ * as a `_key` JSON string field.
174
+ *
175
+ * Declarative lookups reuse the same types as file sources (with all
176
+ * query options). Custom lookups provide full control.
177
+ */
178
+ type EnrichmentLookup = ({
179
+ as?: string;
180
+ } & Omit<HasManySource, 'type'> & {
181
+ type: 'hasMany';
182
+ }) | ({
183
+ as?: string;
184
+ } & Omit<ManyToManySource, 'type'> & {
185
+ type: 'manyToMany';
186
+ }) | ({
187
+ as?: string;
188
+ } & Omit<BelongsToSource, 'type'> & {
189
+ type: 'belongsTo';
190
+ }) | {
191
+ type: 'custom';
192
+ query: (row: Row, adapter: StorageAdapter) => Row[];
193
+ };
194
+ /**
195
+ * Start with the entity's own row (like `self`) and attach related data
196
+ * as JSON string fields. Each key in `include` becomes a `_key` field
197
+ * on the returned row, containing `JSON.stringify(resolvedRows)`.
198
+ *
199
+ * Use when a single file needs the entity's own data plus related lists
200
+ * (e.g. an org profile that includes its agents and projects).
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * source: {
205
+ * type: 'enriched',
206
+ * include: {
207
+ * agents: { type: 'hasMany', table: 'agents', foreignKey: 'org_id', softDelete: true },
208
+ * projects: { type: 'hasMany', table: 'projects', foreignKey: 'org_id', softDelete: true },
209
+ * },
210
+ * }
211
+ * // Result: [{ ...entityRow, _agents: '[...]', _projects: '[...]' }]
212
+ * ```
213
+ */
214
+ interface EnrichedSource {
215
+ type: 'enriched';
216
+ /** Named lookups whose results are attached as `_key` JSON fields. */
217
+ include: Record<string, EnrichmentLookup>;
218
+ }
170
219
  /** Union of all supported source types for {@link EntityFileSpec}. */
171
- type EntityFileSource = SelfSource | HasManySource | ManyToManySource | BelongsToSource | CustomSource;
220
+ type EntityFileSource = SelfSource | HasManySource | ManyToManySource | BelongsToSource | CustomSource | EnrichedSource;
172
221
  /**
173
222
  * Specification for a single file generated inside an entity's directory.
174
223
  *
@@ -1147,4 +1196,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
1147
1196
  */
1148
1197
  declare const READ_ONLY_HEADER: string;
1149
1198
 
1150
- export { type ApplyWriteResult, type AuditEvent, type BelongsToRelation, type BelongsToSource, type BuiltinTemplateName, type CleanupOptions, type CleanupResult, type CountOptions, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileSource, type EntityFileSpec, type Filter, type FilterOp, type HasManyRelation, type HasManySource, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type ParseError, type ParseResult, type ParsedConfig, type PkLookup, type PrimaryKey, type QueryOptions, READ_ONLY_HEADER, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type Relation, type RenderHooks, type RenderResult, type RenderSpec, type Row, type SecurityOptions, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type WatchOptions, type WritebackDefinition, applyWriteEntry, createReadOnlyHeader, frontmatter, generateEntryId, generateWriteEntryId, manifestPath, markdownTable, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
1199
+ export { type ApplyWriteResult, type AuditEvent, type BelongsToRelation, type BelongsToSource, type BuiltinTemplateName, type CleanupOptions, type CleanupResult, type CountOptions, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileSource, type EntityFileSpec, type Filter, type FilterOp, type HasManyRelation, type HasManySource, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type ParseError, type ParseResult, type ParsedConfig, type PkLookup, type PrimaryKey, type QueryOptions, READ_ONLY_HEADER, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type Relation, type RenderHooks, type RenderResult, type RenderSpec, type Row, type SecurityOptions, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type WatchOptions, type WritebackDefinition, applyWriteEntry, createReadOnlyHeader, frontmatter, generateEntryId, generateWriteEntryId, manifestPath, markdownTable, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
package/dist/index.d.ts CHANGED
@@ -167,8 +167,57 @@ interface CustomSource {
167
167
  type: 'custom';
168
168
  query: (row: Row, adapter: StorageAdapter) => Row[];
169
169
  }
170
+ /**
171
+ * Sub-lookup definition for an {@link EnrichedSource}.
172
+ * Each lookup resolves related rows and attaches them to the entity row
173
+ * as a `_key` JSON string field.
174
+ *
175
+ * Declarative lookups reuse the same types as file sources (with all
176
+ * query options). Custom lookups provide full control.
177
+ */
178
+ type EnrichmentLookup = ({
179
+ as?: string;
180
+ } & Omit<HasManySource, 'type'> & {
181
+ type: 'hasMany';
182
+ }) | ({
183
+ as?: string;
184
+ } & Omit<ManyToManySource, 'type'> & {
185
+ type: 'manyToMany';
186
+ }) | ({
187
+ as?: string;
188
+ } & Omit<BelongsToSource, 'type'> & {
189
+ type: 'belongsTo';
190
+ }) | {
191
+ type: 'custom';
192
+ query: (row: Row, adapter: StorageAdapter) => Row[];
193
+ };
194
+ /**
195
+ * Start with the entity's own row (like `self`) and attach related data
196
+ * as JSON string fields. Each key in `include` becomes a `_key` field
197
+ * on the returned row, containing `JSON.stringify(resolvedRows)`.
198
+ *
199
+ * Use when a single file needs the entity's own data plus related lists
200
+ * (e.g. an org profile that includes its agents and projects).
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * source: {
205
+ * type: 'enriched',
206
+ * include: {
207
+ * agents: { type: 'hasMany', table: 'agents', foreignKey: 'org_id', softDelete: true },
208
+ * projects: { type: 'hasMany', table: 'projects', foreignKey: 'org_id', softDelete: true },
209
+ * },
210
+ * }
211
+ * // Result: [{ ...entityRow, _agents: '[...]', _projects: '[...]' }]
212
+ * ```
213
+ */
214
+ interface EnrichedSource {
215
+ type: 'enriched';
216
+ /** Named lookups whose results are attached as `_key` JSON fields. */
217
+ include: Record<string, EnrichmentLookup>;
218
+ }
170
219
  /** Union of all supported source types for {@link EntityFileSpec}. */
171
- type EntityFileSource = SelfSource | HasManySource | ManyToManySource | BelongsToSource | CustomSource;
220
+ type EntityFileSource = SelfSource | HasManySource | ManyToManySource | BelongsToSource | CustomSource | EnrichedSource;
172
221
  /**
173
222
  * Specification for a single file generated inside an entity's directory.
174
223
  *
@@ -1147,4 +1196,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
1147
1196
  */
1148
1197
  declare const READ_ONLY_HEADER: string;
1149
1198
 
1150
- export { type ApplyWriteResult, type AuditEvent, type BelongsToRelation, type BelongsToSource, type BuiltinTemplateName, type CleanupOptions, type CleanupResult, type CountOptions, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileSource, type EntityFileSpec, type Filter, type FilterOp, type HasManyRelation, type HasManySource, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type ParseError, type ParseResult, type ParsedConfig, type PkLookup, type PrimaryKey, type QueryOptions, READ_ONLY_HEADER, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type Relation, type RenderHooks, type RenderResult, type RenderSpec, type Row, type SecurityOptions, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type WatchOptions, type WritebackDefinition, applyWriteEntry, createReadOnlyHeader, frontmatter, generateEntryId, generateWriteEntryId, manifestPath, markdownTable, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
1199
+ export { type ApplyWriteResult, type AuditEvent, type BelongsToRelation, type BelongsToSource, type BuiltinTemplateName, type CleanupOptions, type CleanupResult, type CountOptions, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileSource, type EntityFileSpec, type Filter, type FilterOp, type HasManyRelation, type HasManySource, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type ParseError, type ParseResult, type ParsedConfig, type PkLookup, type PrimaryKey, type QueryOptions, READ_ONLY_HEADER, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type Relation, type RenderHooks, type RenderResult, type RenderSpec, type Row, type SecurityOptions, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type WatchOptions, type WritebackDefinition, applyWriteEntry, createReadOnlyHeader, frontmatter, generateEntryId, generateWriteEntryId, manifestPath, markdownTable, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
package/dist/index.js CHANGED
@@ -402,6 +402,19 @@ function resolveEntitySource(source, entityRow, entityPk, adapter) {
402
402
  }
403
403
  case "custom":
404
404
  return source.query(entityRow, adapter);
405
+ case "enriched": {
406
+ const enriched = { ...entityRow };
407
+ for (const [key, lookup] of Object.entries(source.include)) {
408
+ const fieldName = `_${key}`;
409
+ if (lookup.type === "custom") {
410
+ enriched[fieldName] = JSON.stringify(lookup.query(entityRow, adapter));
411
+ } else {
412
+ const resolved = resolveEntitySource(lookup, entityRow, entityPk, adapter);
413
+ enriched[fieldName] = JSON.stringify(resolved);
414
+ }
415
+ }
416
+ return [enriched];
417
+ }
405
418
  }
406
419
  }
407
420
  function truncateContent(content, budget) {
@@ -614,7 +627,8 @@ var RenderEngine = class {
614
627
  mkdirSync2(entityDir, { recursive: true });
615
628
  const renderedFiles = /* @__PURE__ */ new Map();
616
629
  for (const [filename, spec] of Object.entries(def.files)) {
617
- const source = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" ? { ...def.sourceDefaults, ...spec.source } : spec.source;
630
+ const mergeDefaults = def.sourceDefaults && spec.source.type !== "self" && spec.source.type !== "custom" && spec.source.type !== "enriched";
631
+ const source = mergeDefaults ? { ...def.sourceDefaults, ...spec.source } : spec.source;
618
632
  const rows = resolveEntitySource(source, entityRow, entityPk, this._adapter);
619
633
  if (spec.omitIfEmpty && rows.length === 0) continue;
620
634
  const content = truncateContent(spec.render(rows), spec.budget);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latticesql",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Persistent structured memory for AI agent systems — SQLite ↔ LLM context bridge",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",