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