@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
174 lines • 5.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = exports.DefaultContextFactory = void 0;
const constants_1 = require("./constants.cjs");
const typed_object_accumulator_1 = require("typed-object-accumulator");
const logging_1 = require("@decaf-ts/logging");
/**
* @description Default factory for creating context instances.
* @summary A factory function that creates new Context instances with the provided repository flags.
* It automatically adds a timestamp to the context and returns a properly typed context instance.
* @const DefaultContextFactory
* @memberOf module:db-decorators
*/
const DefaultContextFactory = (arg) => {
return new Context().accumulate(Object.assign({}, arg, {
timestamp: new Date(),
logger: arg.logger || logging_1.Logging.get(),
}));
};
exports.DefaultContextFactory = DefaultContextFactory;
/**
* @description A context management class for handling repository operations.
* @summary The Context class provides a mechanism for managing repository operations with flags,
* parent-child relationships, and state accumulation. It allows for hierarchical context chains
* and maintains operation-specific configurations while supporting type safety through generics.
*
* @template F - Type extending RepositoryFlags that defines the context configuration
*
* @param {ObjectAccumulator<F>} cache - The internal cache storing accumulated values
*
* @class
*
* @example
* ```typescript
* // Creating a new context with repository flags
* const context = new Context<RepositoryFlags>();
*
* // Accumulating values
* const enrichedContext = context.accumulate({
* writeOperation: true,
* affectedTables: ['users'],
* operation: OperationKeys.CREATE
* });
*
* // Accessing values
* const isWrite = enrichedContext.get('writeOperation'); // true
* const tables = enrichedContext.get('affectedTables'); // ['users']
* ```
*
* @mermaid
* sequenceDiagram
* participant C as Client
* participant Ctx as Context
* participant Cache as ObjectAccumulator
*
* C->>Ctx: new Context()
* Ctx->>Cache: create cache
*
* C->>Ctx: accumulate(value)
* Ctx->>Cache: accumulate(value)
* Cache-->>Ctx: updated cache
* Ctx-->>C: updated context
*
* C->>Ctx: get(key)
* Ctx->>Cache: get(key)
* alt Key exists in cache
* Cache-->>Ctx: value
* else Key not found
* Ctx->>Ctx: check parent context
* alt Parent exists
* Ctx->>Parent: get(key)
* Parent-->>Ctx: value
* else No parent
* Ctx-->>C: throw error
* end
* end
* Ctx-->>C: requested value
*/
class Context {
constructor(ctx) {
this.cache = new typed_object_accumulator_1.ObjectAccumulator();
Object.defineProperty(this, "cache", {
value: ctx ? ctx["cache"] : new typed_object_accumulator_1.ObjectAccumulator(),
writable: false,
enumerable: false,
configurable: true,
});
}
static { this.factory = exports.DefaultContextFactory; }
/**
* @description Accumulates new values into the context.
* @summary Merges the provided value object with the existing context state,
* creating a new immutable cache state.
*/
accumulate(value) {
Object.defineProperty(this, "cache", {
value: this.cache.accumulate(value),
writable: false,
enumerable: false,
configurable: true,
});
return this;
}
get logger() {
return this.cache.logger;
}
get timestamp() {
return this.cache.timestamp;
}
/**
* @description Retrieves a value from the context by key.
* @param {string} key
* @return {any}
*/
get(key) {
try {
return this.cache.get(key);
}
catch (e) {
const parent = this.cache.parentContext;
if (parent)
return parent.get(key);
throw e;
}
}
/**
* @description Creates a child context from another context
*/
static childFrom(context, overrides) {
return Context.factory(Object.assign({}, context.cache, overrides || {}));
}
/**
* @description Creates a new context from operation parameters
*/
static async from(operation, overrides, model,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...args) {
return Context.factory(Object.assign({}, constants_1.DefaultRepositoryFlags, overrides, {
operation: operation,
model: model,
logger: overrides.logger || logging_1.Logging.get(),
}));
}
/**
* @description Prepares arguments for context operations
*/
static async args(operation, model, args, contextual, overrides) {
const last = args.pop();
async function getContext() {
if (contextual)
return contextual.context(operation, overrides || {}, model, ...args);
return Context.from(operation, overrides || {}, model, ...args);
}
let c;
if (last) {
if (last instanceof Context) {
c = last;
args.push(last);
}
else {
args.push(last);
c = (await getContext());
args.push(c);
}
}
else {
c = (await getContext());
args.push(c);
}
return { context: c, args: args };
}
}
exports.Context = Context;
//# sourceMappingURL=Context.js.map