@fjell/lib
Version:
Server-side Library for Fjell
698 lines (670 loc) • 22.7 kB
JavaScript
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// src/errors.ts
import { abbrevIK } from "@fjell/core";
var LibError = class _LibError extends Error {
operation;
coordinate;
constructor(message, operation, coordinate, options) {
super(`${message} - ${coordinate} - ${operation}`, options);
this.operation = operation;
this.coordinate = coordinate;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, _LibError);
}
}
};
var NotFoundError = class extends LibError {
key;
constructor(operation, coordinate, key, options) {
super(`Item not found for key - ${abbrevIK(key)}`, operation, coordinate, options);
this.key = key;
}
};
var NotUpdatedError = class extends LibError {
key;
constructor(operation, coordinate, key, options) {
super(`Item not updated for key ${abbrevIK(key)}`, operation, coordinate, options);
this.key = key;
}
};
var ValidationError = class extends LibError {
constructor(message, operation, coordinate, options) {
super(`Validation failed: ${message}`, operation, coordinate, options);
}
};
var CreateValidationError = class extends ValidationError {
constructor(parameters, coordinate, options) {
super(
`Create Validation Failed: ${JSON.stringify(parameters)}`,
"create",
coordinate,
options
);
}
};
var UpdateValidationError = class extends ValidationError {
constructor(parameters, coordinate, options) {
super(
`Update Validation Failed: ${JSON.stringify(parameters)}`,
"update",
coordinate,
options
);
}
};
var RemoveValidationError = class extends ValidationError {
constructor(parameters, coordinate, options) {
const keyInfo = parameters.key ? `key: ${abbrevIK(parameters.key)}` : "key: undefined";
super(
`Remove Validation Failed: ${keyInfo}`,
"remove",
coordinate,
options
);
}
};
var UpdateError = class extends LibError {
constructor(parameters, coordinate, options) {
const keyInfo = parameters.key ? `key: ${abbrevIK(parameters.key)}` : "key: undefined";
super(
`Update Failed: ${keyInfo}`,
"update",
coordinate,
options
);
}
};
var RemoveError = class extends LibError {
constructor(parameters, coordinate, options) {
const keyInfo = parameters.key ? `key: ${abbrevIK(parameters.key)}` : "key: undefined";
super(
`Remove Failed: ${keyInfo}`,
"remove",
coordinate,
options
);
}
};
var HookError = class extends LibError {
constructor(message, operation, coordinate, options) {
super(`${message}`, operation, coordinate, options);
}
};
// src/logger.ts
import Logging from "@fjell/logging";
var LibLogger = Logging.getLogger("@fjell/lib");
var logger_default = LibLogger;
// src/Library.ts
import { createInstance as createBaseInstance } from "@fjell/registry";
var logger = logger_default.get("Library");
var createLibrary = (registry, coordinate, operations, options) => {
logger.debug("createLibrary", { coordinate, operations, registry, options });
const baseInstance = createBaseInstance(registry, coordinate);
return { ...baseInstance, operations, options: options || {} };
};
var isLibrary = (library) => {
return library !== null && library !== void 0 && library.coordinate !== void 0 && library.operations !== void 0 && library.options !== void 0 && library.registry !== void 0;
};
// src/LibraryFactory.ts
var logger2 = logger_default.get("InstanceFactory");
var createLibraryFactory = (operations, options) => {
return (coordinate, context) => {
logger2.debug("Creating lib instance", { coordinate, registry: context.registry, operations, options });
return createLibrary(context.registry, coordinate, operations, options);
};
};
// src/ops/all.ts
var logger3 = logger_default.get("library", "ops", "all");
var wrapAllOperation = (toWrap, options, coordinate, registry) => {
const all = async (itemQuery, locations) => {
logger3.default("getAllOperation", { itemQuery, locations });
const items = await toWrap.all(itemQuery, locations);
logger3.default("getAllOperation: %j", { items });
return items;
};
return all;
};
// src/ops/create.ts
var logger4 = logger_default.get("library", "ops", "create");
var wrapCreateOperation = (toWrap, options, coordinate, registry) => {
const libOptions = options;
const create = async (item, options2) => {
logger4.default("create", { item, options: options2 });
let itemToCreate = item;
itemToCreate = await runPreCreateHook(itemToCreate, options2);
await validateCreate(itemToCreate, options2);
let createdItem = await toWrap.create(itemToCreate, options2);
createdItem = await runPostCreateHook(createdItem);
logger4.default("created item: %j", { createdItem });
return createdItem;
};
async function runPreCreateHook(item, options2) {
let itemToCreate = item;
if (libOptions?.hooks?.preCreate) {
try {
logger4.default("Running preCreate hook", { item: itemToCreate, options: options2 });
itemToCreate = await libOptions.hooks.preCreate(itemToCreate, options2);
} catch (error) {
throw new HookError(
"Error in preCreate",
"create",
coordinate,
{ cause: error }
);
}
} else {
logger4.default("No preCreate hook found, returning.");
}
return itemToCreate;
}
async function runPostCreateHook(createdItem) {
if (libOptions?.hooks?.postCreate) {
try {
logger4.default("Running postCreate hook", { item: createdItem });
createdItem = await libOptions.hooks.postCreate(createdItem);
} catch (error) {
throw new HookError(
"Error in postCreate",
"create",
coordinate,
{ cause: error }
);
}
} else {
logger4.default("No postCreate hook found, returning.");
}
return createdItem;
}
async function validateCreate(item, options2) {
if (!libOptions?.validators?.onCreate) {
logger4.default("No validator found for create, returning.");
return;
}
try {
logger4.default("Validating create", { item, options: options2 });
const isValid = await libOptions.validators.onCreate(item, options2);
if (!isValid) {
throw new CreateValidationError(
{ item, options: options2 },
coordinate,
{ cause: new Error("Invalid item") }
);
}
} catch (error) {
throw new CreateValidationError(
{ item, options: options2 },
coordinate,
{ cause: error }
);
}
}
return create;
};
// src/ops/find.ts
var logger5 = logger_default.get("library", "ops", "find");
var wrapFindOperation = (toWrap, options, coordinate, registry) => {
const { finders } = options || {};
const find = async (finder, finderParams, locations) => {
logger5.default("find", { finder, finderParams, locations });
if (!finders?.[finder]) {
throw new Error(`Finder ${finder} not found in definition for ${coordinate.toString()}`);
}
const foundItems = await toWrap.find(finder, finderParams, locations);
logger5.default("found items: %j", { foundItems });
return foundItems;
};
return find;
};
// src/ops/findOne.ts
var logger6 = logger_default.get("library", "ops", "one");
var wrapFindOneOperation = (toWrap, options, coordinate, registry) => {
const findOne = async (finder, finderParams, locations) => {
logger6.default("find", { finder, finderParams, locations });
const foundItems = await toWrap.findOne(finder, finderParams, locations);
logger6.default("found items: %j", { foundItems });
return foundItems;
};
return findOne;
};
// src/ops/get.ts
var logger7 = logger_default.get("library", "ops", "get");
var wrapGetOperation = (toWrap, options, coordinate, registry) => {
const get = async (key) => {
logger7.default("get", { key });
const item = await toWrap.get(key);
logger7.default("get: %j", { item });
return item;
};
return get;
};
// src/ops/one.ts
var logger8 = logger_default.get("library", "ops", "one");
var wrapOneOperation = (toWrap, options, coordinate, registry) => {
const one = async (itemQuery, locations = []) => {
logger8.default("one", { itemQuery, locations });
const item = await toWrap.one(itemQuery, locations);
logger8.default("one: %j", { item });
return item;
};
return one;
};
// src/ops/remove.ts
var logger9 = logger_default.get("library", "ops", "remove");
var wrapRemoveOperation = (toWrap, options, coordinate, registry) => {
const remove = async (key) => {
logger9.default("Removing item", { key });
await runPreRemoveHook(key);
await validateRemove(key);
const item = await toWrap.remove(key);
if (!item) {
throw new RemoveError({ key }, coordinate);
}
await runPostRemoveHook(item);
logger9.default("removed item: %j", { item });
return item;
};
async function runPreRemoveHook(key) {
if (options?.hooks?.preRemove) {
try {
logger9.default("Running preRemove hook", { key });
await options.hooks.preRemove(key);
} catch (error) {
throw new HookError("preRemove", "remove", coordinate, { cause: error });
}
} else {
logger9.default("No preRemove hook found, returning.");
}
}
async function runPostRemoveHook(item) {
if (options?.hooks?.postRemove) {
try {
logger9.default("Running postRemove hook", { item });
await options.hooks.postRemove(item);
} catch (error) {
throw new HookError("postRemove", "remove", coordinate, { cause: error });
}
} else {
logger9.default("No postRemove hook found, returning.");
}
}
async function validateRemove(key) {
if (!options?.validators?.onRemove) {
logger9.default("No validator found for remove, returning.");
return;
}
try {
logger9.default("Validating remove", { key });
const isValid = await options.validators.onRemove(key);
if (!isValid) {
throw new RemoveValidationError(
{ key },
coordinate,
{ cause: new Error("Error validating remove") }
);
}
} catch (error) {
throw new RemoveValidationError(
{ key },
coordinate,
{ cause: error }
);
}
}
return remove;
};
// src/ops/update.ts
var logger10 = logger_default.get("library", "ops", "update");
var wrapUpdateOperation = (toWrap, options, coordinate, registry) => {
const update = async (key, item) => {
logger10.default("update", { key, item });
let itemToUpdate = item;
itemToUpdate = await runPreUpdateHook(key, itemToUpdate);
await validateUpdate(key, itemToUpdate);
try {
logger10.default("Updating item", { key, item: itemToUpdate });
let updatedItem = await toWrap.update(key, itemToUpdate);
updatedItem = await runPostUpdateHook(updatedItem);
logger10.default("updated item: %j", { updatedItem });
return updatedItem;
} catch (error) {
throw new UpdateError(
{ key, item: itemToUpdate },
coordinate,
{ cause: error }
);
}
};
async function runPreUpdateHook(key, itemToUpdate) {
logger10.debug("Running Pre Update Hook");
if (options?.hooks?.preUpdate) {
try {
logger10.default("Running preUpdate hook", { key, item: itemToUpdate });
itemToUpdate = await options.hooks.preUpdate(key, itemToUpdate);
} catch (error) {
throw new HookError(
"Error in preUpdate",
"update",
coordinate,
{ cause: error }
);
}
} else {
logger10.default("No preUpdate hook found, returning.");
}
return itemToUpdate;
}
async function runPostUpdateHook(updatedItem) {
logger10.debug("Running Post Update Hook");
if (options?.hooks?.postUpdate) {
try {
logger10.default("Running postUpdate hook", { item: updatedItem });
updatedItem = await options.hooks.postUpdate(updatedItem);
} catch (error) {
throw new HookError(
"Error in postUpdate",
"update",
coordinate,
{ cause: error }
);
}
} else {
logger10.default("No postUpdate hook found, returning.");
}
return updatedItem;
}
async function validateUpdate(key, itemToUpdate) {
logger10.debug("Validating update");
if (!options?.validators?.onUpdate) {
logger10.default("No validator found for update, returning.");
return;
}
try {
logger10.debug("Validating update", { key, item: itemToUpdate });
const isValid = await options.validators.onUpdate(key, itemToUpdate);
if (!isValid) {
throw new UpdateValidationError(
{ key, item: itemToUpdate },
coordinate,
{ cause: new Error("Invalid item") }
);
}
} catch (error) {
throw new UpdateValidationError(
{ key, item: itemToUpdate },
coordinate,
{ cause: error }
);
}
}
return update;
};
// src/ops/upsert.ts
var logger11 = logger_default.get("ops", "upsert");
var wrapUpsertOperation = (ops, registry) => {
const retrieveOrCreateWithKey = async (key, itemProperties) => {
let item = null;
try {
logger11.default("Retrieving Item by Key", { key });
item = await ops.get(key);
} catch (error) {
if (error instanceof NotFoundError) {
logger11.default("Item not found, creating new item", { key });
item = await ops.create(itemProperties, { key });
} else {
throw error;
}
}
return item;
};
const upsert = async (key, itemProperties) => {
let item = null;
item = await retrieveOrCreateWithKey(key, itemProperties);
logger11.debug("Updating Item", { key: item.key, itemProperties });
item = await ops.update(item.key, itemProperties);
logger11.default("updated item: %j", { item });
return item;
};
return upsert;
};
// src/ops/action.ts
var logger12 = logger_default.get("library", "ops", "action");
var wrapActionOperation = (toWrap, options, coordinate, registry) => {
const { actions } = options || {};
const action = async (key, actionKey, actionParams) => {
logger12.debug("action", { key, actionKey, actionParams });
if (!actions?.[actionKey]) {
throw new Error(`Action ${actionKey} not found in definition`);
}
const actionMethod = actions[actionKey];
const item = await toWrap.get(key);
return actionMethod(item, actionParams);
};
return action;
};
// src/ops/facet.ts
var logger13 = logger_default.get("library", "ops", "facet");
var wrapFacetOperation = (toWrap, options, coordinate, registry) => {
const { facets } = options || {};
const facet = async (key, facetKey, facetParams) => {
logger13.debug("facet for item key: %j, facet key: %s, params: %j", key, facetKey, facetParams);
if (!facets?.[facetKey]) {
throw new Error(`Facet ${facetKey} not found in definition for ${coordinate.toString()}`);
}
const facetMethod = facets[facetKey];
logger13.debug("Getting Item for Facet by key: %j", key);
const item = await toWrap.get(key);
return facetMethod(item, facetParams);
};
return facet;
};
// src/ops/allAction.ts
var logger14 = logger_default.get("library", "ops", "allAction");
var wrapAllActionOperation = (toWrap, options, coordinate, registry) => {
const { allActions } = options || {};
const allAction = async (allActionKey, allActionParams, locations) => {
logger14.debug("allAction", { allActionKey, allActionParams, locations });
if (!allActions?.[allActionKey]) {
throw new Error(`AllAction ${allActionKey} not found in definition`);
}
const allActionMethod = allActions[allActionKey];
return allActionMethod(allActionParams, locations);
};
return allAction;
};
// src/ops/allFacet.ts
var logger15 = logger_default.get("library", "ops", "allFacet");
var wrapAllFacetOperation = (toWrap, options, coordinate, registry) => {
const { allFacets } = options || {};
const allFacet = async (allFacetKey, allFacetParams, locations) => {
logger15.debug("allFacet", { allFacetKey, allFacetParams, locations });
if (!allFacets?.[allFacetKey]) {
throw new Error(`AllFacet ${allFacetKey} not found in definition`);
}
const allFacetMethod = allFacets[allFacetKey];
return allFacetMethod(allFacetParams, locations);
};
return allFacet;
};
// src/Operations.ts
var logger16 = logger_default.get("Operations");
var wrapOperations = (toWrap, options, coordinate, registry) => {
const operations = {};
operations.all = wrapAllOperation(toWrap, options, coordinate, registry);
operations.one = wrapOneOperation(toWrap, options, coordinate, registry);
operations.create = wrapCreateOperation(toWrap, options, coordinate, registry);
operations.update = wrapUpdateOperation(toWrap, options, coordinate, registry);
operations.get = wrapGetOperation(toWrap, options, coordinate, registry);
operations.remove = wrapRemoveOperation(toWrap, options, coordinate, registry);
operations.find = wrapFindOperation(toWrap, options, coordinate, registry);
operations.findOne = wrapFindOneOperation(toWrap, options, coordinate, registry);
operations.upsert = wrapUpsertOperation(operations, registry);
operations.action = wrapActionOperation(toWrap, options, coordinate, registry);
operations.facet = wrapFacetOperation(toWrap, options, coordinate, registry);
operations.allAction = wrapAllActionOperation(toWrap, options, coordinate, registry);
operations.allFacet = wrapAllFacetOperation(toWrap, options, coordinate, registry);
operations.finders = { ...toWrap.finders, ...options.finders };
operations.actions = { ...toWrap.actions, ...options.actions };
operations.facets = { ...toWrap.facets, ...options.facets };
operations.allActions = { ...toWrap.allActions, ...options.allActions };
operations.allFacets = { ...toWrap.allFacets, ...options.allFacets };
return operations;
};
var createReadOnlyOperations = (toWrap) => {
logger16.debug("createReadOnlyOperations", { toWrap });
const create = async (item, options) => {
logger16.warning("create", "Cannot Create in a ReadOnly Library, Returning Empty Item");
return {};
};
const update = async (key, item) => {
logger16.warning("update", "Cannot Update in a ReadOnly Library, Returning Empty Item");
return {};
};
const upsert = async (key, itemProperties, locations) => {
logger16.warning("upsert", "Cannot Upsert in a ReadOnly Library, Returning Empty Item");
return {};
};
const remove = async (key) => {
logger16.warning("remove", "Cannot Remove in a ReadOnly Library, Returning Empty Item");
return {};
};
return {
...toWrap,
create,
update,
upsert,
remove
};
};
// src/Options.ts
import deepmerge from "deepmerge";
var logger17 = logger_default.get("Options");
var createDefaultOptions = () => {
logger17.debug("createDefaultOptions");
function clearAggs(item) {
delete item.aggs;
return item;
}
return {
hooks: {
// TODO: "We need to figure out how to make this an array of hooks..."
preCreate: async (item, options) => {
const retItem = clearAggs(item);
return retItem;
},
// TODO: "We need to figure out how to make this an array of hooks..."
preUpdate: async (key, item) => {
const retItem = clearAggs(item);
return retItem;
}
}
};
};
var createOptions = (options) => {
const defaultOptions = createDefaultOptions();
return deepmerge(defaultOptions, options ?? {});
};
// src/Registry.ts
import {
createRegistry as createBaseRegistry
} from "@fjell/registry";
var logger18 = logger_default.get("LibRegistry");
var createRegistryFactory = () => {
return (type, registryHub) => {
if (type !== "lib") {
throw new Error(`LibRegistryFactory can only create 'lib' type registries, got: ${type}`);
}
logger18.debug("Creating lib registry", { type, registryHub });
const baseRegistry = createBaseRegistry(type, registryHub);
return baseRegistry;
};
};
var createRegistry = (registryHub) => {
const baseRegistry = createBaseRegistry("lib", registryHub);
return {
...baseRegistry
};
};
// src/primary/index.ts
var primary_exports = {};
__export(primary_exports, {
createLibrary: () => createLibrary2,
wrapOperations: () => wrapOperations2
});
// src/primary/Library.ts
var logger19 = logger_default.get("primary", "Instance");
var createLibrary2 = (registry, coordinate, operations, options) => {
logger19.debug("createLibrary", { coordinate, operations, registry, options });
const library = createLibrary(registry, coordinate, operations, options);
if (!library) {
return library;
}
return {
...library,
operations
};
};
// src/primary/Operations.ts
var logger20 = logger_default.get("primary", "Operations");
var wrapOperations2 = (toWrap, options, coordinate, registry) => {
logger20.debug("wrapOperations", { toWrap, options, coordinate, registry });
return {
...wrapOperations(toWrap, options, coordinate, registry)
};
};
// src/contained/index.ts
var contained_exports = {};
__export(contained_exports, {
createLibrary: () => createLibrary3,
createOptions: () => createOptions2,
wrapOperations: () => wrapOperations3
});
// src/contained/Library.ts
var createLibrary3 = (parent, registry, coordinate, operations, options) => {
const library = createLibrary(registry, coordinate, operations, options);
return {
...library,
parent
};
};
// src/contained/Operations.ts
var wrapOperations3 = (toWrap, options, coordinate, registry) => {
const operations = wrapOperations(toWrap, options, coordinate, registry);
return {
...operations
};
};
// src/contained/Options.ts
var createOptions2 = (libOptions) => {
const options = createOptions(libOptions);
return {
...options
};
};
export {
contained_exports as Contained,
CreateValidationError,
HookError,
LibError,
NotFoundError,
NotUpdatedError,
primary_exports as Primary,
RemoveError,
RemoveValidationError,
UpdateError,
UpdateValidationError,
ValidationError,
createDefaultOptions,
createLibrary,
createLibraryFactory,
createOptions,
createReadOnlyOperations,
createRegistry,
createRegistryFactory,
isLibrary,
wrapOperations
};
//# sourceMappingURL=index.js.map