latticesql 0.9.0 → 0.10.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 +28 -0
- package/dist/index.cjs +28 -0
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +28 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1389,6 +1389,7 @@ var Lattice = class {
|
|
|
1389
1389
|
_renderHandlers = [];
|
|
1390
1390
|
_writebackHandlers = [];
|
|
1391
1391
|
_errorHandlers = [];
|
|
1392
|
+
_writeHooks = [];
|
|
1392
1393
|
constructor(pathOrConfig, options = {}) {
|
|
1393
1394
|
let dbPath;
|
|
1394
1395
|
let configTables;
|
|
@@ -1448,6 +1449,14 @@ var Lattice = class {
|
|
|
1448
1449
|
this._schema.defineEntityContext(table, def);
|
|
1449
1450
|
return this;
|
|
1450
1451
|
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Register a write hook that fires after insert/update/delete operations.
|
|
1454
|
+
* Hooks run synchronously after the DB write and audit emit.
|
|
1455
|
+
*/
|
|
1456
|
+
defineWriteHook(hook) {
|
|
1457
|
+
this._writeHooks.push(hook);
|
|
1458
|
+
return this;
|
|
1459
|
+
}
|
|
1451
1460
|
defineWriteback(def) {
|
|
1452
1461
|
this._writeback.define(def);
|
|
1453
1462
|
return this;
|
|
@@ -1497,6 +1506,7 @@ var Lattice = class {
|
|
|
1497
1506
|
const rawPk = rowWithPk[pkCol];
|
|
1498
1507
|
const pkValue = rawPk != null ? String(rawPk) : "";
|
|
1499
1508
|
this._sanitizer.emitAudit(table, "insert", pkValue);
|
|
1509
|
+
this._fireWriteHooks(table, "insert", rowWithPk, pkValue);
|
|
1500
1510
|
return Promise.resolve(pkValue);
|
|
1501
1511
|
}
|
|
1502
1512
|
upsert(table, row) {
|
|
@@ -1550,6 +1560,7 @@ var Lattice = class {
|
|
|
1550
1560
|
this._adapter.run(`UPDATE "${table}" SET ${setCols} WHERE ${clause}`, values);
|
|
1551
1561
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1552
1562
|
this._sanitizer.emitAudit(table, "update", auditId);
|
|
1563
|
+
this._fireWriteHooks(table, "update", sanitized, auditId, Object.keys(sanitized));
|
|
1553
1564
|
return Promise.resolve();
|
|
1554
1565
|
}
|
|
1555
1566
|
delete(table, id) {
|
|
@@ -1559,6 +1570,7 @@ var Lattice = class {
|
|
|
1559
1570
|
this._adapter.run(`DELETE FROM "${table}" WHERE ${clause}`, params);
|
|
1560
1571
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1561
1572
|
this._sanitizer.emitAudit(table, "delete", auditId);
|
|
1573
|
+
this._fireWriteHooks(table, "delete", { id: auditId }, auditId);
|
|
1562
1574
|
return Promise.resolve();
|
|
1563
1575
|
}
|
|
1564
1576
|
get(table, id) {
|
|
@@ -1796,6 +1808,22 @@ var Lattice = class {
|
|
|
1796
1808
|
return { clauses, params };
|
|
1797
1809
|
}
|
|
1798
1810
|
/** Returns a rejected Promise if not initialized; null if ready. */
|
|
1811
|
+
_fireWriteHooks(table, op, row, pk, changedColumns) {
|
|
1812
|
+
for (const hook of this._writeHooks) {
|
|
1813
|
+
if (hook.table !== table) continue;
|
|
1814
|
+
if (!hook.on.includes(op)) continue;
|
|
1815
|
+
if (op === "update" && hook.watchColumns && changedColumns) {
|
|
1816
|
+
if (!hook.watchColumns.some((c) => changedColumns.includes(c))) continue;
|
|
1817
|
+
}
|
|
1818
|
+
try {
|
|
1819
|
+
const ctx = { table, op, row, pk };
|
|
1820
|
+
if (changedColumns) ctx.changedColumns = changedColumns;
|
|
1821
|
+
hook.handler(ctx);
|
|
1822
|
+
} catch (err) {
|
|
1823
|
+
for (const h of this._errorHandlers) h(err instanceof Error ? err : new Error(String(err)));
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1799
1827
|
_notInitError() {
|
|
1800
1828
|
if (!this._initialized) {
|
|
1801
1829
|
return Promise.reject(
|
package/dist/index.cjs
CHANGED
|
@@ -1363,6 +1363,7 @@ var Lattice = class {
|
|
|
1363
1363
|
_renderHandlers = [];
|
|
1364
1364
|
_writebackHandlers = [];
|
|
1365
1365
|
_errorHandlers = [];
|
|
1366
|
+
_writeHooks = [];
|
|
1366
1367
|
constructor(pathOrConfig, options = {}) {
|
|
1367
1368
|
let dbPath;
|
|
1368
1369
|
let configTables;
|
|
@@ -1422,6 +1423,14 @@ var Lattice = class {
|
|
|
1422
1423
|
this._schema.defineEntityContext(table, def);
|
|
1423
1424
|
return this;
|
|
1424
1425
|
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Register a write hook that fires after insert/update/delete operations.
|
|
1428
|
+
* Hooks run synchronously after the DB write and audit emit.
|
|
1429
|
+
*/
|
|
1430
|
+
defineWriteHook(hook) {
|
|
1431
|
+
this._writeHooks.push(hook);
|
|
1432
|
+
return this;
|
|
1433
|
+
}
|
|
1425
1434
|
defineWriteback(def) {
|
|
1426
1435
|
this._writeback.define(def);
|
|
1427
1436
|
return this;
|
|
@@ -1471,6 +1480,7 @@ var Lattice = class {
|
|
|
1471
1480
|
const rawPk = rowWithPk[pkCol];
|
|
1472
1481
|
const pkValue = rawPk != null ? String(rawPk) : "";
|
|
1473
1482
|
this._sanitizer.emitAudit(table, "insert", pkValue);
|
|
1483
|
+
this._fireWriteHooks(table, "insert", rowWithPk, pkValue);
|
|
1474
1484
|
return Promise.resolve(pkValue);
|
|
1475
1485
|
}
|
|
1476
1486
|
upsert(table, row) {
|
|
@@ -1524,6 +1534,7 @@ var Lattice = class {
|
|
|
1524
1534
|
this._adapter.run(`UPDATE "${table}" SET ${setCols} WHERE ${clause}`, values);
|
|
1525
1535
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1526
1536
|
this._sanitizer.emitAudit(table, "update", auditId);
|
|
1537
|
+
this._fireWriteHooks(table, "update", sanitized, auditId, Object.keys(sanitized));
|
|
1527
1538
|
return Promise.resolve();
|
|
1528
1539
|
}
|
|
1529
1540
|
delete(table, id) {
|
|
@@ -1533,6 +1544,7 @@ var Lattice = class {
|
|
|
1533
1544
|
this._adapter.run(`DELETE FROM "${table}" WHERE ${clause}`, params);
|
|
1534
1545
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1535
1546
|
this._sanitizer.emitAudit(table, "delete", auditId);
|
|
1547
|
+
this._fireWriteHooks(table, "delete", { id: auditId }, auditId);
|
|
1536
1548
|
return Promise.resolve();
|
|
1537
1549
|
}
|
|
1538
1550
|
get(table, id) {
|
|
@@ -1770,6 +1782,22 @@ var Lattice = class {
|
|
|
1770
1782
|
return { clauses, params };
|
|
1771
1783
|
}
|
|
1772
1784
|
/** Returns a rejected Promise if not initialized; null if ready. */
|
|
1785
|
+
_fireWriteHooks(table, op, row, pk, changedColumns) {
|
|
1786
|
+
for (const hook of this._writeHooks) {
|
|
1787
|
+
if (hook.table !== table) continue;
|
|
1788
|
+
if (!hook.on.includes(op)) continue;
|
|
1789
|
+
if (op === "update" && hook.watchColumns && changedColumns) {
|
|
1790
|
+
if (!hook.watchColumns.some((c) => changedColumns.includes(c))) continue;
|
|
1791
|
+
}
|
|
1792
|
+
try {
|
|
1793
|
+
const ctx = { table, op, row, pk };
|
|
1794
|
+
if (changedColumns) ctx.changedColumns = changedColumns;
|
|
1795
|
+
hook.handler(ctx);
|
|
1796
|
+
} catch (err) {
|
|
1797
|
+
for (const h of this._errorHandlers) h(err instanceof Error ? err : new Error(String(err)));
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1773
1801
|
_notInitError() {
|
|
1774
1802
|
if (!this._initialized) {
|
|
1775
1803
|
return Promise.reject(
|
package/dist/index.d.cts
CHANGED
|
@@ -749,6 +749,45 @@ interface AuditEvent {
|
|
|
749
749
|
id: string;
|
|
750
750
|
timestamp: string;
|
|
751
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* Context passed to write hook handlers.
|
|
754
|
+
*/
|
|
755
|
+
interface WriteHookContext {
|
|
756
|
+
/** Table that was modified. */
|
|
757
|
+
table: string;
|
|
758
|
+
/** The operation that triggered the hook. */
|
|
759
|
+
op: 'insert' | 'update' | 'delete';
|
|
760
|
+
/** The row data (for insert: full row; for update: changed fields; for delete: { id }). */
|
|
761
|
+
row: Row;
|
|
762
|
+
/** Primary key value(s) of the affected row. */
|
|
763
|
+
pk: string;
|
|
764
|
+
/** For updates: the column names that were changed. */
|
|
765
|
+
changedColumns?: string[];
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* A write hook fires after insert/update/delete operations.
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```ts
|
|
772
|
+
* db.defineWriteHook({
|
|
773
|
+
* table: 'agents',
|
|
774
|
+
* on: ['insert', 'update'],
|
|
775
|
+
* watchColumns: ['team_id'],
|
|
776
|
+
* handler: (ctx) => { denormalizeTeamFields(ctx.pk); },
|
|
777
|
+
* });
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
780
|
+
interface WriteHook {
|
|
781
|
+
/** Table the hook fires on. */
|
|
782
|
+
table: string;
|
|
783
|
+
/** Operations that trigger the hook. */
|
|
784
|
+
on: Array<'insert' | 'update' | 'delete'>;
|
|
785
|
+
/** Only fire on update when these columns changed. Omit = fire on any change. */
|
|
786
|
+
watchColumns?: string[];
|
|
787
|
+
/** Handler function. Runs synchronously after the DB write. */
|
|
788
|
+
handler: (ctx: WriteHookContext) => void;
|
|
789
|
+
}
|
|
790
|
+
|
|
752
791
|
interface ReconcileOptions {
|
|
753
792
|
/** Remove entity directories whose slug is no longer in the DB. Default: true. */
|
|
754
793
|
removeOrphanedDirectories?: boolean;
|
|
@@ -801,10 +840,16 @@ declare class Lattice {
|
|
|
801
840
|
private readonly _renderHandlers;
|
|
802
841
|
private readonly _writebackHandlers;
|
|
803
842
|
private readonly _errorHandlers;
|
|
843
|
+
private readonly _writeHooks;
|
|
804
844
|
constructor(pathOrConfig: string | LatticeConfigInput, options?: LatticeOptions);
|
|
805
845
|
define(table: string, def: TableDefinition): this;
|
|
806
846
|
defineMulti(name: string, def: MultiTableDefinition): this;
|
|
807
847
|
defineEntityContext(table: string, def: EntityContextDefinition): this;
|
|
848
|
+
/**
|
|
849
|
+
* Register a write hook that fires after insert/update/delete operations.
|
|
850
|
+
* Hooks run synchronously after the DB write and audit emit.
|
|
851
|
+
*/
|
|
852
|
+
defineWriteHook(hook: WriteHook): this;
|
|
808
853
|
defineWriteback(def: WritebackDefinition): this;
|
|
809
854
|
init(options?: InitOptions): Promise<void>;
|
|
810
855
|
close(): void;
|
|
@@ -850,6 +895,7 @@ declare class Lattice {
|
|
|
850
895
|
*/
|
|
851
896
|
private _buildFilters;
|
|
852
897
|
/** Returns a rejected Promise if not initialized; null if ready. */
|
|
898
|
+
private _fireWriteHooks;
|
|
853
899
|
private _notInitError;
|
|
854
900
|
/**
|
|
855
901
|
* Returns a rejected Promise if any of the given column names are not present
|
|
@@ -1305,4 +1351,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
|
|
|
1305
1351
|
*/
|
|
1306
1352
|
declare const READ_ONLY_HEADER: string;
|
|
1307
1353
|
|
|
1308
|
-
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 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, 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 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 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 };
|
|
1354
|
+
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 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, 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 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 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 WriteHook, type WriteHookContext, 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
|
@@ -749,6 +749,45 @@ interface AuditEvent {
|
|
|
749
749
|
id: string;
|
|
750
750
|
timestamp: string;
|
|
751
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* Context passed to write hook handlers.
|
|
754
|
+
*/
|
|
755
|
+
interface WriteHookContext {
|
|
756
|
+
/** Table that was modified. */
|
|
757
|
+
table: string;
|
|
758
|
+
/** The operation that triggered the hook. */
|
|
759
|
+
op: 'insert' | 'update' | 'delete';
|
|
760
|
+
/** The row data (for insert: full row; for update: changed fields; for delete: { id }). */
|
|
761
|
+
row: Row;
|
|
762
|
+
/** Primary key value(s) of the affected row. */
|
|
763
|
+
pk: string;
|
|
764
|
+
/** For updates: the column names that were changed. */
|
|
765
|
+
changedColumns?: string[];
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* A write hook fires after insert/update/delete operations.
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```ts
|
|
772
|
+
* db.defineWriteHook({
|
|
773
|
+
* table: 'agents',
|
|
774
|
+
* on: ['insert', 'update'],
|
|
775
|
+
* watchColumns: ['team_id'],
|
|
776
|
+
* handler: (ctx) => { denormalizeTeamFields(ctx.pk); },
|
|
777
|
+
* });
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
780
|
+
interface WriteHook {
|
|
781
|
+
/** Table the hook fires on. */
|
|
782
|
+
table: string;
|
|
783
|
+
/** Operations that trigger the hook. */
|
|
784
|
+
on: Array<'insert' | 'update' | 'delete'>;
|
|
785
|
+
/** Only fire on update when these columns changed. Omit = fire on any change. */
|
|
786
|
+
watchColumns?: string[];
|
|
787
|
+
/** Handler function. Runs synchronously after the DB write. */
|
|
788
|
+
handler: (ctx: WriteHookContext) => void;
|
|
789
|
+
}
|
|
790
|
+
|
|
752
791
|
interface ReconcileOptions {
|
|
753
792
|
/** Remove entity directories whose slug is no longer in the DB. Default: true. */
|
|
754
793
|
removeOrphanedDirectories?: boolean;
|
|
@@ -801,10 +840,16 @@ declare class Lattice {
|
|
|
801
840
|
private readonly _renderHandlers;
|
|
802
841
|
private readonly _writebackHandlers;
|
|
803
842
|
private readonly _errorHandlers;
|
|
843
|
+
private readonly _writeHooks;
|
|
804
844
|
constructor(pathOrConfig: string | LatticeConfigInput, options?: LatticeOptions);
|
|
805
845
|
define(table: string, def: TableDefinition): this;
|
|
806
846
|
defineMulti(name: string, def: MultiTableDefinition): this;
|
|
807
847
|
defineEntityContext(table: string, def: EntityContextDefinition): this;
|
|
848
|
+
/**
|
|
849
|
+
* Register a write hook that fires after insert/update/delete operations.
|
|
850
|
+
* Hooks run synchronously after the DB write and audit emit.
|
|
851
|
+
*/
|
|
852
|
+
defineWriteHook(hook: WriteHook): this;
|
|
808
853
|
defineWriteback(def: WritebackDefinition): this;
|
|
809
854
|
init(options?: InitOptions): Promise<void>;
|
|
810
855
|
close(): void;
|
|
@@ -850,6 +895,7 @@ declare class Lattice {
|
|
|
850
895
|
*/
|
|
851
896
|
private _buildFilters;
|
|
852
897
|
/** Returns a rejected Promise if not initialized; null if ready. */
|
|
898
|
+
private _fireWriteHooks;
|
|
853
899
|
private _notInitError;
|
|
854
900
|
/**
|
|
855
901
|
* Returns a rejected Promise if any of the given column names are not present
|
|
@@ -1305,4 +1351,4 @@ declare function createReadOnlyHeader(options?: ReadOnlyHeaderOptions): string;
|
|
|
1305
1351
|
*/
|
|
1306
1352
|
declare const READ_ONLY_HEADER: string;
|
|
1307
1353
|
|
|
1308
|
-
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 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, 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 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 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 };
|
|
1354
|
+
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 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, 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 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 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 WriteHook, type WriteHookContext, type WritebackDefinition, applyWriteEntry, createReadOnlyHeader, frontmatter, generateEntryId, generateWriteEntryId, manifestPath, markdownTable, parseConfigFile, parseConfigString, parseMarkdownEntries, parseSessionMD, parseSessionWrites, readManifest, slugify, truncate, validateEntryId, writeManifest };
|
package/dist/index.js
CHANGED
|
@@ -1307,6 +1307,7 @@ var Lattice = class {
|
|
|
1307
1307
|
_renderHandlers = [];
|
|
1308
1308
|
_writebackHandlers = [];
|
|
1309
1309
|
_errorHandlers = [];
|
|
1310
|
+
_writeHooks = [];
|
|
1310
1311
|
constructor(pathOrConfig, options = {}) {
|
|
1311
1312
|
let dbPath;
|
|
1312
1313
|
let configTables;
|
|
@@ -1366,6 +1367,14 @@ var Lattice = class {
|
|
|
1366
1367
|
this._schema.defineEntityContext(table, def);
|
|
1367
1368
|
return this;
|
|
1368
1369
|
}
|
|
1370
|
+
/**
|
|
1371
|
+
* Register a write hook that fires after insert/update/delete operations.
|
|
1372
|
+
* Hooks run synchronously after the DB write and audit emit.
|
|
1373
|
+
*/
|
|
1374
|
+
defineWriteHook(hook) {
|
|
1375
|
+
this._writeHooks.push(hook);
|
|
1376
|
+
return this;
|
|
1377
|
+
}
|
|
1369
1378
|
defineWriteback(def) {
|
|
1370
1379
|
this._writeback.define(def);
|
|
1371
1380
|
return this;
|
|
@@ -1415,6 +1424,7 @@ var Lattice = class {
|
|
|
1415
1424
|
const rawPk = rowWithPk[pkCol];
|
|
1416
1425
|
const pkValue = rawPk != null ? String(rawPk) : "";
|
|
1417
1426
|
this._sanitizer.emitAudit(table, "insert", pkValue);
|
|
1427
|
+
this._fireWriteHooks(table, "insert", rowWithPk, pkValue);
|
|
1418
1428
|
return Promise.resolve(pkValue);
|
|
1419
1429
|
}
|
|
1420
1430
|
upsert(table, row) {
|
|
@@ -1468,6 +1478,7 @@ var Lattice = class {
|
|
|
1468
1478
|
this._adapter.run(`UPDATE "${table}" SET ${setCols} WHERE ${clause}`, values);
|
|
1469
1479
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1470
1480
|
this._sanitizer.emitAudit(table, "update", auditId);
|
|
1481
|
+
this._fireWriteHooks(table, "update", sanitized, auditId, Object.keys(sanitized));
|
|
1471
1482
|
return Promise.resolve();
|
|
1472
1483
|
}
|
|
1473
1484
|
delete(table, id) {
|
|
@@ -1477,6 +1488,7 @@ var Lattice = class {
|
|
|
1477
1488
|
this._adapter.run(`DELETE FROM "${table}" WHERE ${clause}`, params);
|
|
1478
1489
|
const auditId = typeof id === "string" ? id : JSON.stringify(id);
|
|
1479
1490
|
this._sanitizer.emitAudit(table, "delete", auditId);
|
|
1491
|
+
this._fireWriteHooks(table, "delete", { id: auditId }, auditId);
|
|
1480
1492
|
return Promise.resolve();
|
|
1481
1493
|
}
|
|
1482
1494
|
get(table, id) {
|
|
@@ -1714,6 +1726,22 @@ var Lattice = class {
|
|
|
1714
1726
|
return { clauses, params };
|
|
1715
1727
|
}
|
|
1716
1728
|
/** Returns a rejected Promise if not initialized; null if ready. */
|
|
1729
|
+
_fireWriteHooks(table, op, row, pk, changedColumns) {
|
|
1730
|
+
for (const hook of this._writeHooks) {
|
|
1731
|
+
if (hook.table !== table) continue;
|
|
1732
|
+
if (!hook.on.includes(op)) continue;
|
|
1733
|
+
if (op === "update" && hook.watchColumns && changedColumns) {
|
|
1734
|
+
if (!hook.watchColumns.some((c) => changedColumns.includes(c))) continue;
|
|
1735
|
+
}
|
|
1736
|
+
try {
|
|
1737
|
+
const ctx = { table, op, row, pk };
|
|
1738
|
+
if (changedColumns) ctx.changedColumns = changedColumns;
|
|
1739
|
+
hook.handler(ctx);
|
|
1740
|
+
} catch (err) {
|
|
1741
|
+
for (const h of this._errorHandlers) h(err instanceof Error ? err : new Error(String(err)));
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1717
1745
|
_notInitError() {
|
|
1718
1746
|
if (!this._initialized) {
|
|
1719
1747
|
return Promise.reject(
|