@axiom-lattice/pg-stores 1.0.13 → 1.0.14

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.js CHANGED
@@ -22,13 +22,19 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  MigrationManager: () => MigrationManager,
24
24
  PostgreSQLAssistantStore: () => PostgreSQLAssistantStore,
25
+ PostgreSQLDatabaseConfigStore: () => PostgreSQLDatabaseConfigStore,
26
+ PostgreSQLProjectStore: () => PostgreSQLProjectStore,
25
27
  PostgreSQLScheduleStorage: () => PostgreSQLScheduleStorage,
26
28
  PostgreSQLSkillStore: () => PostgreSQLSkillStore,
27
29
  PostgreSQLThreadStore: () => PostgreSQLThreadStore,
30
+ PostgreSQLWorkspaceStore: () => PostgreSQLWorkspaceStore,
28
31
  createAssistantsTable: () => createAssistantsTable,
32
+ createDatabaseConfigsTable: () => createDatabaseConfigsTable,
33
+ createProjectsTable: () => createProjectsTable,
29
34
  createScheduledTasksTable: () => createScheduledTasksTable,
30
35
  createSkillsTable: () => createSkillsTable,
31
- createThreadsTable: () => createThreadsTable
36
+ createThreadsTable: () => createThreadsTable,
37
+ createWorkspacesTable: () => createWorkspacesTable
32
38
  });
33
39
  module.exports = __toCommonJS(index_exports);
34
40
 
@@ -1506,16 +1512,767 @@ var PostgreSQLSkillStore = class {
1506
1512
  return result.rows.map(this.mapRowToSkill);
1507
1513
  }
1508
1514
  };
1515
+
1516
+ // src/stores/PostgreSQLDatabaseConfigStore.ts
1517
+ var import_pg5 = require("pg");
1518
+
1519
+ // src/migrations/database_config_migrations.ts
1520
+ var createDatabaseConfigsTable = {
1521
+ version: 4,
1522
+ name: "create_database_configs_table",
1523
+ up: async (client) => {
1524
+ await client.query(`
1525
+ CREATE TABLE IF NOT EXISTS lattice_database_configs (
1526
+ id VARCHAR(255) NOT NULL,
1527
+ tenant_id VARCHAR(255) NOT NULL,
1528
+ key VARCHAR(255) NOT NULL,
1529
+ name VARCHAR(255),
1530
+ description TEXT,
1531
+ config JSONB NOT NULL,
1532
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
1533
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
1534
+
1535
+ PRIMARY KEY (tenant_id, id),
1536
+ CONSTRAINT uk_lattice_database_configs_tenant_key UNIQUE (tenant_id, key)
1537
+ )
1538
+ `);
1539
+ await client.query(`
1540
+ CREATE INDEX IF NOT EXISTS idx_lattice_database_configs_tenant_id
1541
+ ON lattice_database_configs(tenant_id)
1542
+ `);
1543
+ await client.query(`
1544
+ CREATE INDEX IF NOT EXISTS idx_lattice_database_configs_key
1545
+ ON lattice_database_configs(key)
1546
+ `);
1547
+ },
1548
+ down: async (client) => {
1549
+ await client.query("DROP INDEX IF EXISTS idx_lattice_database_configs_key");
1550
+ await client.query("DROP INDEX IF EXISTS idx_lattice_database_configs_tenant_id");
1551
+ await client.query("DROP TABLE IF EXISTS lattice_database_configs");
1552
+ }
1553
+ };
1554
+
1555
+ // src/stores/PostgreSQLDatabaseConfigStore.ts
1556
+ var import_core = require("@axiom-lattice/core");
1557
+ var PostgreSQLDatabaseConfigStore = class {
1558
+ constructor(options) {
1559
+ this.initialized = false;
1560
+ this.initPromise = null;
1561
+ if (typeof options.poolConfig === "string") {
1562
+ this.pool = new import_pg5.Pool({ connectionString: options.poolConfig });
1563
+ } else {
1564
+ this.pool = new import_pg5.Pool(options.poolConfig);
1565
+ }
1566
+ this.migrationManager = new MigrationManager(this.pool);
1567
+ this.migrationManager.register(createDatabaseConfigsTable);
1568
+ if (options.autoMigrate !== false) {
1569
+ this.initialize().catch((error) => {
1570
+ console.error("Failed to initialize PostgreSQLDatabaseConfigStore:", error);
1571
+ throw error;
1572
+ });
1573
+ }
1574
+ }
1575
+ /**
1576
+ * Initialize the store and run migrations
1577
+ * Uses a promise-based lock to prevent concurrent initialization
1578
+ */
1579
+ async initialize() {
1580
+ if (this.initialized) {
1581
+ return;
1582
+ }
1583
+ if (this.initPromise) {
1584
+ return this.initPromise;
1585
+ }
1586
+ this.initPromise = (async () => {
1587
+ try {
1588
+ await this.migrationManager.migrate();
1589
+ this.initialized = true;
1590
+ } finally {
1591
+ this.initPromise = null;
1592
+ }
1593
+ })();
1594
+ return this.initPromise;
1595
+ }
1596
+ /**
1597
+ * Get all database configurations for a tenant
1598
+ */
1599
+ async getAllConfigs(tenantId) {
1600
+ await this.ensureInitialized();
1601
+ const result = await this.pool.query(
1602
+ `
1603
+ SELECT id, tenant_id, key, name, description, config, created_at, updated_at
1604
+ FROM lattice_database_configs
1605
+ WHERE tenant_id = $1
1606
+ ORDER BY created_at DESC
1607
+ `,
1608
+ [tenantId]
1609
+ );
1610
+ return result.rows.map((row) => this.mapRowToEntry(row));
1611
+ }
1612
+ /**
1613
+ * Get all database configurations across all tenants
1614
+ */
1615
+ async getAllConfigsWithoutTenant() {
1616
+ await this.ensureInitialized();
1617
+ const result = await this.pool.query(
1618
+ `
1619
+ SELECT id, tenant_id, key, name, description, config, created_at, updated_at
1620
+ FROM lattice_database_configs
1621
+ ORDER BY created_at DESC
1622
+ `
1623
+ );
1624
+ return result.rows.map((row) => this.mapRowToEntry(row));
1625
+ }
1626
+ /**
1627
+ * Get database configuration by ID
1628
+ */
1629
+ async getConfigById(tenantId, id) {
1630
+ await this.ensureInitialized();
1631
+ const result = await this.pool.query(
1632
+ `
1633
+ SELECT id, tenant_id, key, name, description, config, created_at, updated_at
1634
+ FROM lattice_database_configs
1635
+ WHERE tenant_id = $1 AND id = $2
1636
+ `,
1637
+ [tenantId, id]
1638
+ );
1639
+ if (result.rows.length === 0) {
1640
+ return null;
1641
+ }
1642
+ return this.mapRowToEntry(result.rows[0]);
1643
+ }
1644
+ /**
1645
+ * Get database configuration by business key
1646
+ */
1647
+ async getConfigByKey(tenantId, key) {
1648
+ await this.ensureInitialized();
1649
+ const result = await this.pool.query(
1650
+ `
1651
+ SELECT id, tenant_id, key, name, description, config, created_at, updated_at
1652
+ FROM lattice_database_configs
1653
+ WHERE tenant_id = $1 AND key = $2
1654
+ `,
1655
+ [tenantId, key]
1656
+ );
1657
+ if (result.rows.length === 0) {
1658
+ return null;
1659
+ }
1660
+ return this.mapRowToEntry(result.rows[0]);
1661
+ }
1662
+ /**
1663
+ * Create a new database configuration
1664
+ */
1665
+ async createConfig(tenantId, id, data) {
1666
+ await this.ensureInitialized();
1667
+ const now = /* @__PURE__ */ new Date();
1668
+ const nowString = now.toISOString();
1669
+ const configWithEncryptedPassword = this.encryptPasswordInConfig(data.config);
1670
+ await this.pool.query(
1671
+ `
1672
+ INSERT INTO lattice_database_configs (id, tenant_id, key, name, description, config, created_at, updated_at)
1673
+ VALUES ($1, $2, $3, $4, $5, $6, $7::timestamp, $8::timestamp)
1674
+ ON CONFLICT (tenant_id, id) DO UPDATE SET
1675
+ key = EXCLUDED.key,
1676
+ name = EXCLUDED.name,
1677
+ description = EXCLUDED.description,
1678
+ config = EXCLUDED.config,
1679
+ updated_at = EXCLUDED.updated_at
1680
+ `,
1681
+ [
1682
+ id,
1683
+ tenantId,
1684
+ data.key,
1685
+ data.name || null,
1686
+ data.description || null,
1687
+ JSON.stringify(configWithEncryptedPassword),
1688
+ nowString,
1689
+ nowString
1690
+ ]
1691
+ );
1692
+ return {
1693
+ id,
1694
+ tenantId,
1695
+ key: data.key,
1696
+ config: data.config,
1697
+ name: data.name,
1698
+ description: data.description,
1699
+ createdAt: now,
1700
+ updatedAt: now
1701
+ };
1702
+ }
1703
+ /**
1704
+ * Update an existing database configuration
1705
+ */
1706
+ async updateConfig(tenantId, id, updates) {
1707
+ await this.ensureInitialized();
1708
+ const existing = await this.getConfigById(tenantId, id);
1709
+ if (!existing) {
1710
+ return null;
1711
+ }
1712
+ const updateData = {};
1713
+ if (updates.key !== void 0) {
1714
+ updateData.key = updates.key;
1715
+ }
1716
+ if (updates.name !== void 0) {
1717
+ updateData.name = updates.name || null;
1718
+ }
1719
+ if (updates.description !== void 0) {
1720
+ updateData.description = updates.description || null;
1721
+ }
1722
+ if (updates.config !== void 0) {
1723
+ const configWithEncryptedPassword = this.encryptPasswordInConfig(updates.config);
1724
+ updateData.config = JSON.stringify(configWithEncryptedPassword);
1725
+ }
1726
+ if (Object.keys(updateData).length === 0) {
1727
+ return existing;
1728
+ }
1729
+ updateData.updated_at = (/* @__PURE__ */ new Date()).toISOString();
1730
+ const fields = Object.keys(updateData);
1731
+ const values = Object.values(updateData);
1732
+ values.push(tenantId);
1733
+ values.push(id);
1734
+ const setClauses = fields.map((field, index) => {
1735
+ if (field === "updated_at") {
1736
+ return `${field} = $${index + 1}::timestamp`;
1737
+ }
1738
+ return `${field} = $${index + 1}`;
1739
+ });
1740
+ const whereTenantIndex = fields.length + 1;
1741
+ const whereIdIndex = fields.length + 2;
1742
+ const sql = `
1743
+ UPDATE lattice_database_configs
1744
+ SET ${setClauses.join(", ")}
1745
+ WHERE tenant_id = $${whereTenantIndex} AND id = $${whereIdIndex}
1746
+ `;
1747
+ await this.pool.query(sql, values);
1748
+ return await this.getConfigById(tenantId, id);
1749
+ }
1750
+ /**
1751
+ * Delete a database configuration by ID
1752
+ */
1753
+ async deleteConfig(tenantId, id) {
1754
+ await this.ensureInitialized();
1755
+ const result = await this.pool.query(
1756
+ `
1757
+ DELETE FROM lattice_database_configs
1758
+ WHERE tenant_id = $1 AND id = $2
1759
+ `,
1760
+ [tenantId, id]
1761
+ );
1762
+ return result.rowCount !== null && result.rowCount > 0;
1763
+ }
1764
+ /**
1765
+ * Check if configuration exists
1766
+ */
1767
+ async hasConfig(tenantId, id) {
1768
+ await this.ensureInitialized();
1769
+ const result = await this.pool.query(
1770
+ `
1771
+ SELECT 1 FROM lattice_database_configs
1772
+ WHERE tenant_id = $1 AND id = $2
1773
+ LIMIT 1
1774
+ `,
1775
+ [tenantId, id]
1776
+ );
1777
+ return result.rows.length > 0;
1778
+ }
1779
+ /**
1780
+ * Dispose resources and close the connection pool
1781
+ */
1782
+ async dispose() {
1783
+ await this.pool.end();
1784
+ }
1785
+ /**
1786
+ * Ensure store is initialized
1787
+ */
1788
+ async ensureInitialized() {
1789
+ if (!this.initialized) {
1790
+ await this.initialize();
1791
+ }
1792
+ }
1793
+ /**
1794
+ * Map database row to DatabaseConfigEntry object
1795
+ * Automatically decrypts password if present
1796
+ */
1797
+ mapRowToEntry(row) {
1798
+ const config = typeof row.config === "string" ? JSON.parse(row.config) : row.config;
1799
+ if (config.password) {
1800
+ try {
1801
+ config.password = (0, import_core.decrypt)(config.password);
1802
+ } catch (error) {
1803
+ console.error("Failed to decrypt database password:", error);
1804
+ throw new Error("Failed to decrypt database configuration");
1805
+ }
1806
+ }
1807
+ return {
1808
+ id: row.id,
1809
+ tenantId: row.tenant_id,
1810
+ key: row.key,
1811
+ config,
1812
+ name: row.name || void 0,
1813
+ description: row.description || void 0,
1814
+ createdAt: row.created_at,
1815
+ updatedAt: row.updated_at
1816
+ };
1817
+ }
1818
+ /**
1819
+ * Encrypt password in config before storing
1820
+ */
1821
+ encryptPasswordInConfig(config) {
1822
+ const configCopy = { ...config };
1823
+ if (configCopy.password) {
1824
+ configCopy.password = (0, import_core.encrypt)(configCopy.password);
1825
+ }
1826
+ return configCopy;
1827
+ }
1828
+ };
1829
+
1830
+ // src/stores/PostgreSQLWorkspaceStore.ts
1831
+ var import_pg6 = require("pg");
1832
+
1833
+ // src/migrations/workspace_migrations.ts
1834
+ var createWorkspacesTable = {
1835
+ version: 5,
1836
+ name: "create_workspaces_table",
1837
+ up: async (client) => {
1838
+ await client.query(`
1839
+ CREATE TABLE IF NOT EXISTS lattice_workspaces (
1840
+ id VARCHAR(255) NOT NULL,
1841
+ tenant_id VARCHAR(255) NOT NULL,
1842
+ name VARCHAR(255) NOT NULL,
1843
+ description TEXT,
1844
+ storage_type VARCHAR(50) NOT NULL DEFAULT 'sandbox',
1845
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
1846
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
1847
+ PRIMARY KEY (id, tenant_id)
1848
+ )
1849
+ `);
1850
+ await client.query(`
1851
+ CREATE INDEX IF NOT EXISTS idx_lattice_workspaces_tenant_id
1852
+ ON lattice_workspaces(tenant_id)
1853
+ `);
1854
+ await client.query(`
1855
+ CREATE INDEX IF NOT EXISTS idx_lattice_workspaces_created_at
1856
+ ON lattice_workspaces(created_at DESC)
1857
+ `);
1858
+ },
1859
+ down: async (client) => {
1860
+ await client.query("DROP INDEX IF EXISTS idx_lattice_workspaces_created_at");
1861
+ await client.query("DROP INDEX IF EXISTS idx_lattice_workspaces_tenant_id");
1862
+ await client.query("DROP TABLE IF EXISTS lattice_workspaces");
1863
+ }
1864
+ };
1865
+
1866
+ // src/stores/PostgreSQLWorkspaceStore.ts
1867
+ var PostgreSQLWorkspaceStore = class {
1868
+ constructor(options) {
1869
+ this.initialized = false;
1870
+ this.ownsPool = true;
1871
+ if (typeof options.poolConfig === "string") {
1872
+ this.pool = new import_pg6.Pool({ connectionString: options.poolConfig });
1873
+ } else {
1874
+ this.pool = new import_pg6.Pool(options.poolConfig);
1875
+ }
1876
+ this.migrationManager = new MigrationManager(this.pool);
1877
+ this.migrationManager.register(createWorkspacesTable);
1878
+ if (options.autoMigrate !== false) {
1879
+ this.initialize().catch((error) => {
1880
+ console.error("Failed to initialize PostgreSQLWorkspaceStore:", error);
1881
+ throw error;
1882
+ });
1883
+ }
1884
+ }
1885
+ /**
1886
+ * Dispose resources and close the connection pool
1887
+ * Should be called when the store is no longer needed
1888
+ */
1889
+ async dispose() {
1890
+ if (this.ownsPool && this.pool) {
1891
+ await this.pool.end();
1892
+ }
1893
+ }
1894
+ /**
1895
+ * Initialize the store and run migrations
1896
+ */
1897
+ async initialize() {
1898
+ if (this.initialized) {
1899
+ return;
1900
+ }
1901
+ await this.migrationManager.migrate();
1902
+ this.initialized = true;
1903
+ }
1904
+ /**
1905
+ * Ensure store is initialized
1906
+ */
1907
+ async ensureInitialized() {
1908
+ if (!this.initialized) {
1909
+ await this.initialize();
1910
+ }
1911
+ }
1912
+ /**
1913
+ * Map database row to Workspace object
1914
+ */
1915
+ mapRowToWorkspace(row) {
1916
+ return {
1917
+ id: row.id,
1918
+ tenantId: row.tenant_id,
1919
+ name: row.name,
1920
+ description: row.description || void 0,
1921
+ storageType: row.storage_type,
1922
+ createdAt: row.created_at,
1923
+ updatedAt: row.updated_at
1924
+ };
1925
+ }
1926
+ /**
1927
+ * Get all workspaces for a tenant
1928
+ */
1929
+ async getAllWorkspaces(tenantId) {
1930
+ await this.ensureInitialized();
1931
+ const result = await this.pool.query(
1932
+ `
1933
+ SELECT id, tenant_id, name, description, storage_type, created_at, updated_at
1934
+ FROM lattice_workspaces
1935
+ WHERE tenant_id = $1
1936
+ ORDER BY created_at DESC
1937
+ `,
1938
+ [tenantId]
1939
+ );
1940
+ return result.rows.map(this.mapRowToWorkspace);
1941
+ }
1942
+ /**
1943
+ * Get a workspace by ID for a specific tenant
1944
+ */
1945
+ async getWorkspaceById(tenantId, id) {
1946
+ await this.ensureInitialized();
1947
+ const result = await this.pool.query(
1948
+ `
1949
+ SELECT id, tenant_id, name, description, storage_type, created_at, updated_at
1950
+ FROM lattice_workspaces
1951
+ WHERE id = $1 AND tenant_id = $2
1952
+ `,
1953
+ [id, tenantId]
1954
+ );
1955
+ if (result.rows.length === 0) {
1956
+ return null;
1957
+ }
1958
+ return this.mapRowToWorkspace(result.rows[0]);
1959
+ }
1960
+ /**
1961
+ * Create a new workspace
1962
+ */
1963
+ async createWorkspace(tenantId, id, data) {
1964
+ await this.ensureInitialized();
1965
+ const now = /* @__PURE__ */ new Date();
1966
+ await this.pool.query(
1967
+ `
1968
+ INSERT INTO lattice_workspaces (id, tenant_id, name, description, storage_type, created_at, updated_at)
1969
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
1970
+ ON CONFLICT (id, tenant_id) DO UPDATE SET
1971
+ name = EXCLUDED.name,
1972
+ description = EXCLUDED.description,
1973
+ storage_type = EXCLUDED.storage_type,
1974
+ updated_at = EXCLUDED.updated_at
1975
+ `,
1976
+ [id, tenantId, data.name, data.description || null, data.storageType, now, now]
1977
+ );
1978
+ return {
1979
+ id,
1980
+ tenantId,
1981
+ name: data.name,
1982
+ description: data.description,
1983
+ storageType: data.storageType,
1984
+ createdAt: now,
1985
+ updatedAt: now
1986
+ };
1987
+ }
1988
+ /**
1989
+ * Update an existing workspace
1990
+ */
1991
+ async updateWorkspace(tenantId, id, updates) {
1992
+ await this.ensureInitialized();
1993
+ const existing = await this.getWorkspaceById(tenantId, id);
1994
+ if (!existing) {
1995
+ return null;
1996
+ }
1997
+ const updateFields = [];
1998
+ const updateValues = [];
1999
+ let paramIndex = 1;
2000
+ if (updates.name !== void 0) {
2001
+ updateFields.push(`name = $${paramIndex++}`);
2002
+ updateValues.push(updates.name);
2003
+ }
2004
+ if (updates.description !== void 0) {
2005
+ updateFields.push(`description = $${paramIndex++}`);
2006
+ updateValues.push(updates.description || null);
2007
+ }
2008
+ if (updates.storageType !== void 0) {
2009
+ updateFields.push(`storage_type = $${paramIndex++}`);
2010
+ updateValues.push(updates.storageType);
2011
+ }
2012
+ if (updateFields.length === 0) {
2013
+ return existing;
2014
+ }
2015
+ updateFields.push(`updated_at = $${paramIndex++}`);
2016
+ updateValues.push(/* @__PURE__ */ new Date());
2017
+ updateValues.push(id);
2018
+ updateValues.push(tenantId);
2019
+ await this.pool.query(
2020
+ `
2021
+ UPDATE lattice_workspaces
2022
+ SET ${updateFields.join(", ")}
2023
+ WHERE id = $${paramIndex} AND tenant_id = $${paramIndex + 1}
2024
+ `,
2025
+ updateValues
2026
+ );
2027
+ return await this.getWorkspaceById(tenantId, id);
2028
+ }
2029
+ /**
2030
+ * Delete a workspace by ID
2031
+ */
2032
+ async deleteWorkspace(tenantId, id) {
2033
+ await this.ensureInitialized();
2034
+ const result = await this.pool.query(
2035
+ `
2036
+ DELETE FROM lattice_workspaces
2037
+ WHERE id = $1 AND tenant_id = $2
2038
+ `,
2039
+ [id, tenantId]
2040
+ );
2041
+ return result.rowCount !== null && result.rowCount > 0;
2042
+ }
2043
+ };
2044
+
2045
+ // src/stores/PostgreSQLProjectStore.ts
2046
+ var import_pg7 = require("pg");
2047
+
2048
+ // src/migrations/project_migrations.ts
2049
+ var createProjectsTable = {
2050
+ version: 6,
2051
+ name: "create_projects_table",
2052
+ up: async (client) => {
2053
+ await client.query(`
2054
+ CREATE TABLE IF NOT EXISTS lattice_projects (
2055
+ id VARCHAR(255) NOT NULL,
2056
+ tenant_id VARCHAR(255) NOT NULL,
2057
+ workspace_id VARCHAR(255) NOT NULL,
2058
+ name VARCHAR(255) NOT NULL,
2059
+ description TEXT,
2060
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
2061
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
2062
+ PRIMARY KEY (id, tenant_id)
2063
+ )
2064
+ `);
2065
+ await client.query(`
2066
+ CREATE INDEX IF NOT EXISTS idx_lattice_projects_tenant_id
2067
+ ON lattice_projects(tenant_id)
2068
+ `);
2069
+ await client.query(`
2070
+ CREATE INDEX IF NOT EXISTS idx_lattice_projects_workspace_id
2071
+ ON lattice_projects(workspace_id)
2072
+ `);
2073
+ await client.query(`
2074
+ CREATE INDEX IF NOT EXISTS idx_lattice_projects_created_at
2075
+ ON lattice_projects(created_at DESC)
2076
+ `);
2077
+ },
2078
+ down: async (client) => {
2079
+ await client.query("DROP INDEX IF EXISTS idx_lattice_projects_created_at");
2080
+ await client.query("DROP INDEX IF EXISTS idx_lattice_projects_workspace_id");
2081
+ await client.query("DROP INDEX IF EXISTS idx_lattice_projects_tenant_id");
2082
+ await client.query("DROP TABLE IF EXISTS lattice_projects");
2083
+ }
2084
+ };
2085
+
2086
+ // src/stores/PostgreSQLProjectStore.ts
2087
+ var PostgreSQLProjectStore = class {
2088
+ constructor(options) {
2089
+ this.initialized = false;
2090
+ this.ownsPool = true;
2091
+ if (typeof options.poolConfig === "string") {
2092
+ this.pool = new import_pg7.Pool({ connectionString: options.poolConfig });
2093
+ } else {
2094
+ this.pool = new import_pg7.Pool(options.poolConfig);
2095
+ }
2096
+ this.migrationManager = new MigrationManager(this.pool);
2097
+ this.migrationManager.register(createProjectsTable);
2098
+ if (options.autoMigrate !== false) {
2099
+ this.initialize().catch((error) => {
2100
+ console.error("Failed to initialize PostgreSQLProjectStore:", error);
2101
+ throw error;
2102
+ });
2103
+ }
2104
+ }
2105
+ /**
2106
+ * Dispose resources and close the connection pool
2107
+ * Should be called when the store is no longer needed
2108
+ */
2109
+ async dispose() {
2110
+ if (this.ownsPool && this.pool) {
2111
+ await this.pool.end();
2112
+ }
2113
+ }
2114
+ /**
2115
+ * Initialize the store and run migrations
2116
+ */
2117
+ async initialize() {
2118
+ if (this.initialized) {
2119
+ return;
2120
+ }
2121
+ await this.migrationManager.migrate();
2122
+ this.initialized = true;
2123
+ }
2124
+ /**
2125
+ * Ensure store is initialized
2126
+ */
2127
+ async ensureInitialized() {
2128
+ if (!this.initialized) {
2129
+ await this.initialize();
2130
+ }
2131
+ }
2132
+ /**
2133
+ * Map database row to Project object
2134
+ */
2135
+ mapRowToProject(row) {
2136
+ return {
2137
+ id: row.id,
2138
+ tenantId: row.tenant_id,
2139
+ workspaceId: row.workspace_id,
2140
+ name: row.name,
2141
+ description: row.description || void 0,
2142
+ createdAt: row.created_at,
2143
+ updatedAt: row.updated_at
2144
+ };
2145
+ }
2146
+ /**
2147
+ * Get all projects for a specific workspace
2148
+ */
2149
+ async getProjectsByWorkspace(tenantId, workspaceId) {
2150
+ await this.ensureInitialized();
2151
+ const result = await this.pool.query(
2152
+ `
2153
+ SELECT id, tenant_id, workspace_id, name, description, created_at, updated_at
2154
+ FROM lattice_projects
2155
+ WHERE tenant_id = $1 AND workspace_id = $2
2156
+ ORDER BY created_at DESC
2157
+ `,
2158
+ [tenantId, workspaceId]
2159
+ );
2160
+ return result.rows.map(this.mapRowToProject);
2161
+ }
2162
+ /**
2163
+ * Get a project by ID for a specific tenant
2164
+ */
2165
+ async getProjectById(tenantId, id) {
2166
+ await this.ensureInitialized();
2167
+ const result = await this.pool.query(
2168
+ `
2169
+ SELECT id, tenant_id, workspace_id, name, description, created_at, updated_at
2170
+ FROM lattice_projects
2171
+ WHERE id = $1 AND tenant_id = $2
2172
+ `,
2173
+ [id, tenantId]
2174
+ );
2175
+ if (result.rows.length === 0) {
2176
+ return null;
2177
+ }
2178
+ return this.mapRowToProject(result.rows[0]);
2179
+ }
2180
+ /**
2181
+ * Create a new project
2182
+ */
2183
+ async createProject(tenantId, workspaceId, id, data) {
2184
+ await this.ensureInitialized();
2185
+ const now = /* @__PURE__ */ new Date();
2186
+ await this.pool.query(
2187
+ `
2188
+ INSERT INTO lattice_projects (id, tenant_id, workspace_id, name, description, created_at, updated_at)
2189
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
2190
+ ON CONFLICT (id, tenant_id) DO UPDATE SET
2191
+ workspace_id = EXCLUDED.workspace_id,
2192
+ name = EXCLUDED.name,
2193
+ description = EXCLUDED.description,
2194
+ updated_at = EXCLUDED.updated_at
2195
+ `,
2196
+ [id, tenantId, workspaceId, data.name, data.description || null, now, now]
2197
+ );
2198
+ return {
2199
+ id,
2200
+ tenantId,
2201
+ workspaceId,
2202
+ name: data.name,
2203
+ description: data.description,
2204
+ createdAt: now,
2205
+ updatedAt: now
2206
+ };
2207
+ }
2208
+ /**
2209
+ * Update an existing project
2210
+ */
2211
+ async updateProject(tenantId, id, updates) {
2212
+ await this.ensureInitialized();
2213
+ const existing = await this.getProjectById(tenantId, id);
2214
+ if (!existing) {
2215
+ return null;
2216
+ }
2217
+ const updateFields = [];
2218
+ const updateValues = [];
2219
+ let paramIndex = 1;
2220
+ if (updates.name !== void 0) {
2221
+ updateFields.push(`name = $${paramIndex++}`);
2222
+ updateValues.push(updates.name);
2223
+ }
2224
+ if (updates.description !== void 0) {
2225
+ updateFields.push(`description = $${paramIndex++}`);
2226
+ updateValues.push(updates.description || null);
2227
+ }
2228
+ if (updateFields.length === 0) {
2229
+ return existing;
2230
+ }
2231
+ updateFields.push(`updated_at = $${paramIndex++}`);
2232
+ updateValues.push(/* @__PURE__ */ new Date());
2233
+ updateValues.push(id);
2234
+ updateValues.push(tenantId);
2235
+ await this.pool.query(
2236
+ `
2237
+ UPDATE lattice_projects
2238
+ SET ${updateFields.join(", ")}
2239
+ WHERE id = $${paramIndex} AND tenant_id = $${paramIndex + 1}
2240
+ `,
2241
+ updateValues
2242
+ );
2243
+ return await this.getProjectById(tenantId, id);
2244
+ }
2245
+ /**
2246
+ * Delete a project by ID
2247
+ */
2248
+ async deleteProject(tenantId, id) {
2249
+ await this.ensureInitialized();
2250
+ const result = await this.pool.query(
2251
+ `
2252
+ DELETE FROM lattice_projects
2253
+ WHERE id = $1 AND tenant_id = $2
2254
+ `,
2255
+ [id, tenantId]
2256
+ );
2257
+ return result.rowCount !== null && result.rowCount > 0;
2258
+ }
2259
+ };
1509
2260
  // Annotate the CommonJS export names for ESM import in node:
1510
2261
  0 && (module.exports = {
1511
2262
  MigrationManager,
1512
2263
  PostgreSQLAssistantStore,
2264
+ PostgreSQLDatabaseConfigStore,
2265
+ PostgreSQLProjectStore,
1513
2266
  PostgreSQLScheduleStorage,
1514
2267
  PostgreSQLSkillStore,
1515
2268
  PostgreSQLThreadStore,
2269
+ PostgreSQLWorkspaceStore,
1516
2270
  createAssistantsTable,
2271
+ createDatabaseConfigsTable,
2272
+ createProjectsTable,
1517
2273
  createScheduledTasksTable,
1518
2274
  createSkillsTable,
1519
- createThreadsTable
2275
+ createThreadsTable,
2276
+ createWorkspacesTable
1520
2277
  });
1521
2278
  //# sourceMappingURL=index.js.map