@decaf-ts/for-nano
Version:
decaf-ts persistence adapter for CouchDB via nano
775 lines • 31.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NanoAdapter = void 0;
exports.createdByOnNanoCreateUpdate = createdByOnNanoCreateUpdate;
const db_decorators_1 = require("@decaf-ts/db-decorators");
const for_couchdb_1 = require("@decaf-ts/for-couchdb");
const nano_1 = __importDefault(require("nano"));
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
const core_1 = require("@decaf-ts/core");
const constants_js_1 = require("./constants.cjs");
const NanoRepository_js_1 = require("./NanoRepository.cjs");
const NanoDispatch_js_1 = require("./NanoDispatch.cjs");
const decoration_1 = require("@decaf-ts/decoration");
/**
* @description Sets the creator or updater field in a model based on the user in the context
* @summary Callback function used in decorators to automatically set the created_by or updated_by fields
* with the username from the context when a document is created or updated
* @template M - Type extending Model
* @template R - Type extending NanoRepository<M>
* @template V - Type extending RelationsMetadata
* @param {R} this - The repository instance
* @param {Context<NanoFlags>} context - The operation context containing user information
* @param {V} data - The relation metadata
* @param key - The property key to set with the username
* @param {M} model - The model instance being created or updated
* @return {Promise<void>} A promise that resolves when the operation is complete
* @function createdByOnNanoCreateUpdate
* @memberOf module:for-nano
* @mermaid
* sequenceDiagram
* participant F as createdByOnNanoCreateUpdate
* participant C as Context
* participant M as Model
* F->>C: get("user")
* C-->>F: user object
* F->>M: set key to user.name
* Note over F: If no user in context
* F-->>F: throw UnsupportedError
*/
async function createdByOnNanoCreateUpdate(context, data, key, model) {
try {
const user = context.get("user");
model[key] = (user.name || user);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
throw new core_1.UnsupportedError("No User found in context. Please provide a user in the context");
}
}
/**
* @description Adapter for interacting with Nano databases
* @summary Provides a standardized interface for performing CRUD operations on Nano databases,
* extending the CouchDB adapter with Nano-specific functionality. This adapter handles document
* creation, reading, updating, and deletion, as well as bulk operations and index management.
* @template DocumentScope - The Nano document scope type
* @template NanoFlags - Configuration flags for Nano operations
* @template Context - Context type for operations
* @param {DocumentScope<any>} scope - The Nano document scope to use for database operations
* @param {string} [alias] - Optional alias for the adapter
* @class NanoAdapter
* @example
* ```typescript
* // Connect to a Nano database
* const server = NanoAdapter.connect('admin', 'password', 'localhost:5984');
* const db = server.db.use('my_database');
*
* // Create an adapter instance
* const adapter = new NanoAdapter(db);
*
* // Use the adapter for database operations
* const document = await adapter.read('users', '123');
* ```
* @mermaid
* classDiagram
* class CouchDBAdapter {
* +flags()
* +Dispatch()
* +index()
* +create()
* +read()
* +update()
* +delete()
* }
* class NanoAdapter {
* +flags()
* +Dispatch()
* +index()
* +create()
* +createAll()
* +read()
* +readAll()
* +update()
* +updateAll()
* +delete()
* +deleteAll()
* +raw()
* +static connect()
* +static createDatabase()
* +static deleteDatabase()
* +static createUser()
* +static deleteUser()
* +static decoration()
* }
* CouchDBAdapter <|-- NanoAdapter
*/
class NanoAdapter extends for_couchdb_1.CouchDBAdapter {
constructor(scope, alias) {
super(scope, constants_js_1.NanoFlavour, alias);
}
/**
* @description Shuts down the adapter instance
* @summary Cleans up internal resources and clears the cached Nano client instance
* @return {Promise<void>} A promise that resolves when shutdown completes
*/
async shutdown(...args) {
const { ctxArgs } = (await this.logCtx(args, core_1.PersistenceKeys.SHUTDOWN, true)).for(this.shutdown);
await super.shutdown(...ctxArgs);
if (this._client) {
NanoAdapter.closeConnection(this._client[for_couchdb_1.CouchDBKeys.NATIVE]);
this._client = undefined;
}
}
/**
* @description Lazily creates and returns the Nano DocumentScope client
* @summary Uses the adapter configuration to establish a connection and wrap a database scope with credentials
* @return {DocumentScope<any>} The ready-to-use Nano DocumentScope for the configured database
*/
getClient() {
const { couchUser, couchPassword, host, dbName, protocol } = this.config;
const con = NanoAdapter.connect(couchUser, couchPassword, host, protocol);
return (0, for_couchdb_1.wrapDocumentScope)(con, dbName, couchUser, couchPassword);
}
/**
* @description Generates flags for database operations
* @summary Creates a set of flags for a specific operation, including user information
* @template M - Type extending Model
* @param {OperationKeys} operation - The operation being performed (create, read, update, delete)
* @param {Constructor<M>} model - The model constructor
* @param {Partial<NanoFlags>} flags - Partial flags to be merged
* @return {Promise<NanoFlags>} Complete flags for the operation
*/
async flags(operation, model, flags, ...args) {
return super.flags(operation, model, Object.assign({
user: {
name: flags.user?.name || this.config.couchUser,
},
}, flags, ...args));
}
/**
* @description Creates a new NanoDispatch instance
* @summary Returns a dispatcher for handling Nano-specific operations
* @return {NanoDispatch} A new NanoDispatch instance
*/
Dispatch() {
return new NanoDispatch_js_1.NanoDispatch();
}
repository() {
return NanoRepository_js_1.NanoRepository;
}
/**
* @description Creates database indexes for models
* @summary Generates and creates indexes in the Nano database based on the provided models
* @template M - Type extending Model
* @param models - Model constructors to create indexes for
* @return {Promise<void>} A promise that resolves when all indexes are created
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant G as generateIndexes
* participant DB as Nano Database
* A->>G: generateIndexes(models)
* G-->>A: indexes
* loop For each index
* A->>DB: createIndex(index)
* DB-->>A: response
* Note over A: Check if index already exists
* alt Index exists
* A-->>A: throw ConflictError
* end
* end
*/
async index(...models) {
const indexes = (0, for_couchdb_1.generateIndexes)(models);
for (const index of indexes) {
const res = await this.client.createIndex(index);
const { result, id, name } = res;
if (result === "existing")
throw new db_decorators_1.ConflictError(`Index for table ${name} with id ${id}`);
}
const views = (0, for_couchdb_1.generateViews)(models);
for (const view of views) {
try {
await this.client.insert(view);
}
catch (e) {
if (e?.statusCode === 409 || e?.error === "conflict") {
const existing = await this.client.get(view._id);
await this.client.insert({
...view,
_rev: existing._rev,
});
}
else {
throw e;
}
}
}
}
/**
* @description Creates a new document in the database
* @summary Inserts a new document into the Nano database with the provided data
* @param {string} tableName - The name of the table/collection
* @param {string | number} id - The document identifier
* @param {Record<string, any>} model - The document data to insert
* @return {Promise<Record<string, any>>} A promise that resolves to the created document with metadata
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Database
* A->>DB: insert(model)
* alt Success
* DB-->>A: response with ok=true
* A->>A: assignMetadata(model, response.rev)
* A-->>A: return document with metadata
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* else Not OK
* DB-->>A: response with ok=false
* A-->>A: throw InternalError
* end
*/
async create(tableName, id, model,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
let response;
try {
response = await this.client.insert(model);
}
catch (e) {
throw this.parseError(e);
}
if (!response.ok)
throw new db_decorators_1.InternalError(`Failed to insert doc id: ${id} in table ${tableName}`);
return this.assignMetadata(model, response.rev);
}
/**
* @description Creates multiple documents in the database
* @summary Inserts multiple documents into the Nano database in a single bulk operation
* @param {string} tableName - The name of the table/collection
* @param {string[] | number[]} ids - Array of document identifiers
* @param models - Array of document data to insert
* @return A promise that resolves to an array of created documents with metadata
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Database
* A->>DB: bulk({docs: models})
* alt Success
* DB-->>A: response array
* A->>A: Check if all responses have no errors
* alt All OK
* A->>A: assignMultipleMetadata(models, revs)
* A-->>A: return documents with metadata
* else Some errors
* A->>A: Collect error messages
* A-->>A: throw InternalError with collected messages
* end
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* end
*/
async createAll(tableName, ids, models,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
let response;
try {
response = await this.client.bulk({ docs: models });
}
catch (e) {
throw this.parseError(e);
}
if (!response.every((r) => !r.error)) {
const errors = response.reduce((accum, el, i) => {
if (el.error)
accum.push(`el ${i}: ${el.error}${el.reason ? ` - ${el.reason}` : ""}`);
return accum;
}, []);
throw new db_decorators_1.InternalError(errors.join("\n"));
}
return this.assignMultipleMetadata(models, response.map((r) => r.rev));
}
/**
* @description Retrieves a document from the database
* @summary Fetches a single document from the Nano database by its ID
* @param {string} tableName - The name of the table/collection
* @param {string | number} id - The document identifier
* @return {Promise<Record<string, any>>} A promise that resolves to the retrieved document with metadata
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Database
* A->>A: generateId(tableName, id)
* A->>DB: get(_id)
* alt Success
* DB-->>A: record
* A->>A: assignMetadata(record, record._rev)
* A-->>A: return document with metadata
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* end
*/
async read(tableName, id,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
const _id = this.generateId(decorator_validation_1.Model.tableName(tableName), id);
let record;
try {
record = await this.client.get(_id);
}
catch (e) {
throw this.parseError(e);
}
return this.assignMetadata(record, record._rev);
}
/**
* @description Retrieves multiple documents from the database
* @summary Fetches multiple documents from the Nano database by their IDs in a single operation
* @param {string} tableName - The name of the table/collection
* @param {Array<string | number | bigint>} ids - Array of document identifiers
* @return A promise that resolves to an array of retrieved documents with metadata
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Database
* A->>A: Map ids to generateId(tableName, id)
* A->>DB: fetch({keys: mappedIds}, {})
* DB-->>A: results
* A->>A: Process each result row
* loop For each row
* alt Row has error
* A-->>A: throw InternalError
* else Row has document
* A->>A: assignMetadata(doc, doc._rev)
* else No document
* A-->>A: throw InternalError
* end
* end
* A-->>A: return documents with metadata
*/
async readAll(tableName, ids,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
const table = decorator_validation_1.Model.tableName(tableName);
const results = await this.client.fetch({ keys: ids.map((id) => this.generateId(table, id)) }, {});
return results.rows.map((r) => {
if (r.error)
throw new db_decorators_1.InternalError(r.error);
if (r.doc) {
const res = Object.assign({}, r.doc);
return this.assignMetadata(res, r.doc[for_couchdb_1.CouchDBKeys.REV]);
}
throw new db_decorators_1.InternalError("Should be impossible");
});
}
/**
* @description Updates a document in the database
* @summary Updates an existing document in the Nano database with the provided data
* @param {string} tableName - The name of the table/collection
* @param {string | number} id - The document identifier
* @param {Record<string, any>} model - The updated document data
* @return {Promise<Record<string, any>>} A promise that resolves to the updated document with metadata
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Database
* A->>DB: insert(model)
* alt Success
* DB-->>A: response with ok=true
* A->>A: assignMetadata(model, response.rev)
* A-->>A: return document with metadata
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* else Not OK
* DB-->>A: response with ok=false
* A-->>A: throw InternalError
* end
*/
async update(tableName, id, model,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
let response;
try {
response = await this.client.insert(model);
}
catch (e) {
throw this.parseError(e);
}
if (!response.ok)
throw new db_decorators_1.InternalError(`Failed to update doc id: ${id} in table ${tableName}`);
return this.assignMetadata(model, response.rev);
}
/**
* @description Updates multiple documents in the database
* @summary Performs a bulk update operation on the Nano database for the provided documents
* @param {string} tableName - The name of the table/collection
* @param {Array<string|number>} ids - Array of document identifiers
* @param {Promise<Array<Record<string, any>>>} models - Array of updated document data
* @return {Promise<Promise<Array<Record<string, any>>>>} A promise that resolves to the updated documents with metadata
*/
async updateAll(tableName, ids, models,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
let response;
try {
response = await this.client.bulk({ docs: models });
}
catch (e) {
throw this.parseError(e);
}
if (!response.every((r) => !r.error)) {
const errors = response.reduce((accum, el, i) => {
if (el.error)
accum.push(`el ${i}: ${el.error}${el.reason ? ` - ${el.reason}` : ""}`);
return accum;
}, []);
throw new db_decorators_1.InternalError(errors.join("\n"));
}
return this.assignMultipleMetadata(models, response.map((r) => r.rev));
}
/**
* @description Deletes a document from the database
* @summary Removes a single document from the Nano database by its ID and returns the deleted document metadata
* @param {string} tableName - The name of the table/collection
* @param {string|number} id - The document identifier
* @return {Promise<Record<string, any>>} A promise that resolves to the deleted document with metadata
*/
async delete(tableName, id,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
const _id = this.generateId(decorator_validation_1.Model.tableName(tableName), id);
let record;
try {
record = await this.client.get(_id);
await this.client.destroy(_id, record._rev);
}
catch (e) {
throw this.parseError(e);
}
return this.assignMetadata(record, record._rev);
}
/**
* @description Deletes multiple documents from the database
* @summary Performs a bulk delete operation for the provided IDs and returns the deleted documents metadata
* @param {string} tableName - The name of the table/collection
* @param {Array<string|number|bigint>} ids - Array of document identifiers to delete
* @return {Promise<Array<Record<string, any>>>} A promise resolving to the deleted documents with metadata
*/
async deleteAll(tableName, ids, ...args) {
const { log } = this.logCtx(args, this.deleteAll);
const table = decorator_validation_1.Model.tableName(tableName);
const keys = ids.map((id) => this.generateId(table, id));
const results = await this.client.fetch({ keys }, { include_docs: true });
const docs = results.rows.map((row, index) => {
if (row.error)
throw new db_decorators_1.InternalError(row.error);
if (!row.doc)
throw new db_decorators_1.InternalError(`Unable to load document ${row.id ?? keys[index]}`);
return Object.assign({}, row.doc);
});
const deletion = await this.client.bulk({
docs: docs.map((doc) => ({
_id: doc[for_couchdb_1.CouchDBKeys.ID],
_rev: doc[for_couchdb_1.CouchDBKeys.REV],
[for_couchdb_1.CouchDBKeys.DELETED]: true,
})),
});
deletion.forEach((d, index) => {
if (d.error)
log.error(`Failed to delete document ${docs[index][for_couchdb_1.CouchDBKeys.ID]}: ${d.error} ${d.reason ? `- ${d.reason}` : ""}`);
});
return docs.map((doc) => this.assignMetadata({ ...doc }, doc[for_couchdb_1.CouchDBKeys.REV]));
}
/**
* @description Executes a raw Mango query against the database
* @summary Runs a Mango query using Nano's find API and optionally returns only the documents array
* @template R - The expected response or document array type
* @param {MangoQuery} rawInput - The Mango query to execute
* @param {boolean} [docsOnly=true] - Whether to return only the docs array or the full response
* @return {Promise<R>} A promise that resolves to the query result, shaped according to docsOnly
*/
async raw(rawInput, docsOnly = true, ...args) {
try {
const response = await this.client.find(rawInput);
if (response.warning) {
const { log } = this.logCtx(args, this.raw);
// Nano/CouchDB warnings here usually mean "no matching index found".
// Include the query details to make it actionable when it happens.
const details = {
warning: response.warning,
selector: rawInput?.selector,
sort: rawInput?.sort,
use_index: rawInput?.use_index,
fields: rawInput?.fields,
limit: rawInput?.limit,
skip: rawInput?.skip,
};
log.warn(`${response.warning} query=${JSON.stringify(details, null, 2)}`);
}
if (docsOnly)
return response.docs;
return response;
}
catch (e) {
throw this.parseError(e);
}
}
async view(ddoc, viewName, options, ..._args) {
void _args;
try {
return (await this.client.view(ddoc, viewName, options));
}
catch (e) {
throw this.parseError(e);
}
}
/**
* @description Establishes a connection to a Nano (CouchDB) server
* @summary Creates and returns a Nano ServerScope using the given credentials, host, and protocol
* @param {string} user - Username used for authentication
* @param {string} pass - Password used for authentication
* @param {string} [host="localhost:5984"] - Host and port of the CouchDB server
* @param {("http"|"https")} [protocol="http"] - Protocol to use for the connection
* @return {ServerScope} The Nano ServerScope connection
*/
static connect(user, pass, host = "localhost:5984", protocol = "http", agent) {
const requestDefaults = agent ? { agent } : undefined;
const con = (0, nano_1.default)({
url: `${protocol}://${user}:${pass}@${host}`,
...(requestDefaults ? { requestDefaults } : {}),
});
if (con && agent) {
con._decafAgent = agent;
}
return con;
}
/**
* @description Creates a new database on the Nano server
* @summary Creates a new database with the specified name on the connected Nano server
* @param {ServerScope} con - The Nano server connection
* @param {string} name - The name of the database to create
* @return {Promise<void>} A promise that resolves when the database is created
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Server
* A->>DB: db.create(name)
* alt Success
* DB-->>A: result with ok=true
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* else Not OK
* DB-->>A: result with ok=false
* A-->>A: throw parseError(error, reason)
* end
*/
static async createDatabase(con, name) {
let result;
try {
result = await con.db.create(name);
}
catch (e) {
throw for_couchdb_1.CouchDBAdapter.parseError(e);
}
const { ok, error, reason } = result;
if (!ok)
throw for_couchdb_1.CouchDBAdapter.parseError(error, reason);
}
/**
* @description Deletes a database from the Nano server
* @summary Removes an existing database with the specified name from the connected Nano server
* @param {ServerScope} con - The Nano server connection
* @param {string} name - The name of the database to delete
* @return {Promise<void>} A promise that resolves when the database is deleted
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant DB as Nano Server
* A->>DB: db.destroy(name)
* alt Success
* DB-->>A: result with ok=true
* else Error
* DB-->>A: error
* A-->>A: throw parseError(e)
* else Not OK
* DB-->>A: result with ok=false
* A-->>A: throw InternalError
* end
*/
static async deleteDatabase(con, name) {
let result;
try {
result = await con.db.destroy(name);
}
catch (e) {
throw for_couchdb_1.CouchDBAdapter.parseError(e);
}
const { ok } = result;
if (!ok)
throw new db_decorators_1.InternalError(`Failed to delete database with name ${name}`);
}
/**
* @description Closes the keep-alive agent associated with a Nano connection
* @summary Destroys the custom HTTP/HTTPS agent that was created during connection setup
* @param {ServerScope} con - The Nano server connection whose agent should be destroyed
*/
static closeConnection(con) {
if (!con)
return;
const agent = con?._decafAgent;
if (agent && typeof agent.destroy === "function") {
agent.destroy();
}
}
/**
* @description Creates a new user and grants access to a database
* @summary Creates a new user in the Nano server and configures security to grant the user access to a specific database
* @param {ServerScope} con - The Nano server connection
* @param {string} dbName - The name of the database to grant access to
* @param {string} user - The username to create
* @param {string} pass - The password for the new user
* @param {string[]} [roles=["reader", "writer"]] - The roles to assign to the user
* @return {Promise<void>} A promise that resolves when the user is created and granted access
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant U as _users Database
* participant S as Security API
* A->>A: Create user object
* A->>U: insert(user)
* alt Success
* U-->>A: response with ok=true
* A->>S: PUT _security with user permissions
* alt Security Success
* S-->>A: security response with ok=true
* else Security Failure
* S-->>A: security response with ok=false
* A-->>A: throw InternalError
* end
* else Error
* U-->>A: error
* A-->>A: throw parseError(e)
* else Not OK
* U-->>A: response with ok=false
* A-->>A: throw InternalError
* end
*/
static async createUser(con, dbName, user, pass, roles = ["reader", "writer"]) {
const users = con.db.use("_users");
const usr = {
_id: "org.couchdb.user:" + user,
name: user,
password: pass,
roles: roles,
type: "user",
};
try {
const created = await users.insert(usr);
const { ok } = created;
if (!ok)
throw new db_decorators_1.InternalError(`Failed to create user ${user}`);
const security = await con.request({
db: dbName,
method: "put",
path: "_security",
// headers: {
//
// },
body: {
admins: {
names: [user],
roles: [],
},
members: {
names: [user],
roles: roles,
},
},
});
if (!security.ok)
throw new db_decorators_1.InternalError(`Failed to authorize user ${user} to db ${dbName}`);
}
catch (e) {
throw for_couchdb_1.CouchDBAdapter.parseError(e);
}
}
/**
* @description Deletes a user from the Nano server
* @summary Removes an existing user from the Nano server
* @param {ServerScope} con - The Nano server connection
* @param {string} dbName - The name of the database (used for logging purposes)
* @param {string} user - The username to delete
* @return {Promise<void>} A promise that resolves when the user is deleted
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant U as _users Database
* A->>A: Generate user ID
* A->>U: get(id)
* U-->>A: user document
* A->>U: destroy(id, user._rev)
* alt Success
* U-->>A: success response
* else Error
* U-->>A: error
* A-->>A: throw parseError(e)
* end
*/
static async deleteUser(con, dbName, user) {
const users = con.db.use("_users");
const id = "org.couchdb.user:" + user;
try {
const usr = await users.get(id);
await users.destroy(id, usr._rev);
}
catch (e) {
throw for_couchdb_1.CouchDBAdapter.parseError(e);
}
}
/**
* @description Sets up decorations for Nano-specific model properties
* @summary Configures decorators for created_by and updated_by fields in models to be automatically
* populated with the user from the context when documents are created or updated
* @return {void}
* @mermaid
* sequenceDiagram
* participant A as NanoAdapter
* participant D as Decoration
* participant R as Repository
* A->>R: key(PersistenceKeys.CREATED_BY)
* R-->>A: createdByKey
* A->>D: flavouredAs("nano")
* A->>D: for(createdByKey)
* A->>D: define(onCreate(createdByOnNanoCreateUpdate), propMetadata)
* A->>D: apply()
* A->>R: key(PersistenceKeys.UPDATED_BY)
* R-->>A: updatedByKey
* A->>D: flavouredAs("nano")
* A->>D: for(updatedByKey)
* A->>D: define(onCreate(createdByOnNanoCreateUpdate), propMetadata)
* A->>D: apply()
*/
static decoration() {
super.decoration();
decoration_1.Decoration.flavouredAs(constants_js_1.NanoFlavour)
.for(core_1.PersistenceKeys.CREATED_BY)
.define((0, db_decorators_1.onCreate)(createdByOnNanoCreateUpdate), (0, decoration_1.propMetadata)(core_1.PersistenceKeys.CREATED_BY, {}))
.apply();
decoration_1.Decoration.flavouredAs(constants_js_1.NanoFlavour)
.for(core_1.PersistenceKeys.UPDATED_BY)
.define((0, db_decorators_1.onCreateUpdate)(createdByOnNanoCreateUpdate), (0, decoration_1.propMetadata)(core_1.PersistenceKeys.UPDATED_BY, {}))
.apply();
}
}
exports.NanoAdapter = NanoAdapter;
core_1.Adapter.setCurrent(constants_js_1.NanoFlavour);
//# sourceMappingURL=adapter.js.map
//# sourceMappingURL=adapter.cjs.map