latticesql 0.18.1 → 0.18.2

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/index.cjs CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  deriveKey: () => deriveKey,
44
44
  encrypt: () => encrypt,
45
45
  entityFileNames: () => entityFileNames,
46
+ fixSchemaConflicts: () => fixSchemaConflicts,
46
47
  frontmatter: () => frontmatter,
47
48
  generateEntryId: () => generateEntryId,
48
49
  generateWriteEntryId: () => generateWriteEntryId,
@@ -2648,6 +2649,39 @@ var Lattice = class {
2648
2649
  }
2649
2650
  };
2650
2651
 
2652
+ // src/lifecycle/pre-init.ts
2653
+ function fixSchemaConflicts(db, checks) {
2654
+ for (const { table, requiredColumns } of checks) {
2655
+ if (!tableExists(db, table)) continue;
2656
+ const cols = getColumns(db, table);
2657
+ const missing = requiredColumns.filter((c) => !cols.includes(c));
2658
+ if (missing.length > 0) {
2659
+ renameTable(db, table);
2660
+ }
2661
+ }
2662
+ if (tableExists(db, "__lattice_migrations")) {
2663
+ const versionCol = db.prepare('PRAGMA table_info("__lattice_migrations")').all().find((c) => c.name === "version");
2664
+ if (versionCol && versionCol.type.toUpperCase().includes("INTEGER")) {
2665
+ db.exec(
2666
+ 'ALTER TABLE "__lattice_migrations" RENAME TO "__lattice_migrations_v1"'
2667
+ );
2668
+ }
2669
+ }
2670
+ }
2671
+ function tableExists(db, name) {
2672
+ return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(name);
2673
+ }
2674
+ function getColumns(db, table) {
2675
+ return db.prepare(`PRAGMA table_info("${table}")`).all().map((c) => c.name);
2676
+ }
2677
+ function renameTable(db, table) {
2678
+ const target = `_legacy_${table}`;
2679
+ if (tableExists(db, target)) {
2680
+ db.exec(`DROP TABLE "${target}"`);
2681
+ }
2682
+ db.exec(`ALTER TABLE "${table}" RENAME TO "${target}"`);
2683
+ }
2684
+
2651
2685
  // src/session/parser.ts
2652
2686
  var import_node_crypto4 = require("crypto");
2653
2687
  function generateWriteEntryId(timestamp, agentName, op, table, target) {
@@ -2994,8 +3028,8 @@ function applyWriteEntry(db, entry) {
2994
3028
  if (!TABLE_NAME_RE2.test(table)) {
2995
3029
  return { ok: false, reason: `Invalid table name: "${table}". Only [a-zA-Z0-9_] allowed` };
2996
3030
  }
2997
- const tableExists = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table);
2998
- if (!tableExists) {
3031
+ const tableExists2 = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table);
3032
+ if (!tableExists2) {
2999
3033
  return { ok: false, reason: `Unknown table: "${table}"` };
3000
3034
  }
3001
3035
  const columnRows = db.prepare(`PRAGMA table_info("${table}")`).all();
@@ -3065,6 +3099,7 @@ function applyWriteEntry(db, entry) {
3065
3099
  deriveKey,
3066
3100
  encrypt,
3067
3101
  entityFileNames,
3102
+ fixSchemaConflicts,
3068
3103
  frontmatter,
3069
3104
  generateEntryId,
3070
3105
  generateWriteEntryId,
package/dist/index.d.cts CHANGED
@@ -1494,6 +1494,38 @@ declare function parseConfigString(yamlContent: string, configDir: string): Pars
1494
1494
 
1495
1495
  declare function contentHash(content: string): string;
1496
1496
 
1497
+ /**
1498
+ * Fix legacy schema conflicts before Lattice init().
1499
+ *
1500
+ * When upgrading from an older schema version, existing tables may have
1501
+ * incompatible column definitions (e.g., a column with PRIMARY KEY that
1502
+ * new code tries to add via ALTER TABLE, which SQLite doesn't support).
1503
+ *
1504
+ * This utility renames conflicting tables to `_legacy_{name}` so init()
1505
+ * can create fresh tables with the new schema.
1506
+ *
1507
+ * @param db - An open better-sqlite3 database instance
1508
+ * @param checks - Array of { table, requiredColumns } to verify
1509
+ *
1510
+ * @example
1511
+ * ```ts
1512
+ * import Database from 'better-sqlite3';
1513
+ * import { fixSchemaConflicts } from 'latticesql';
1514
+ *
1515
+ * const db = new Database('./app.db');
1516
+ * fixSchemaConflicts(db, [
1517
+ * { table: 'sessions', requiredColumns: ['id'] },
1518
+ * { table: 'messages', requiredColumns: ['id'] },
1519
+ * ]);
1520
+ * db.close();
1521
+ * // Now safe to call lattice.init()
1522
+ * ```
1523
+ */
1524
+ declare function fixSchemaConflicts(db: Database.Database, checks: Array<{
1525
+ table: string;
1526
+ requiredColumns: string[];
1527
+ }>): void;
1528
+
1497
1529
  /**
1498
1530
  * Derive a 256-bit AES key from a master password using scrypt.
1499
1531
  * The salt is fixed per Lattice instance — callers should use a unique
@@ -1760,4 +1792,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
1760
1792
  */
1761
1793
  declare const READ_ONLY_HEADER: string;
1762
1794
 
1763
- 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 EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type Filter, type FilterOp, type HasManyRelation, type HasManySource, InMemoryStateStore, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type OrderBySpec, 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 ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type Row, type SecurityOptions, type SeedConfig, type SeedLinkSpec, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type UpsertByNaturalKeyOptions, type WatchOptions, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, applyWriteEntry, contentHash, createReadOnlyHeader, createSQLiteStateStore, decrypt, deriveKey, encrypt, entityFileNames, frontmatter, generateEntryId, generateWriteEntryId, isEncrypted, isV1EntityFiles, manifestPath, markdownTable, normalizeEntityFiles, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
1795
+ 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 EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type Filter, type FilterOp, type HasManyRelation, type HasManySource, InMemoryStateStore, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type OrderBySpec, 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 ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type Row, type SecurityOptions, type SeedConfig, type SeedLinkSpec, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type UpsertByNaturalKeyOptions, type WatchOptions, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, applyWriteEntry, contentHash, createReadOnlyHeader, createSQLiteStateStore, decrypt, deriveKey, encrypt, entityFileNames, fixSchemaConflicts, frontmatter, generateEntryId, generateWriteEntryId, isEncrypted, isV1EntityFiles, manifestPath, markdownTable, normalizeEntityFiles, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
package/dist/index.d.ts CHANGED
@@ -1494,6 +1494,38 @@ declare function parseConfigString(yamlContent: string, configDir: string): Pars
1494
1494
 
1495
1495
  declare function contentHash(content: string): string;
1496
1496
 
1497
+ /**
1498
+ * Fix legacy schema conflicts before Lattice init().
1499
+ *
1500
+ * When upgrading from an older schema version, existing tables may have
1501
+ * incompatible column definitions (e.g., a column with PRIMARY KEY that
1502
+ * new code tries to add via ALTER TABLE, which SQLite doesn't support).
1503
+ *
1504
+ * This utility renames conflicting tables to `_legacy_{name}` so init()
1505
+ * can create fresh tables with the new schema.
1506
+ *
1507
+ * @param db - An open better-sqlite3 database instance
1508
+ * @param checks - Array of { table, requiredColumns } to verify
1509
+ *
1510
+ * @example
1511
+ * ```ts
1512
+ * import Database from 'better-sqlite3';
1513
+ * import { fixSchemaConflicts } from 'latticesql';
1514
+ *
1515
+ * const db = new Database('./app.db');
1516
+ * fixSchemaConflicts(db, [
1517
+ * { table: 'sessions', requiredColumns: ['id'] },
1518
+ * { table: 'messages', requiredColumns: ['id'] },
1519
+ * ]);
1520
+ * db.close();
1521
+ * // Now safe to call lattice.init()
1522
+ * ```
1523
+ */
1524
+ declare function fixSchemaConflicts(db: Database.Database, checks: Array<{
1525
+ table: string;
1526
+ requiredColumns: string[];
1527
+ }>): void;
1528
+
1497
1529
  /**
1498
1530
  * Derive a 256-bit AES key from a master password using scrypt.
1499
1531
  * The salt is fixed per Lattice instance — callers should use a unique
@@ -1760,4 +1792,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
1760
1792
  */
1761
1793
  declare const READ_ONLY_HEADER: string;
1762
1794
 
1763
- 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 EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type Filter, type FilterOp, type HasManyRelation, type HasManySource, InMemoryStateStore, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type OrderBySpec, 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 ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type Row, type SecurityOptions, type SeedConfig, type SeedLinkSpec, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type UpsertByNaturalKeyOptions, type WatchOptions, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, applyWriteEntry, contentHash, createReadOnlyHeader, createSQLiteStateStore, decrypt, deriveKey, encrypt, entityFileNames, frontmatter, generateEntryId, generateWriteEntryId, isEncrypted, isV1EntityFiles, manifestPath, markdownTable, normalizeEntityFiles, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
1795
+ 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 EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type Filter, type FilterOp, type HasManyRelation, type HasManySource, InMemoryStateStore, type InitOptions, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type ManyToManySource, type MarkdownTableColumn, type Migration, type MultiTableDefinition, type OrderBySpec, 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 ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type Row, type SecurityOptions, type SeedConfig, type SeedLinkSpec, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceQueryOptions, type StopFn, type SyncResult, type TableDefinition, type TemplateRenderSpec, type UpsertByNaturalKeyOptions, type WatchOptions, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, applyWriteEntry, contentHash, createReadOnlyHeader, createSQLiteStateStore, decrypt, deriveKey, encrypt, entityFileNames, fixSchemaConflicts, frontmatter, generateEntryId, generateWriteEntryId, isEncrypted, isV1EntityFiles, manifestPath, markdownTable, normalizeEntityFiles, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
package/dist/index.js CHANGED
@@ -2582,6 +2582,39 @@ var Lattice = class {
2582
2582
  }
2583
2583
  };
2584
2584
 
2585
+ // src/lifecycle/pre-init.ts
2586
+ function fixSchemaConflicts(db, checks) {
2587
+ for (const { table, requiredColumns } of checks) {
2588
+ if (!tableExists(db, table)) continue;
2589
+ const cols = getColumns(db, table);
2590
+ const missing = requiredColumns.filter((c) => !cols.includes(c));
2591
+ if (missing.length > 0) {
2592
+ renameTable(db, table);
2593
+ }
2594
+ }
2595
+ if (tableExists(db, "__lattice_migrations")) {
2596
+ const versionCol = db.prepare('PRAGMA table_info("__lattice_migrations")').all().find((c) => c.name === "version");
2597
+ if (versionCol && versionCol.type.toUpperCase().includes("INTEGER")) {
2598
+ db.exec(
2599
+ 'ALTER TABLE "__lattice_migrations" RENAME TO "__lattice_migrations_v1"'
2600
+ );
2601
+ }
2602
+ }
2603
+ }
2604
+ function tableExists(db, name) {
2605
+ return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(name);
2606
+ }
2607
+ function getColumns(db, table) {
2608
+ return db.prepare(`PRAGMA table_info("${table}")`).all().map((c) => c.name);
2609
+ }
2610
+ function renameTable(db, table) {
2611
+ const target = `_legacy_${table}`;
2612
+ if (tableExists(db, target)) {
2613
+ db.exec(`DROP TABLE "${target}"`);
2614
+ }
2615
+ db.exec(`ALTER TABLE "${table}" RENAME TO "${target}"`);
2616
+ }
2617
+
2585
2618
  // src/session/parser.ts
2586
2619
  import { createHash as createHash2 } from "crypto";
2587
2620
  function generateWriteEntryId(timestamp, agentName, op, table, target) {
@@ -2928,8 +2961,8 @@ function applyWriteEntry(db, entry) {
2928
2961
  if (!TABLE_NAME_RE2.test(table)) {
2929
2962
  return { ok: false, reason: `Invalid table name: "${table}". Only [a-zA-Z0-9_] allowed` };
2930
2963
  }
2931
- const tableExists = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table);
2932
- if (!tableExists) {
2964
+ const tableExists2 = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table);
2965
+ if (!tableExists2) {
2933
2966
  return { ok: false, reason: `Unknown table: "${table}"` };
2934
2967
  }
2935
2968
  const columnRows = db.prepare(`PRAGMA table_info("${table}")`).all();
@@ -2998,6 +3031,7 @@ export {
2998
3031
  deriveKey,
2999
3032
  encrypt,
3000
3033
  entityFileNames,
3034
+ fixSchemaConflicts,
3001
3035
  frontmatter,
3002
3036
  generateEntryId,
3003
3037
  generateWriteEntryId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latticesql",
3
- "version": "0.18.1",
3
+ "version": "0.18.2",
4
4
  "description": "Persistent structured memory for AI agent systems — SQLite ↔ LLM context bridge",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",