UNPKG

@decaf-ts/for-couchdb

Version:
201 lines 8.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reAuth = reAuth; exports.wrapDocumentScope = wrapDocumentScope; exports.testReservedAttributes = testReservedAttributes; exports.generateIndexName = generateIndexName; exports.generateIndexDoc = generateIndexDoc; const core_1 = require("@decaf-ts/core"); const constants_js_1 = require("./constants.cjs"); const db_decorators_1 = require("@decaf-ts/db-decorators"); const constants_js_2 = require("./query/constants.cjs"); /** * @description Re-authenticates a connection to CouchDB * @summary Refreshes the authentication for a CouchDB connection using the provided credentials * @param {any} con - The CouchDB connection object * @param {string} user - The username for authentication * @param {string} pass - The password for authentication * @return {Promise<any>} A promise that resolves to the authentication result * @function reAuth * @memberOf module:for-couchdb */ async function reAuth(con, couchUser, couchPassword) { return con.auth(couchUser, couchPassword); } /** * @description Wraps a CouchDB database connection with automatic re-authentication * @summary Creates a proxy around a CouchDB database connection that automatically re-authenticates before each operation * @param {any} con - The CouchDB connection object * @param {string} dbName - The name of the database to use * @param {string} user - The username for authentication * @param {string} pass - The password for authentication * @return {any} The wrapped database connection object * @function wrapDocumentScope * @memberOf module:for-couchdb * @mermaid * sequenceDiagram * participant Client * participant wrapDocumentScope * participant DB * participant reAuth * * Client->>wrapDocumentScope: con, dbName, user, pass * wrapDocumentScope->>DB: con.use(dbName) * Note over wrapDocumentScope: Wrap DB methods with re-auth * * loop For each method (insert, get, put, destroy, find) * wrapDocumentScope->>wrapDocumentScope: Store original method * wrapDocumentScope->>wrapDocumentScope: Define new method with re-auth * end * * wrapDocumentScope->>wrapDocumentScope: Add NATIVE property with con value * wrapDocumentScope-->>Client: Return wrapped DB * * Note over Client: Later when client uses DB methods * Client->>DB: Any wrapped method call * DB->>reAuth: Authenticate before operation * reAuth-->>DB: Authentication complete * DB->>DB: Call original method * DB-->>Client: Return result */ function wrapDocumentScope(con, dbName, couchUser, couchPassword) { const db = con.use ? con.use(dbName) : con; [ "insert", "bulk", "fetch", "createIndex", "get", "put", "destroy", "find", "view", ].forEach((k) => { const original = db[k]; // Not every CouchDB client exposes the same surface (e.g. nano has no // `put`, it uses `insert` for both create and update). Skip methods that // are not available on the underlying scope instead of failing hard, so // the wrapper stays usable across adapters while still re-authing every // method that does exist. if (typeof original !== "function") return; Object.defineProperty(db, k, { enumerable: false, configurable: true, value: async (...args) => { await reAuth(con, couchUser, couchPassword); return original.call(db, ...args); }, }); }); Object.defineProperty(db, constants_js_1.CouchDBKeys.NATIVE, { enumerable: false, configurable: false, writable: false, value: con, }); return db; } /** * @description Tests if an attribute name is reserved in CouchDB * @summary Checks if an attribute name starts with an underscore, which indicates it's a reserved attribute in CouchDB * @param {string} attr - The attribute name to test * @return {RegExpMatchArray|null} The match result or null if no match * @function testReservedAttributes * @memberOf module:for-couchdb */ function testReservedAttributes(attr) { const regexp = /^_.*$/g; return attr.match(regexp); } /** * @description Generates a name for a CouchDB index * @summary Creates a standardized name for a CouchDB index based on the table, attribute, compositions, and order * @param {string} attribute - The primary attribute for the index * @param {string} tableName - The name of the table * @param {string[]} [compositions] - Optional additional attributes to include in the index * @param {OrderDirection} [order] - Optional sort order for the index * @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name * @return {string} The generated index name * @function generateIndexName * @memberOf module:for-couchdb */ function generateIndexName(attribute, tableName, compositions, order, separator = db_decorators_1.DefaultSeparator) { const attr = [core_1.PersistenceKeys.INDEX, tableName, attribute]; if (compositions) attr.push(...compositions); if (order) attr.push(order); return attr.join(separator); } /** * @description Generates a CouchDB index configuration * @summary Creates a complete CreateIndexRequest object for defining a CouchDB index based on specified parameters * @param {string} attribute - The primary attribute for the index * @param {string} tableName - The name of the table * @param {string[]} [compositions] - Optional additional attributes to include in the index * @param {OrderDirection} [order] - Optional sort order for the index * @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name * @return {CreateIndexRequest} The complete index configuration object * @function generateIndexDoc * @memberOf module:for-couchdb * @mermaid * sequenceDiagram * participant Caller * participant generateIndexDoc * participant generateIndexName * * Caller->>generateIndexDoc: attribute, tableName, compositions, order, separator * * Note over generateIndexDoc: Create partial filter selector * generateIndexDoc->>generateIndexDoc: Set up filter for tableName * * alt order is specified * Note over generateIndexDoc: Create ordered fields array * generateIndexDoc->>generateIndexDoc: Create orderProp for attribute * generateIndexDoc->>generateIndexDoc: Map compositions to ordered props * generateIndexDoc->>generateIndexDoc: Create sortedTable for table field * generateIndexDoc->>generateIndexDoc: Combine all ordered fields * else * Note over generateIndexDoc: Create simple fields array * generateIndexDoc->>generateIndexDoc: Use attribute, compositions, and table as strings * end * * generateIndexDoc->>generateIndexName: Generate index name * generateIndexName-->>generateIndexDoc: Return name * * Note over generateIndexDoc: Create final index request * generateIndexDoc-->>Caller: Return CreateIndexRequest */ function generateIndexDoc(attribute, tableName, compositions, order, separator = db_decorators_1.DefaultSeparator) { const partialFilterSelector = {}; partialFilterSelector[constants_js_1.CouchDBKeys.TABLE] = {}; partialFilterSelector[constants_js_1.CouchDBKeys.TABLE][constants_js_2.CouchDBOperator.EQUAL] = tableName; let fields; if (order) { const orderProp = {}; orderProp[attribute] = order; const sortedCompositions = (compositions || []).map((c) => { const r = {}; r[c] = order; return r; }); const sortedTable = {}; sortedTable[constants_js_1.CouchDBKeys.TABLE] = order; fields = [orderProp, ...sortedCompositions, sortedTable]; } else { fields = [attribute, ...(compositions || []), constants_js_1.CouchDBKeys.TABLE]; } const name = generateIndexName(attribute, tableName, compositions, order, separator); return { index: { fields: fields, // partial_filter_selector: partialFilterSelector, }, ddoc: [name, constants_js_1.CouchDBKeys.DDOC].join(separator), name: name, }; } //# sourceMappingURL=utils.js.map //# sourceMappingURL=utils.cjs.map