Comparing version 3.0.0-rc.4 to 3.0.0-rc.5
@@ -10,2 +10,10 @@ # Changelog | ||
## [3.0.0-rc.5] | ||
### Added | ||
- New `RecordNotFoundError` error was created to be thrown when a record cannot be found in the database. [#740](https://github.com/STORIS/mvom/pull/740) | ||
- New Increment operation is now supported on numeric fields. The operation will increment the value at the path specified by the amount specified and will return both the original and updated documents. [#750](https://github.com/STORIS/mvom/pull/750), [#757](https://github.com/STORIS/mvom/pull/757), [#758](https://github.com/STORIS/mvom/pull/758) | ||
- New internal unibasic subroutine `writeRecord` was created to be shared by `save` and `increment` operations for writes to the database. [#756](https://github.com/STORIS/mvom/pull/756) | ||
## [3.0.0-rc.4] | ||
@@ -495,3 +503,4 @@ | ||
[unreleased]: https://github.com/storis/mvom/compare/3.0.0-rc.4...HEAD | ||
[unreleased]: https://github.com/storis/mvom/compare/3.0.0-rc.5...HEAD | ||
[3.0.0-rc.5]: https://github.com/storis/mvom/compare/3.0.0-rc.4...3.0.0-rc.5 | ||
[3.0.0-rc.4]: https://github.com/storis/mvom/compare/3.0.0-rc.3...3.0.0-rc.4 | ||
@@ -498,0 +507,0 @@ [3.0.0-rc.3]: https://github.com/storis/mvom/compare/3.0.0-rc.2...3.0.0-rc.3 |
@@ -6,4 +6,5 @@ import type Connection from './Connection'; | ||
import type Schema from './Schema'; | ||
import type { InferModelObject } from './Schema'; | ||
import type { DbServerDelimiters, DbSubroutineUserDefinedOptions } from './types'; | ||
import type { FlattenDocument, InferModelObject, SchemaDefinition } from './Schema'; | ||
import type { SchemaTypeDefinitionNumber } from './schemaType'; | ||
import type { DbServerDelimiters, DbSubroutineInputIncrementOperation, DbSubroutineUserDefinedOptions } from './types'; | ||
export interface ModelConstructorOptions<TSchema extends Schema | null> { | ||
@@ -28,2 +29,6 @@ _id?: string | null; | ||
} | ||
export interface ModelIncrementResult<TSchema extends Schema | null> { | ||
originalDocument: ModelCompositeValue<TSchema>; | ||
updatedDocument: ModelCompositeValue<TSchema>; | ||
} | ||
export interface ModelDatabaseExecutionOptions { | ||
@@ -41,2 +46,18 @@ userDefined?: DbSubroutineUserDefinedOptions; | ||
} | ||
export interface ModelIncrementOptions extends ModelDatabaseExecutionOptions { | ||
/** | ||
* Number of retries to perform when record is locked | ||
* @defaultValue 5 | ||
*/ | ||
retry?: number; | ||
/** | ||
* Delay between retries in seconds when record is locked | ||
* @defaultValue 1 | ||
*/ | ||
retryDelay?: number; | ||
} | ||
export type IncrementOperation<TSchema extends Schema | null> = TSchema extends Schema ? { | ||
path: Extract<keyof FlattenDocument<TSchema, Schema | SchemaDefinition | SchemaTypeDefinitionNumber>, string>; | ||
value: number; | ||
} : never; | ||
export type ModelReadFileContentsByIdOptions = ModelDatabaseExecutionOptions; | ||
@@ -60,3 +81,3 @@ export type ModelSaveOptions = ModelDatabaseExecutionOptions; | ||
"__#2@#convertToMvString"(): string; | ||
_raw: TSchema extends Schema<import("./Schema").SchemaDefinition, Record<never, never>> ? never : import("./types").MvRecord; | ||
_raw: TSchema extends Schema<SchemaDefinition, Record<never, never>> ? never : import("./types").MvRecord; | ||
_transformationErrors: import("./errors").TransformDataError[]; | ||
@@ -91,2 +112,8 @@ readonly "__#1@#schema": TSchema; | ||
findByIds(ids: string | string[], options?: ModelFindByIdOptions): Promise<(ModelCompositeValue<TSchema> | null)[]>; | ||
/** | ||
* Increment fields in a document by values | ||
* @throws {Error} if schema is not defined | ||
* @throws {Error} if no result is returned from increment operation | ||
*/ | ||
increment(id: string, operations: IncrementOperation<TSchema>[], options?: ModelIncrementOptions): Promise<ModelIncrementResult<TSchema>>; | ||
/** Read a DIR file type record directly from file system as Base64 string by its id */ | ||
@@ -98,2 +125,6 @@ readFileContentsById(id: string, options?: ModelReadFileContentsByIdOptions): Promise<string>; | ||
"__#2@#formatProjection"(projection?: string[]): number[] | null; | ||
/** | ||
* Format increment operations to be sent to the database | ||
*/ | ||
"__#2@#formatIncrementOperations"(operations: IncrementOperation<TSchema>[]): DbSubroutineInputIncrementOperation[]; | ||
createSubdocumentFromRecord<TSchema_1 extends Schema | null>(schema: TSchema_1, record: import("./types").MvRecord): import("./Document").DocumentCompositeValue<TSchema_1>; | ||
@@ -100,0 +131,0 @@ createSubdocumentFromData<TSchema_1 extends Schema>(schema: TSchema_1, data: DocumentData<TSchema_1>): import("./Document").DocumentCompositeValue<TSchema_1>; |
@@ -265,2 +265,49 @@ "use strict"; | ||
/** | ||
* Increment fields in a document by values | ||
* @throws {Error} if schema is not defined | ||
* @throws {Error} if no result is returned from increment operation | ||
*/ | ||
static async increment(id, operations, options = {}) { | ||
const { | ||
maxReturnPayloadSize, | ||
requestId, | ||
userDefined, | ||
retry = 5, | ||
retryDelay = 1 | ||
} = options; | ||
const transformedOperations = this.#formatIncrementOperations(operations); | ||
const data = await this.connection.executeDbSubroutine('increment', { | ||
filename: this.file, | ||
id, | ||
operations: transformedOperations, | ||
retry, | ||
retryDelay | ||
}, { | ||
...(maxReturnPayloadSize != null && { | ||
maxReturnPayloadSize | ||
}), | ||
...(requestId != null && { | ||
requestId | ||
}), | ||
...(userDefined && { | ||
userDefined | ||
}) | ||
}); | ||
const { | ||
originalDocument: { | ||
__v: originalVersion, | ||
record: originalRecord | ||
}, | ||
updatedDocument: { | ||
__v: updatedVersion, | ||
record: updatedRecord | ||
} | ||
} = data; | ||
return { | ||
originalDocument: this.#createModelFromRecordString(originalRecord, id, originalVersion), | ||
updatedDocument: this.#createModelFromRecordString(updatedRecord, id, updatedVersion) | ||
}; | ||
} | ||
/** Read a DIR file type record directly from file system as Base64 string by its id */ | ||
@@ -304,2 +351,19 @@ static async readFileContentsById(id, options = {}) { | ||
/** | ||
* Format increment operations to be sent to the database | ||
*/ | ||
static #formatIncrementOperations(operations) { | ||
if (this.schema == null) { | ||
throw new Error('Schema must be defined to perform increment operations'); | ||
} | ||
const incrementSchema = this.schema; | ||
return operations.map(({ | ||
path, | ||
value | ||
}) => ({ | ||
path: incrementSchema.transformPathToOrdinalPosition(path), | ||
value | ||
})); | ||
} | ||
/** Save a document to the database */ | ||
@@ -306,0 +370,0 @@ async save(options = {}) { |
@@ -108,2 +108,3 @@ import type http from 'http'; | ||
* @throws {@link DbServerError} An error was encountered on the database server | ||
* @throws {@link RecordNotFoundError} A record was not found and could not be updated | ||
*/ | ||
@@ -110,0 +111,0 @@ private handleDbServerError; |
@@ -314,2 +314,3 @@ "use strict"; | ||
* @throws {@link DbServerError} An error was encountered on the database server | ||
* @throws {@link RecordNotFoundError} A record was not found and could not be updated | ||
*/ | ||
@@ -378,2 +379,14 @@ handleDbServerError(response, subroutineName, options, setupOptions) { | ||
} | ||
case _constants.dbErrors.recordNotFound.code: | ||
{ | ||
const { | ||
filename, | ||
id | ||
} = options; | ||
this.logHandler.debug(`record ${id} not found from ${filename} when incrementing`); | ||
throw new _errors.RecordNotFoundError({ | ||
filename, | ||
recordId: id | ||
}); | ||
} | ||
default: | ||
@@ -380,0 +393,0 @@ this.logHandler.error(`error code ${response.data.output.errorCode} occurred in database operation when calling ${subroutineName}`); |
@@ -5,5 +5,5 @@ export { default as Connection } from './Connection'; | ||
export { default as Schema, type SchemaDefinition, type DictionariesOption, type SchemaConstructorOptions, type ISOCalendarDate, type ISOCalendarDateTime, type ISOTime, type FlattenDocument, type InferDocumentObject, type InferModelObject, type InferSchemaPaths, } from './Schema'; | ||
export type { ModelConstructor, ModelConstructorOptions, Model, ModelCompositeValue, } from './compileModel'; | ||
export { MvisError, DataValidationError, DbServerError, ForeignKeyValidationError, InvalidParameterError, InvalidServerFeaturesError, RecordLockedError, RecordVersionError, TimeoutError, TransformDataError, UnknownError, } from './errors'; | ||
export type { ModelConstructor, ModelConstructorOptions, Model, ModelCompositeValue, IncrementOperation, ModelIncrementResult, } from './compileModel'; | ||
export { MvisError, DataValidationError, DbServerError, ForeignKeyValidationError, InvalidParameterError, InvalidServerFeaturesError, RecordLockedError, RecordNotFoundError, RecordVersionError, TimeoutError, TransformDataError, UnknownError, } from './errors'; | ||
export type { SchemaTypeDefinitionBoolean, SchemaTypeDefinitionISOCalendarDateTime, SchemaTypeDefinitionISOCalendarDate, SchemaTypeDefinitionISOTime, SchemaTypeDefinitionNumber, SchemaTypeDefinitionString, } from './schemaType'; | ||
export type { EncryptFn, DecryptFn } from './types'; |
@@ -61,2 +61,8 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "RecordNotFoundError", { | ||
enumerable: true, | ||
get: function () { | ||
return _errors.RecordNotFoundError; | ||
} | ||
}); | ||
Object.defineProperty(exports, "RecordVersionError", { | ||
@@ -63,0 +69,0 @@ enumerable: true, |
{ | ||
"name": "mvom", | ||
"private": false, | ||
"version": "3.0.0-rc.4", | ||
"version": "3.0.0-rc.5", | ||
"description": "Multivalue Object Mapper", | ||
@@ -6,0 +6,0 @@ "main": "index.js", |
@@ -76,3 +76,3 @@ import type { BaseSchemaType, SchemaTypeDefinitionBoolean, SchemaTypeDefinitionISOCalendarDate, SchemaTypeDefinitionISOCalendarDateTime, SchemaTypeDefinitionISOTime, SchemaTypeDefinitionNumber, SchemaTypeDefinitionScalar, SchemaTypeDefinitionString, SchemaTypePath } from './schemaType'; | ||
/** Infer the string keyPaths of a schema */ | ||
export type InferSchemaPaths<TSchema extends Schema> = keyof FlattenDocument<TSchema>; | ||
export type InferSchemaPaths<TSchema extends Schema> = Extract<keyof FlattenDocument<TSchema>, string>; | ||
/** Schema constructor */ | ||
@@ -103,2 +103,7 @@ declare class Schema<TSchemaDefinition extends SchemaDefinition = SchemaDefinition, TDictionaries extends DictionariesOption = Record<never, never>> { | ||
transformPathsToDbPositions(paths: string[]): number[]; | ||
/** | ||
* Transform the path to its ordinal position. Returning a '.' delimited string. Ex. "1.2.3" | ||
* @throws {Error} Invalid path provided | ||
*/ | ||
transformPathToOrdinalPosition(path: InferSchemaPaths<Schema<TSchemaDefinition, TDictionaries>>): `${number}.${number}.${number}`; | ||
/** Build the dictionary path map for additional dictionaries provided as schema options */ | ||
@@ -105,0 +110,0 @@ private buildDictionaryPaths; |
@@ -121,2 +121,16 @@ "use strict"; | ||
/** | ||
* Transform the path to its ordinal position. Returning a '.' delimited string. Ex. "1.2.3" | ||
* @throws {Error} Invalid path provided | ||
*/ | ||
transformPathToOrdinalPosition(path) { | ||
const positionPaths = this.getPositionPaths(); | ||
const ordinalPath = positionPaths.get(path); | ||
if (ordinalPath == null) { | ||
throw new Error('Invalid path provided'); | ||
} | ||
const [attributePosition, valuePosition = 0, subvaluePosition = 0] = ordinalPath; | ||
return `${attributePosition + 1}.${valuePosition + 1}.${subvaluePosition + 1}`; | ||
} | ||
/** Build the dictionary path map for additional dictionaries provided as schema options */ | ||
@@ -123,0 +137,0 @@ buildDictionaryPaths(dictionaries = {}) { |
@@ -41,2 +41,25 @@ import type { BuildForeignKeyDefinitionsResult } from '../Document'; | ||
} | ||
export interface DbSubroutineInputIncrementOperation { | ||
/** | ||
* Ordinal path to the field to increment ex. 1.2.3 | ||
*/ | ||
path: string; | ||
/** | ||
* Numeric value to increment by | ||
*/ | ||
value: number; | ||
} | ||
export interface DbSubroutineInputIncrement { | ||
filename: string; | ||
id: string; | ||
operations: DbSubroutineInputIncrementOperation[]; | ||
/** | ||
* Number of retries to perform | ||
*/ | ||
retry: number; | ||
/** | ||
* Delay between retries in seconds | ||
*/ | ||
retryDelay: number; | ||
} | ||
export interface DbSubroutineInputReadFileContentsById { | ||
@@ -54,3 +77,3 @@ filename: string; | ||
} | ||
export type DbActionSubroutineInputTypes = DbSubroutinePayload<DbSubroutineInputDeleteById | DbSubroutineInputFind | DbSubroutineInputFindById | DbSubroutineInputFindByIds | DbSubroutineInputReadFileContentsById | DbSubroutineInputGetServerInfo>; | ||
export type DbActionSubroutineInputTypes = DbSubroutinePayload<DbSubroutineInputDeleteById | DbSubroutineInputFind | DbSubroutineInputFindById | DbSubroutineInputFindByIds | DbSubroutineInputIncrement | DbSubroutineInputReadFileContentsById | DbSubroutineInputGetServerInfo>; | ||
export interface DbSubroutineInputOptionsMap { | ||
@@ -61,2 +84,3 @@ deleteById: DbSubroutineInputDeleteById; | ||
findByIds: DbSubroutineInputFindByIds; | ||
increment: DbSubroutineInputIncrement; | ||
readFileContentsById: DbSubroutineInputReadFileContentsById; | ||
@@ -63,0 +87,0 @@ getServerInfo: DbSubroutineInputGetServerInfo; |
@@ -27,2 +27,7 @@ import type { ForeignKeyValidationErrorData } from '../errors/ForeignKeyValidationError'; | ||
export type DbSubroutineResponseFindByIds = DbSubroutineResponse<DbSubroutineOutputFindByIds>; | ||
export interface DbSubroutineOutputIncrement { | ||
originalDocument: DbDocument; | ||
updatedDocument: DbDocument; | ||
} | ||
export type DbSubroutineResponseIncrement = DbSubroutineResponse<DbSubroutineOutputIncrement>; | ||
export interface DbSubroutineOutputReadFileContentsById { | ||
@@ -63,3 +68,3 @@ result: string; | ||
export type DbSubroutineResponseSave = DbSubroutineResponse<DbSubroutineOutputSave>; | ||
export type DbSubroutineResponseTypes = DbSubroutineResponseDeleteById | DbSubroutineResponseFind | DbSubroutineResponseFindById | DbSubroutineResponseFindByIds | DbSubroutineResponseReadFileContentsById | DbSubroutineResponseGetServerInfo | DbSubroutineResponseSave; | ||
export type DbSubroutineResponseTypes = DbSubroutineResponseDeleteById | DbSubroutineResponseFind | DbSubroutineResponseFindById | DbSubroutineResponseFindByIds | DbSubroutineResponseIncrement | DbSubroutineResponseReadFileContentsById | DbSubroutineResponseGetServerInfo | DbSubroutineResponseSave; | ||
export interface DbSubroutineResponseTypesMap { | ||
@@ -70,2 +75,3 @@ deleteById: DbSubroutineResponseDeleteById; | ||
findByIds: DbSubroutineResponseFindByIds; | ||
increment: DbSubroutineResponseIncrement; | ||
readFileContentsById: DbSubroutineResponseReadFileContentsById; | ||
@@ -72,0 +78,0 @@ getServerInfo: DbSubroutineResponseGetServerInfo; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
304327
5460