{"version":3,"file":"sync-tenants.mjs","names":["constants","formatter"],"sources":["../../../src/services/sync/sync-tenants.ts"],"sourcesContent":["import constants from \"../../constants/constants.js\";\nimport formatter from \"../../libs/formatters/index.js\";\nimport logger from \"../../libs/logger/index.js\";\nimport { TenantsRepository } from \"../../libs/repositories/index.js\";\nimport type { ServiceContext, ServiceFn } from \"../../utils/services/types.js\";\n\n/**\n * Syncs the tenants in the database with the tenants in the config. Handles creating, soft-deleting, and restoring.\n */\nconst syncTenants: ServiceFn<[], undefined> = async (\n\tcontext: ServiceContext,\n) => {\n\tconst Tenants = new TenantsRepository(context.db.client, context.config.db);\n\tconst tenantKeys = context.config.tenants.map((tenant) => tenant.key);\n\n\tconst tenantsRes = await Tenants.selectMultiple({\n\t\tselect: [\"key\", \"is_deleted\"],\n\t\tvalidation: {\n\t\t\tenabled: true,\n\t\t},\n\t});\n\tif (tenantsRes.error) return tenantsRes;\n\n\tconst tenantKeysFromDB = tenantsRes.data.map((tenant) => tenant.key);\n\n\t// Get tenant keys that are in the config but not in the database\n\tconst missingTenants = tenantKeys.filter(\n\t\t(tenant) => !tenantKeysFromDB.includes(tenant),\n\t);\n\tif (missingTenants.length > 0) {\n\t\tlogger.debug({\n\t\t\tmessage: `Syncing new tenants to the DB: ${missingTenants.join(\", \")}`,\n\t\t\tscope: constants.logScopes.sync,\n\t\t});\n\t}\n\n\t// Get tenant keys that are in the database but not in the config\n\tconst tenantsToDelete = tenantsRes.data.filter(\n\t\t(tenant) =>\n\t\t\t!tenantKeys.includes(tenant.key) &&\n\t\t\tformatter.formatBoolean(tenant.is_deleted) === false,\n\t);\n\tconst tenantsToDeleteKeys = tenantsToDelete.map((tenant) => tenant.key);\n\tif (tenantsToDeleteKeys.length > 0) {\n\t\tlogger.debug({\n\t\t\tmessage: `Marking the following tenants as deleted: ${tenantsToDeleteKeys.join(\", \")}`,\n\t\t\tscope: constants.logScopes.sync,\n\t\t});\n\t}\n\n\t// Get tenants that are in the database as is_deleted but in the config\n\tconst unDeletedTenants = tenantsRes.data.filter(\n\t\t(tenant) =>\n\t\t\tformatter.formatBoolean(tenant.is_deleted) &&\n\t\t\ttenantKeys.includes(tenant.key),\n\t);\n\tconst unDeletedTenantKeys = unDeletedTenants.map((tenant) => tenant.key);\n\tif (unDeletedTenantKeys.length > 0) {\n\t\tlogger.debug({\n\t\t\tmessage: `Restoring previously deleted tenants: ${unDeletedTenantKeys.join(\", \")}`,\n\t\t\tscope: constants.logScopes.sync,\n\t\t});\n\t}\n\n\tconst [createRes, deleteRes, restoreRes] = await Promise.all([\n\t\tmissingTenants.length > 0 &&\n\t\t\tTenants.createMultiple({\n\t\t\t\tdata: missingTenants.map((tenant) => ({\n\t\t\t\t\tkey: tenant,\n\t\t\t\t})),\n\t\t\t}),\n\t\ttenantsToDeleteKeys.length > 0 &&\n\t\t\tTenants.updateSingle({\n\t\t\t\tdata: {\n\t\t\t\t\tis_deleted: true,\n\t\t\t\t\tis_deleted_at: new Date().toISOString(),\n\t\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"key\",\n\t\t\t\t\t\toperator: \"in\",\n\t\t\t\t\t\tvalue: tenantsToDeleteKeys,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\treturning: [\"key\"],\n\t\t\t\tvalidation: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t},\n\t\t\t}),\n\t\tunDeletedTenantKeys.length > 0 &&\n\t\t\tTenants.updateSingle({\n\t\t\t\tdata: {\n\t\t\t\t\tis_deleted: false,\n\t\t\t\t\tis_deleted_at: null,\n\t\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: \"key\",\n\t\t\t\t\t\toperator: \"in\",\n\t\t\t\t\t\tvalue: unDeletedTenantKeys,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\treturning: [\"key\"],\n\t\t\t\tvalidation: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t},\n\t\t\t}),\n\t]);\n\tif (typeof createRes !== \"boolean\" && createRes.error) return createRes;\n\tif (typeof deleteRes !== \"boolean\" && deleteRes.error) return deleteRes;\n\tif (typeof restoreRes !== \"boolean\" && restoreRes.error) return restoreRes;\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: undefined,\n\t};\n};\n\nexport default syncTenants;\n"],"mappings":"0LASA,MAAM,EAAwC,KAC7C,IACI,CACJ,IAAM,EAAU,IAAI,EAAkB,EAAQ,GAAG,OAAQ,EAAQ,OAAO,EAAE,EACpE,EAAa,EAAQ,OAAO,QAAQ,IAAK,GAAW,EAAO,GAAG,EAE9D,EAAa,MAAM,EAAQ,eAAe,CAC/C,OAAQ,CAAC,MAAO,YAAY,EAC5B,WAAY,CACX,QAAS,EACV,CACD,CAAC,EACD,GAAI,EAAW,MAAO,OAAO,EAE7B,IAAM,EAAmB,EAAW,KAAK,IAAK,GAAW,EAAO,GAAG,EAG7D,EAAiB,EAAW,OAChC,GAAW,CAAC,EAAiB,SAAS,CAAM,CAC9C,EACI,EAAe,OAAS,GAC3B,EAAO,MAAM,CACZ,QAAS,kCAAkC,EAAe,KAAK,IAAI,IACnE,MAAOA,EAAU,UAAU,IAC5B,CAAC,EASF,IAAM,EALkB,EAAW,KAAK,OACtC,GACA,CAAC,EAAW,SAAS,EAAO,GAAG,GAC/BC,EAAU,cAAc,EAAO,UAAU,IAAM,EAEP,CAAC,CAAC,IAAK,GAAW,EAAO,GAAG,EAClE,EAAoB,OAAS,GAChC,EAAO,MAAM,CACZ,QAAS,6CAA6C,EAAoB,KAAK,IAAI,IACnF,MAAOD,EAAU,UAAU,IAC5B,CAAC,EASF,IAAM,EALmB,EAAW,KAAK,OACvC,GACAC,EAAU,cAAc,EAAO,UAAU,GACzC,EAAW,SAAS,EAAO,GAAG,CAEW,CAAC,CAAC,IAAK,GAAW,EAAO,GAAG,EACnE,EAAoB,OAAS,GAChC,EAAO,MAAM,CACZ,QAAS,yCAAyC,EAAoB,KAAK,IAAI,IAC/E,MAAOD,EAAU,UAAU,IAC5B,CAAC,EAGF,GAAM,CAAC,EAAW,EAAW,GAAc,MAAM,QAAQ,IAAI,CAC5D,EAAe,OAAS,GACvB,EAAQ,eAAe,CACtB,KAAM,EAAe,IAAK,IAAY,CACrC,IAAK,CACN,EAAE,CACH,CAAC,EACF,EAAoB,OAAS,GAC5B,EAAQ,aAAa,CACpB,KAAM,CACL,WAAY,GACZ,cAAe,IAAI,KAAK,CAAA,CAAE,YAAY,EACtC,WAAY,IAAI,KAAK,CAAA,CAAE,YAAY,CACpC,EACA,MAAO,CACN,CACC,IAAK,MACL,SAAU,KACV,MAAO,CACR,CACD,EACA,UAAW,CAAC,KAAK,EACjB,WAAY,CACX,QAAS,EACV,CACD,CAAC,EACF,EAAoB,OAAS,GAC5B,EAAQ,aAAa,CACpB,KAAM,CACL,WAAY,GACZ,cAAe,KACf,WAAY,IAAI,KAAK,CAAA,CAAE,YAAY,CACpC,EACA,MAAO,CACN,CACC,IAAK,MACL,SAAU,KACV,MAAO,CACR,CACD,EACA,UAAW,CAAC,KAAK,EACjB,WAAY,CACX,QAAS,EACV,CACD,CAAC,CACH,CAAC,EAKD,OAJI,OAAO,GAAc,WAAa,EAAU,MAAc,EAC1D,OAAO,GAAc,WAAa,EAAU,MAAc,EAC1D,OAAO,GAAe,WAAa,EAAW,MAAc,EAEzD,CACN,MAAO,IAAA,GACP,KAAM,IAAA,EACP,CACD"}