UNPKG

longcelot-sheet-db

Version:

Google Sheets-backed staging database adapter for Node.js with schema-first design

91 lines 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SQLAdapterBase = void 0; const PermissionError_1 = require("../../errors/PermissionError"); const SchemaError_1 = require("../../errors/SchemaError"); const accessControl_1 = require("../accessControl"); const sqlTableOperations_1 = require("./sqlTableOperations"); const fkResolver_1 = require("./fkResolver"); /** * Shared DatabaseAdapter implementation for the Postgres/MySQL adapters (Phase 16.2) — * withContext()/asActor()/table() mirror SheetAdapter's exactly (same actor/role and * targetActor/targetRole normalization), minus the Sheets-only schema-version-check * machinery, since SQL adapters never auto-sync schema at runtime (Phase 16 decision 5). */ class SQLAdapterBase { constructor(connection, dialect, config = {}) { this.connection = connection; this.dialect = dialect; this.schemas = new Map(); this.tenantColumn = config.tenantColumn ?? 'tenant_id'; this.permissions = config.permissions; } registerSchema(schema) { this.schemas.set(schema.name, schema); } registerSchemas(schemas) { schemas.forEach((schema) => this.registerSchema(schema)); } withContext(context) { let actorValue; if (context.actor) { actorValue = context.actor; } else if (context.role) { console.warn('[lsdb] UserContext.role is deprecated — use actor instead. ' + 'See: https://github.com/longcelot/sheet-db#actors-vs-application-roles'); actorValue = context.role; } else { throw new Error('[lsdb] withContext() requires either actor or role in UserContext'); } let targetActorValue; if (context.targetActor) { targetActorValue = context.targetActor; } else if (context.targetRole) { console.warn('[lsdb] UserContext.targetRole is deprecated — use targetActor instead. ' + 'See: https://github.com/longcelot/sheet-db#actors-vs-application-roles'); targetActorValue = context.targetRole; } const normalised = { userId: context.userId, actor: actorValue, role: actorValue, actorSheetId: context.actorSheetId, targetActor: targetActorValue, targetSheetId: context.targetSheetId, }; const newAdapter = Object.create(this); newAdapter.context = normalised; return newAdapter; } asActor(targetActor, targetSheetId) { if (!this.context) { throw new PermissionError_1.PermissionError('Context required before calling asActor()', undefined); } return this.withContext({ userId: this.context.userId, actor: this.context.actor, actorSheetId: this.context.actorSheetId, targetActor, targetSheetId, }); } table(tableName) { const schema = this.schemas.get(tableName); if (!schema) { throw new SchemaError_1.SchemaError(`Table ${tableName} is not registered`, tableName); } if (!(0, accessControl_1.hasPermission)(schema, this.context, this.permissions)) { throw new PermissionError_1.PermissionError(`User does not have permission to access ${tableName}`, this.context?.role); } const tenant = schema.actor === 'admin' ? undefined : { column: this.tenantColumn, value: (0, accessControl_1.resolveNonAdminTenantKey)(schema, this.context) }; const fkResolver = (0, fkResolver_1.createSQLFKResolver)(this.connection, this.dialect, this.schemas, this.tenantColumn, this.context); return new sqlTableOperations_1.SQLTableOperations(this.connection, this.dialect, schema, tenant, fkResolver); } } exports.SQLAdapterBase = SQLAdapterBase; //# sourceMappingURL=sqlAdapterBase.js.map