Repository: jeremydaly/dynamodb-toolbox
Pull request #703 (2024-04-05 17:54:59)

Move paths to actions


Patch:
diff --git a/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.ts b/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.ts
index 46c9ece7..1922ecb1 100644
--- a/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.ts
+++ b/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.ts
@@ -11,7 +11,7 @@ export const $key = Symbol('$key')
 export class BatchDeleteItemRequest<ENTITY extends EntityV2 = EntityV2>
   extends EntityAction<ENTITY>
   implements BatchWriteItemRequest<ENTITY, 'DeleteRequest'> {
-  static operationName = 'deleteBatch' as const;
+  static actionName = 'deleteBatch' as const;
 
   [$key]?: KeyInput<ENTITY>
 
@@ -28,7 +28,7 @@ export class BatchDeleteItemRequest<ENTITY extends EntityV2 = EntityV2>
 
   params() {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'DeleteItemCommand incomplete: Missing "key" property'
       })
     }
diff --git a/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.ts b/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.ts
index a6503f33..aaed3d3a 100644
--- a/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.ts
+++ b/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.ts
@@ -10,7 +10,7 @@ export const $item = Symbol('$item')
 export class BatchPutItemRequest<ENTITY extends EntityV2 = EntityV2>
   extends EntityAction<ENTITY>
   implements BatchWriteItemRequest<ENTITY, 'PutRequest'> {
-  static operationName = 'putBatch' as const;
+  static actionName = 'putBatch' as const;
 
   [$item]?: PutItemInput<ENTITY>
 
@@ -27,7 +27,7 @@ export class BatchPutItemRequest<ENTITY extends EntityV2 = EntityV2>
 
   params() {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'PutBatchItemCommand incomplete: Missing "item" property'
       })
     }
diff --git a/src/v1/entity/actions/batchWrite/batchWrite.ts b/src/v1/entity/actions/batchWrite/batchWrite.ts
index f2664e9d..79444e69 100644
--- a/src/v1/entity/actions/batchWrite/batchWrite.ts
+++ b/src/v1/entity/actions/batchWrite/batchWrite.ts
@@ -12,7 +12,8 @@ import { BatchWriteItemRequest, $requestType } from './BatchWriteItemRequest'
 import type { BatchWriteOptions } from './options'
 import { parseBatchWriteOptions } from './parseBatchWriteOptions'
 
-/** Run a `BatchWriteItem` operation
+/**
+ * Send a collection of `BatchWriteItemRequest`
  *
  * @param requests
  * @param options
@@ -41,7 +42,7 @@ export const getBatchWriteCommandInput = (
   const RequestItems: NonNullable<BatchWriteCommandInput>['RequestItems'] = {}
 
   if (requests.length === 0) {
-    throw new DynamoDBToolboxError('operations.incompleteOperation', {
+    throw new DynamoDBToolboxError('actions.incompleteAction', {
       message: 'BatchWrite command incomplete: No items supplied'
     })
   }
diff --git a/src/v1/entity/actions/batchWrite/options.ts b/src/v1/entity/actions/batchWrite/options.ts
index bc3b18bf..c93737d7 100644
--- a/src/v1/entity/actions/batchWrite/options.ts
+++ b/src/v1/entity/actions/batchWrite/options.ts
@@ -1,4 +1,7 @@
-import type { CapacityOptions } from 'v1/operations/constants/options/capacity'
-import type { MetricsOptions } from 'v1/operations/constants/options/metrics'
+import type { CapacityOption } from 'v1/options/capacity'
+import type { MetricsOption } from 'v1/options/metrics'
 
-export interface BatchWriteOptions extends CapacityOptions, MetricsOptions {}
+export interface BatchWriteOptions {
+  capacity?: CapacityOption
+  metrics?: MetricsOption
+}
diff --git a/src/v1/entity/actions/batchWrite/parseBatchWriteOptions.ts b/src/v1/entity/actions/batchWrite/parseBatchWriteOptions.ts
index 00e0cb8f..b2b4178d 100644
--- a/src/v1/entity/actions/batchWrite/parseBatchWriteOptions.ts
+++ b/src/v1/entity/actions/batchWrite/parseBatchWriteOptions.ts
@@ -1,8 +1,8 @@
 import type { BatchWriteCommandInput } from '@aws-sdk/lib-dynamodb'
 
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseMetricsOption } from 'v1/operations/utils/parseOptions/parseMetricsOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseMetricsOption } from 'v1/options/metrics'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import type { BatchWriteOptions } from './options'
 
diff --git a/src/v1/entity/actions/commands/deleteItem/deleteItemCommand.ts b/src/v1/entity/actions/commands/deleteItem/deleteItemCommand.ts
index df328380..be80b156 100644
--- a/src/v1/entity/actions/commands/deleteItem/deleteItemCommand.ts
+++ b/src/v1/entity/actions/commands/deleteItem/deleteItemCommand.ts
@@ -4,10 +4,7 @@ import { DeleteCommandInput, DeleteCommand, DeleteCommandOutput } from '@aws-sdk
 import { EntityV2, EntityAction, $entity } from 'v1/entity'
 import { EntityFormatter, FormattedItem } from 'v1/entity/actions/format'
 import type { KeyInput } from 'v1/entity/actions/tParse'
-import type {
-  NoneReturnValuesOption,
-  AllOldReturnValuesOption
-} from 'v1/operations/constants/options/returnValues'
+import type { NoneReturnValuesOption, AllOldReturnValuesOption } from 'v1/options/returnValues'
 import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { DeleteItemOptions, DeleteItemCommandReturnValuesOption } from './options'
@@ -42,7 +39,7 @@ export class DeleteItemCommand<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends DeleteItemOptions<ENTITY> = DeleteItemOptions<ENTITY>
 > extends EntityAction<ENTITY> {
-  static operationName = 'delete' as const;
+  static actionName = 'delete' as const;
 
   [$key]?: KeyInput<ENTITY>;
   [$options]?: OPTIONS
@@ -65,7 +62,7 @@ export class DeleteItemCommand<
 
   params(): DeleteCommandInput {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'DeleteItemCommand incomplete: Missing "key" property'
       })
     }
diff --git a/src/v1/entity/actions/commands/deleteItem/deleteItemParams/parseDeleteItemOptions.ts b/src/v1/entity/actions/commands/deleteItem/deleteItemParams/parseDeleteItemOptions.ts
index 8e508cc2..148f84db 100644
--- a/src/v1/entity/actions/commands/deleteItem/deleteItemParams/parseDeleteItemOptions.ts
+++ b/src/v1/entity/actions/commands/deleteItem/deleteItemParams/parseDeleteItemOptions.ts
@@ -3,10 +3,10 @@ import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseMetricsOption } from 'v1/operations/utils/parseOptions/parseMetricsOption'
-import { parseReturnValuesOption } from 'v1/operations/utils/parseOptions/parseReturnValuesOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseMetricsOption } from 'v1/options/metrics'
+import { parseReturnValuesOption } from 'v1/options/returnValues'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import { deleteItemCommandReturnValuesOptionsSet, DeleteItemOptions } from '../options'
 
diff --git a/src/v1/entity/actions/commands/deleteItem/options.ts b/src/v1/entity/actions/commands/deleteItem/options.ts
index 06aad24d..8c7d1c5d 100644
--- a/src/v1/entity/actions/commands/deleteItem/options.ts
+++ b/src/v1/entity/actions/commands/deleteItem/options.ts
@@ -1,9 +1,6 @@
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
-import type { MetricsOption } from 'v1/operations/constants/options/metrics'
-import type {
-  NoneReturnValuesOption,
-  AllOldReturnValuesOption
-} from 'v1/operations/constants/options/returnValues'
+import type { CapacityOption } from 'v1/options/capacity'
+import type { MetricsOption } from 'v1/options/metrics'
+import type { NoneReturnValuesOption, AllOldReturnValuesOption } from 'v1/options/returnValues'
 import type { EntityV2 } from 'v1/entity'
 import type { EntityCondition } from 'v1/entity/actions/parseCondition'
 
diff --git a/src/v1/entity/actions/commands/getItem/getItemCommand.ts b/src/v1/entity/actions/commands/getItem/getItemCommand.ts
index ddd79ea5..e35bfd5b 100644
--- a/src/v1/entity/actions/commands/getItem/getItemCommand.ts
+++ b/src/v1/entity/actions/commands/getItem/getItemCommand.ts
@@ -36,7 +36,7 @@ export class GetItemCommand<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends GetItemOptions<ENTITY> = GetItemOptions<ENTITY>
 > extends EntityAction<ENTITY> {
-  static operationName = 'get' as const;
+  static actionName = 'get' as const;
 
   [$key]?: KeyInput<ENTITY>;
   [$options]: OPTIONS
@@ -59,7 +59,7 @@ export class GetItemCommand<
 
   params(): GetCommandInput {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'GetItemCommand incomplete: Missing "key" property'
       })
     }
diff --git a/src/v1/entity/actions/commands/getItem/getItemParams/parseGetItemOptions.ts b/src/v1/entity/actions/commands/getItem/getItemParams/parseGetItemOptions.ts
index e32a7d02..675f9dda 100644
--- a/src/v1/entity/actions/commands/getItem/getItemParams/parseGetItemOptions.ts
+++ b/src/v1/entity/actions/commands/getItem/getItemParams/parseGetItemOptions.ts
@@ -2,10 +2,10 @@ import type { GetCommandInput } from '@aws-sdk/lib-dynamodb'
 import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
-import { parseConsistentOption } from 'v1/operations/utils/parseOptions/parseConsistentOption'
-import { parseProjection } from 'v1/operations/expression/projection/parse'
+import { EntityPathParser } from 'v1/entity/actions/parsePaths'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
+import { parseConsistentOption } from 'v1/options/consistent'
 
 import type { GetItemOptions } from '../options'
 
@@ -28,7 +28,10 @@ export const parseGetItemOptions = <ENTITY extends EntityV2>(
   }
 
   if (attributes !== undefined) {
-    const { ExpressionAttributeNames, ProjectionExpression } = parseProjection(entity, attributes)
+    const { ExpressionAttributeNames, ProjectionExpression } = entity
+      .build(EntityPathParser)
+      .parse(attributes)
+      .toCommandOptions()
 
     if (!isEmpty(ExpressionAttributeNames)) {
       commandOptions.ExpressionAttributeNames = ExpressionAttributeNames
diff --git a/src/v1/entity/actions/commands/getItem/options.ts b/src/v1/entity/actions/commands/getItem/options.ts
index db8b1174..ad165511 100644
--- a/src/v1/entity/actions/commands/getItem/options.ts
+++ b/src/v1/entity/actions/commands/getItem/options.ts
@@ -1,6 +1,6 @@
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPaths } from 'v1/entity/actions/paths'
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
+import type { CapacityOption } from 'v1/options/capacity'
 
 export interface GetItemOptions<ENTITY extends EntityV2 = EntityV2> {
   capacity?: CapacityOption
diff --git a/src/v1/entity/actions/commands/putItem/options.ts b/src/v1/entity/actions/commands/putItem/options.ts
index a4196105..c13c2771 100644
--- a/src/v1/entity/actions/commands/putItem/options.ts
+++ b/src/v1/entity/actions/commands/putItem/options.ts
@@ -1,8 +1,8 @@
 import type { EntityV2 } from 'v1/entity'
 import type { EntityCondition } from 'v1/entity/actions/parseCondition'
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
-import type { MetricsOption } from 'v1/operations/constants/options/metrics'
-import type { ReturnValuesOption } from 'v1/operations/constants/options/returnValues'
+import type { CapacityOption } from 'v1/options/capacity'
+import type { MetricsOption } from 'v1/options/metrics'
+import type { ReturnValuesOption } from 'v1/options/returnValues'
 
 export type PutItemCommandReturnValuesOption = ReturnValuesOption
 
diff --git a/src/v1/entity/actions/commands/putItem/putItemCommand.ts b/src/v1/entity/actions/commands/putItem/putItemCommand.ts
index 46e38d14..3f8dd939 100644
--- a/src/v1/entity/actions/commands/putItem/putItemCommand.ts
+++ b/src/v1/entity/actions/commands/putItem/putItemCommand.ts
@@ -9,7 +9,7 @@ import type {
   UpdatedNewReturnValuesOption,
   AllOldReturnValuesOption,
   AllNewReturnValuesOption
-} from 'v1/operations/constants/options/returnValues'
+} from 'v1/options/returnValues'
 import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { PutItemInput } from './types'
@@ -58,7 +58,7 @@ export class PutItemCommand<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends PutItemOptions<ENTITY> = PutItemOptions<ENTITY>
 > extends EntityAction<ENTITY> {
-  static operationName = 'put' as const;
+  static actionName = 'put' as const;
 
   [$item]?: PutItemInput<ENTITY>;
   [$options]: OPTIONS
@@ -81,7 +81,7 @@ export class PutItemCommand<
 
   params(): PutCommandInput {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'PutItemCommand incomplete: Missing "item" property'
       })
     }
diff --git a/src/v1/entity/actions/commands/putItem/putItemParams/parsePutItemOptions.ts b/src/v1/entity/actions/commands/putItem/putItemParams/parsePutItemOptions.ts
index 9ebb400f..0d396c4c 100644
--- a/src/v1/entity/actions/commands/putItem/putItemParams/parsePutItemOptions.ts
+++ b/src/v1/entity/actions/commands/putItem/putItemParams/parsePutItemOptions.ts
@@ -3,10 +3,10 @@ import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseMetricsOption } from 'v1/operations/utils/parseOptions/parseMetricsOption'
-import { parseReturnValuesOption } from 'v1/operations/utils/parseOptions/parseReturnValuesOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseMetricsOption } from 'v1/options/metrics'
+import { parseReturnValuesOption } from 'v1/options/returnValues'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import { putItemCommandReturnValuesOptionsSet, PutItemOptions } from '../options'
 
diff --git a/src/v1/entity/actions/commands/updateItem/options.ts b/src/v1/entity/actions/commands/updateItem/options.ts
index 27f16773..18802d4e 100644
--- a/src/v1/entity/actions/commands/updateItem/options.ts
+++ b/src/v1/entity/actions/commands/updateItem/options.ts
@@ -1,6 +1,6 @@
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
-import type { MetricsOption } from 'v1/operations/constants/options/metrics'
-import type { ReturnValuesOption } from 'v1/operations/constants/options/returnValues'
+import type { CapacityOption } from 'v1/options/capacity'
+import type { MetricsOption } from 'v1/options/metrics'
+import type { ReturnValuesOption } from 'v1/options/returnValues'
 import type { EntityV2 } from 'v1/entity'
 import type { EntityCondition } from 'v1/entity/actions/parseCondition'
 
diff --git a/src/v1/entity/actions/commands/updateItem/types.ts b/src/v1/entity/actions/commands/updateItem/types.ts
index a78d196b..a77e0299 100644
--- a/src/v1/entity/actions/commands/updateItem/types.ts
+++ b/src/v1/entity/actions/commands/updateItem/types.ts
@@ -24,7 +24,7 @@ import type {
   Always,
   Never
 } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import type { OptionalizeUndefinableProperties } from 'v1/types/optionalizeUndefinableProperties'
 import type { If } from 'v1/types/if'
 
diff --git a/src/v1/entity/actions/commands/updateItem/updateExpression/parser.ts b/src/v1/entity/actions/commands/updateItem/updateExpression/parser.ts
index 7a5758f9..b6e48011 100644
--- a/src/v1/entity/actions/commands/updateItem/updateExpression/parser.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateExpression/parser.ts
@@ -9,14 +9,14 @@ import { isArray } from 'v1/utils/validation/isArray'
 import type { UpdateItemInputExtension } from '../types'
 import { $SET, $REMOVE, $SUM, $SUBTRACT, $ADD, $DELETE, $APPEND, $PREPEND } from '../constants'
 import {
-  hasSetOperation,
-  hasGetOperation,
-  hasSumOperation,
-  hasSubtractOperation,
-  hasAddOperation,
-  hasDeleteOperation,
-  hasAppendOperation,
-  hasPrependOperation
+  isSetUpdate,
+  isReferenceUpdate,
+  isSumUpdate,
+  isSubtractUpdate,
+  isAddUpdate,
+  isDeleteUpdate,
+  isAppendUpdate,
+  isPrependUpdate
 } from '../utils'
 
 import type { ParsedUpdate } from './type'
@@ -48,7 +48,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasSetOperation(input)) {
+    if (isSetUpdate(input)) {
       this.set.beginNewInstruction()
       this.set.appendValidAttributePath(currentPath)
       this.set.appendToExpression(' = ')
@@ -57,7 +57,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasGetOperation(input)) {
+    if (isReferenceUpdate(input)) {
       this.set.beginNewInstruction()
       this.set.appendValidAttributePath(currentPath)
       this.set.appendToExpression(' = ')
@@ -71,7 +71,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasSumOperation(input)) {
+    if (isSumUpdate(input)) {
       // TODO: Fix this cast
       const [left, right] = input[$SUM] as [
         AttributeValue<UpdateItemInputExtension>,
@@ -86,7 +86,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasSubtractOperation(input)) {
+    if (isSubtractUpdate(input)) {
       // TODO: Fix this cast
       const [left, right] = input[$SUBTRACT] as [
         AttributeValue<UpdateItemInputExtension>,
@@ -101,7 +101,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasAddOperation(input)) {
+    if (isAddUpdate(input)) {
       this.add.beginNewInstruction()
       this.add.appendValidAttributePath(currentPath)
       this.add.appendToExpression(' ')
@@ -110,7 +110,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasDeleteOperation(input)) {
+    if (isDeleteUpdate(input)) {
       this.delete.beginNewInstruction()
       this.delete.appendValidAttributePath(currentPath)
       this.delete.appendToExpression(' ')
@@ -121,7 +121,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasAppendOperation(input)) {
+    if (isAppendUpdate(input)) {
       this.set.beginNewInstruction()
       this.set.appendValidAttributePath(currentPath)
       this.set.appendToExpression(' = list_append(')
@@ -133,7 +133,7 @@ export class UpdateExpressionParser {
       return
     }
 
-    if (hasPrependOperation(input)) {
+    if (isPrependUpdate(input)) {
       this.set.beginNewInstruction()
       this.set.appendValidAttributePath(currentPath)
       this.set.appendToExpression(' = list_append(')
diff --git a/src/v1/entity/actions/commands/updateItem/updateExpression/verbParser.ts b/src/v1/entity/actions/commands/updateItem/updateExpression/verbParser.ts
index 9c7046d7..81b1ff24 100644
--- a/src/v1/entity/actions/commands/updateItem/updateExpression/verbParser.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateExpression/verbParser.ts
@@ -1,15 +1,15 @@
 import type { Schema } from 'v1/schema'
 import type { Attribute } from 'v1/schema/attributes'
 import type { ParsedValue } from 'v1/schema/actions/parse'
-import { isNumber, isString } from 'v1/utils/validation'
 import {
   ExpressionParser,
   appendAttributePath,
   AppendAttributePathOptions
-} from 'v1/operations/expression/expressionParser'
+} from 'v1/schema/actions/utils/appendAttributePath'
+import { isNumber, isString } from 'v1/utils/validation'
 
 import type { ReferenceExtension, UpdateItemInputExtension } from '../types'
-import { hasGetOperation } from '../utils'
+import { isReferenceUpdate } from '../utils'
 import { $GET } from '../constants'
 import type { ParsedUpdate } from './type'
 
@@ -83,7 +83,7 @@ export class UpdateExpressionVerbParser implements ExpressionParser {
       { operation: 'update'; extension: UpdateItemInputExtension }
     >
   ): void => {
-    if (hasGetOperation(validAttributeValue)) {
+    if (isReferenceUpdate(validAttributeValue)) {
       // TODO: Fix this cast
       const [expression, fallback] = validAttributeValue[$GET] as [
         string,
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemCommand.ts b/src/v1/entity/actions/commands/updateItem/updateItemCommand.ts
index b67445ef..2a2585d4 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemCommand.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemCommand.ts
@@ -9,7 +9,7 @@ import type {
   UpdatedNewReturnValuesOption,
   AllOldReturnValuesOption,
   AllNewReturnValuesOption
-} from 'v1/operations/constants/options/returnValues'
+} from 'v1/options/returnValues'
 import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { UpdateItemInput } from './types'
@@ -58,7 +58,7 @@ export class UpdateItemCommand<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends UpdateItemOptions<ENTITY> = UpdateItemOptions<ENTITY>
 > extends EntityAction<ENTITY> {
-  static operationName = 'update' as const;
+  static actionName = 'update' as const;
 
   [$item]?: UpdateItemInput<ENTITY>;
   [$options]: OPTIONS
@@ -81,7 +81,7 @@ export class UpdateItemCommand<
 
   params(): UpdateCommandInput {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'UpdateItemCommand incomplete: Missing "item" property'
       })
     }
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/attribute.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/attribute.ts
index 9328f4ad..1779f8e3 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/attribute.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/attribute.ts
@@ -4,7 +4,7 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $REMOVE } from '../../../constants'
-import { hasGetOperation } from '../../../utils'
+import { isReferenceUpdate } from '../../../utils'
 
 import { parseNumberExtension } from './number'
 import { parseSetExtension } from './set'
@@ -48,7 +48,7 @@ export const parseUpdateExtension: ExtensionParser<UpdateItemInputExtension> = (
     }
   }
 
-  if (hasGetOperation(input)) {
+  if (isReferenceUpdate(input)) {
     return parseReferenceExtension(attribute, input, options)
   }
 
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/list.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/list.ts
index 0b006110..574c994d 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/list.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/list.ts
@@ -9,7 +9,7 @@ import { isArray } from 'v1/utils/validation/isArray'
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $SET, $REMOVE, $APPEND, $PREPEND } from '../../../constants'
-import { hasSetOperation, hasAppendOperation, hasPrependOperation } from '../../../utils'
+import { isSetUpdate, isAppendUpdate, isPrependUpdate } from '../../../utils'
 
 import { parseReferenceExtension } from './reference'
 import { parseUpdateExtension } from './attribute'
@@ -62,7 +62,7 @@ export const parseListExtension = (
 ): ReturnType<ExtensionParser<UpdateItemInputExtension>> => {
   const { transform = true } = options
 
-  if (hasSetOperation(input) && input[$SET] !== undefined) {
+  if (isSetUpdate(input) && input[$SET] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
@@ -82,7 +82,7 @@ export const parseListExtension = (
   }
 
   if (isObject(input) || isArray(input)) {
-    if (hasAppendOperation(input) && input[$APPEND] !== undefined) {
+    if (isAppendUpdate(input) && input[$APPEND] !== undefined) {
       const appendedValue = input[$APPEND]
 
       if (isArray(appendedValue)) {
@@ -129,7 +129,7 @@ export const parseListExtension = (
       }
     }
 
-    if (hasPrependOperation(input) && input[$PREPEND] !== undefined) {
+    if (isPrependUpdate(input) && input[$PREPEND] !== undefined) {
       const prependedValue = input[$PREPEND]
 
       if (isArray(prependedValue)) {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/map.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/map.ts
index 34fd6fa4..11487520 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/map.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/map.ts
@@ -3,14 +3,14 @@ import { Parser, ExtensionParser, ExtensionParserOptions } from 'v1/schema/actio
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $SET } from '../../../constants'
-import { hasSetOperation } from '../../../utils'
+import { isSetUpdate } from '../../../utils'
 
 export const parseMapExtension = (
   attribute: MapAttribute,
   input: unknown,
   { transform = true }: ExtensionParserOptions = {}
 ): ReturnType<ExtensionParser<UpdateItemInputExtension>> => {
-  if (hasSetOperation(input) && input[$SET] !== undefined) {
+  if (isSetUpdate(input) && input[$SET] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/number.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/number.ts
index 3eb926bb..bb917afc 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/number.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/number.ts
@@ -6,7 +6,7 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $SUM, $SUBTRACT, $ADD } from '../../../constants'
-import { hasSumOperation, hasSubtractOperation, hasAddOperation } from '../../../utils'
+import { isSumUpdate, isSubtractUpdate, isAddUpdate } from '../../../utils'
 
 import { parseReferenceExtension } from './reference'
 
@@ -15,7 +15,7 @@ export const parseNumberExtension = (
   inputValue: unknown,
   { transform = true }: ExtensionParserOptions = {}
 ): ReturnType<ExtensionParser<UpdateItemInputExtension>> => {
-  if (hasSumOperation(inputValue) && inputValue[$SUM] !== undefined) {
+  if (isSumUpdate(inputValue) && inputValue[$SUM] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
@@ -62,7 +62,7 @@ export const parseNumberExtension = (
     }
   }
 
-  if (hasSubtractOperation(inputValue) && inputValue[$SUBTRACT] !== undefined) {
+  if (isSubtractUpdate(inputValue) && inputValue[$SUBTRACT] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
@@ -110,7 +110,7 @@ export const parseNumberExtension = (
     }
   }
 
-  if (hasAddOperation(inputValue) && inputValue[$ADD] !== undefined) {
+  if (isAddUpdate(inputValue) && inputValue[$ADD] !== undefined) {
     const parser = number()
       .freeze(`${attribute.path}[$ADD]`)
       .build(Parser)
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/record.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/record.ts
index 6c1927c2..aa0bdf04 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/record.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/record.ts
@@ -10,7 +10,7 @@ import { isObject } from 'v1/utils/validation/isObject'
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $SET, $REMOVE } from '../../../constants'
-import { hasSetOperation } from '../../../utils'
+import { isSetUpdate } from '../../../utils'
 
 import { parseUpdateExtension } from './attribute'
 
@@ -50,7 +50,7 @@ export const parseRecordExtension = (
 ): ReturnType<ExtensionParser<UpdateItemInputExtension>> => {
   const { transform = true } = options
 
-  if (hasSetOperation(input) && input[$SET] !== undefined) {
+  if (isSetUpdate(input) && input[$SET] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/reference.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/reference.ts
index 507d2c6f..17c61248 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/reference.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/reference.ts
@@ -6,7 +6,7 @@ import { isString } from 'v1/utils/validation/isString'
 
 import type { UpdateItemInputExtension, ReferenceExtension } from '../../../types'
 import { $GET } from '../../../constants'
-import { hasGetOperation } from '../../../utils'
+import { isReferenceUpdate } from '../../../utils'
 
 export const parseReferenceExtension: ExtensionParser<
   ReferenceExtension,
@@ -16,7 +16,7 @@ export const parseReferenceExtension: ExtensionParser<
   inputValue: unknown,
   { transform = true }: ExtensionParserOptions = {}
 ) => {
-  if (hasGetOperation(inputValue) && inputValue[$GET] !== undefined) {
+  if (isReferenceUpdate(inputValue) && inputValue[$GET] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/set.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/set.ts
index a36a916d..1f425cfe 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/set.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/extension/parseExtension/set.ts
@@ -3,14 +3,14 @@ import { Parser, ExtensionParser, ExtensionParserOptions } from 'v1/schema/actio
 
 import type { UpdateItemInputExtension } from '../../../types'
 import { $ADD, $DELETE } from '../../../constants'
-import { hasAddOperation, hasDeleteOperation } from '../../../utils'
+import { isAddUpdate, isDeleteUpdate } from '../../../utils'
 
 export const parseSetExtension = (
   attribute: SetAttribute,
   input: unknown,
   { transform = true }: ExtensionParserOptions = {}
 ): ReturnType<ExtensionParser<UpdateItemInputExtension>> => {
-  if (hasAddOperation(input) && input[$ADD] !== undefined) {
+  if (isAddUpdate(input) && input[$ADD] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
@@ -29,7 +29,7 @@ export const parseSetExtension = (
     }
   }
 
-  if (hasDeleteOperation(input) && input[$DELETE] !== undefined) {
+  if (isDeleteUpdate(input) && input[$DELETE] !== undefined) {
     return {
       isExtension: true,
       *extensionParser() {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/parseUpdateItemOptions.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/parseUpdateItemOptions.ts
index bc07b34c..db13c8d9 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/parseUpdateItemOptions.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/parseUpdateItemOptions.ts
@@ -2,10 +2,10 @@ import type { UpdateCommandInput } from '@aws-sdk/lib-dynamodb'
 
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseMetricsOption } from 'v1/operations/utils/parseOptions/parseMetricsOption'
-import { parseReturnValuesOption } from 'v1/operations/utils/parseOptions/parseReturnValuesOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseMetricsOption } from 'v1/options/metrics'
+import { parseReturnValuesOption } from 'v1/options/returnValues'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import { updateItemCommandReturnValuesOptionsSet, UpdateItemOptions } from '../options'
 
diff --git a/src/v1/entity/actions/commands/updateItem/utils.ts b/src/v1/entity/actions/commands/updateItem/utils.ts
index 3d002f20..83222746 100644
--- a/src/v1/entity/actions/commands/updateItem/utils.ts
+++ b/src/v1/entity/actions/commands/updateItem/utils.ts
@@ -17,7 +17,7 @@ import {
 
 export const $set = <VALUE>(value: VALUE): SET<VALUE> => ({ [$HAS_VERB]: true, [$SET]: value })
 
-export const hasSetOperation = (input: unknown): input is { [$SET]: unknown } =>
+export const isSetUpdate = (input: unknown): input is { [$SET]: unknown } =>
   isObject(input) && $SET in input
 
 export const $get = <
@@ -31,14 +31,14 @@ export const $get = <
   [$GET]: (fallback === undefined ? [reference] : [reference, fallback]) as any
 })
 
-export const hasGetOperation = (input: unknown): input is { [$GET]: unknown } =>
+export const isReferenceUpdate = (input: unknown): input is { [$GET]: unknown } =>
   isObject(input) && $GET in input
 
 export const $remove = (): $REMOVE => $REMOVE
 
 export const $sum = <A, B>(a: A, b: B): SUM<A, B> => ({ [$HAS_VERB]: true, [$SUM]: [a, b] })
 
-export const hasSumOperation = (input: unknown): input is { [$SUM]: unknown } =>
+export const isSumUpdate = (input: unknown): input is { [$SUM]: unknown } =>
   isObject(input) && $SUM in input
 
 export const $subtract = <A, B>(a: A, b: B): SUBTRACT<A, B> => ({
@@ -46,12 +46,12 @@ export const $subtract = <A, B>(a: A, b: B): SUBTRACT<A, B> => ({
   [$SUBTRACT]: [a, b]
 })
 
-export const hasSubtractOperation = (input: unknown): input is { [$SUBTRACT]: unknown } =>
+export const isSubtractUpdate = (input: unknown): input is { [$SUBTRACT]: unknown } =>
   isObject(input) && $SUBTRACT in input
 
 export const $add = <VALUE>(value: VALUE): ADD<VALUE> => ({ [$HAS_VERB]: true, [$ADD]: value })
 
-export const hasAddOperation = (input: unknown): input is { [$ADD]: unknown } =>
+export const isAddUpdate = (input: unknown): input is { [$ADD]: unknown } =>
   isObject(input) && $ADD in input
 
 export const $delete = <VALUE>(value: VALUE): DELETE<VALUE> => ({
@@ -59,7 +59,7 @@ export const $delete = <VALUE>(value: VALUE): DELETE<VALUE> => ({
   [$DELETE]: value
 })
 
-export const hasDeleteOperation = (input: unknown): input is { [$DELETE]: unknown } =>
+export const isDeleteUpdate = (input: unknown): input is { [$DELETE]: unknown } =>
   isObject(input) && $DELETE in input
 
 export const $append = <VALUE>(value: VALUE): APPEND<VALUE> => ({
@@ -67,7 +67,7 @@ export const $append = <VALUE>(value: VALUE): APPEND<VALUE> => ({
   [$APPEND]: value
 })
 
-export const hasAppendOperation = (input: unknown): input is { [$APPEND]: unknown } =>
+export const isAppendUpdate = (input: unknown): input is { [$APPEND]: unknown } =>
   isObject(input) && $APPEND in input
 
 export const $prepend = <VALUE>(value: VALUE): PREPEND<VALUE> => ({
@@ -75,5 +75,5 @@ export const $prepend = <VALUE>(value: VALUE): PREPEND<VALUE> => ({
   [$PREPEND]: value
 })
 
-export const hasPrependOperation = (input: unknown): input is { [$PREPEND]: unknown } =>
+export const isPrependUpdate = (input: unknown): input is { [$PREPEND]: unknown } =>
   isObject(input) && $PREPEND in input
diff --git a/src/v1/entity/actions/format.ts b/src/v1/entity/actions/format.ts
index 1a6ff653..089d8ebc 100644
--- a/src/v1/entity/actions/format.ts
+++ b/src/v1/entity/actions/format.ts
@@ -24,7 +24,7 @@ export const $formatter = Symbol('$formatter')
 export type $formatter = typeof $formatter
 
 export class EntityFormatter<ENTITY extends EntityV2 = EntityV2> extends EntityAction<ENTITY> {
-  static operationName: 'format';
+  static actionName: 'format';
   [$formatter]: Formatter<ENTITY['schema']>
 
   constructor(entity: ENTITY) {
diff --git a/src/v1/entity/actions/parse.ts b/src/v1/entity/actions/parse.ts
index 4fcb8245..21bbafde 100644
--- a/src/v1/entity/actions/parse.ts
+++ b/src/v1/entity/actions/parse.ts
@@ -25,7 +25,7 @@ const $parser = Symbol('$parser')
 type $parser = typeof $parser
 
 export class EntityParser<ENTITY extends EntityV2 = EntityV2> extends EntityAction<ENTITY> {
-  static operationName: 'parse';
+  static actionName: 'parse';
   [$parser]: Parser<ENTITY['schema']>
 
   constructor(entity: ENTITY) {
diff --git a/src/v1/entity/actions/parseCondition.ts b/src/v1/entity/actions/parseCondition.ts
index 173ee292..b434efea 100644
--- a/src/v1/entity/actions/parseCondition.ts
+++ b/src/v1/entity/actions/parseCondition.ts
@@ -9,7 +9,7 @@ type $conditionParser = typeof $conditionParser
 export class EntityConditionParser<
   ENTITY extends EntityV2 = EntityV2
 > extends EntityAction<ENTITY> {
-  static operationName: 'parseCondition';
+  static actionName: 'parseCondition';
   [$conditionParser]: ConditionParser<ENTITY['schema']>
 
   constructor(entity: ENTITY, id = '') {
diff --git a/src/v1/entity/actions/parsePaths.ts b/src/v1/entity/actions/parsePaths.ts
new file mode 100644
index 00000000..6da1bec6
--- /dev/null
+++ b/src/v1/entity/actions/parsePaths.ts
@@ -0,0 +1,45 @@
+import { PathParser, Paths } from 'v1/schema/actions/parsePaths'
+import { EntityV2, EntityAction } from 'v1/entity'
+
+const $pathParser = Symbol('$pathParser')
+type $pathParser = typeof $pathParser
+
+export class EntityPathParser<ENTITY extends EntityV2 = EntityV2> extends EntityAction<ENTITY> {
+  static actionName: 'parsePaths';
+  [$pathParser]: PathParser<ENTITY['schema']>
+
+  constructor(entity: ENTITY, id = '') {
+    super(entity)
+    this[$pathParser] = new PathParser(entity.schema, id)
+  }
+
+  setId(nextId: string): this {
+    this[$pathParser].setId(nextId)
+    return this
+  }
+
+  parse = (attributes: string[]): this => {
+    this[$pathParser].parse(attributes)
+    return this
+  }
+
+  toCommandOptions(): {
+    ProjectionExpression: string
+    ExpressionAttributeNames: Record<string, string>
+  } {
+    return this[$pathParser].toCommandOptions()
+  }
+}
+
+export type EntityPaths<ENTITY extends EntityV2 = EntityV2> = Paths<ENTITY['schema']>
+
+export type EntityPathsIntersection<
+  ENTITIES extends EntityV2[] = EntityV2[],
+  RESULTS extends string = string
+> = ENTITIES extends [infer ENTITIES_HEAD, ...infer ENTITIES_TAIL]
+  ? ENTITIES_HEAD extends EntityV2
+    ? ENTITIES_TAIL extends EntityV2[]
+      ? EntityPathsIntersection<ENTITIES_TAIL, RESULTS & EntityPaths<ENTITIES_HEAD>>
+      : never
+    : never
+  : RESULTS
diff --git a/src/v1/entity/actions/paths.ts b/src/v1/entity/actions/paths.ts
deleted file mode 100644
index b661b6cc..00000000
--- a/src/v1/entity/actions/paths.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Paths } from 'v1/schema/actions/paths'
-import type { EntityV2 } from 'v1/entity'
-
-export type EntityPaths<ENTITY extends EntityV2 = EntityV2> = Paths<ENTITY['schema']>
-
-export type EntityPathsIntersection<
-  ENTITIES extends EntityV2[] = EntityV2[],
-  RESULTS extends string = string
-> = ENTITIES extends [infer ENTITIES_HEAD, ...infer ENTITIES_TAIL]
-  ? ENTITIES_HEAD extends EntityV2
-    ? ENTITIES_TAIL extends EntityV2[]
-      ? EntityPathsIntersection<ENTITIES_TAIL, RESULTS & EntityPaths<ENTITIES_HEAD>>
-      : never
-    : never
-  : RESULTS
diff --git a/src/v1/entity/actions/tParse.ts b/src/v1/entity/actions/tParse.ts
index 32fc0320..637d6088 100644
--- a/src/v1/entity/actions/tParse.ts
+++ b/src/v1/entity/actions/tParse.ts
@@ -18,7 +18,7 @@ export type EntityParserInput<
 export type KeyInput<ENTITY extends EntityV2> = EntityParserInput<ENTITY, { operation: 'key' }>
 
 export class EntityTParser<ENTITY extends EntityV2 = EntityV2> extends EntityAction<ENTITY> {
-  static operationName: 'tParse'
+  static actionName: 'tParse'
   parser: EntityParser<ENTITY>
 
   constructor(entity: ENTITY) {
diff --git a/src/v1/entity/actions/transactions/conditionCheck/conditionCheck.ts b/src/v1/entity/actions/transactions/conditionCheck/conditionCheck.ts
index 41accfea..c4245418 100644
--- a/src/v1/entity/actions/transactions/conditionCheck/conditionCheck.ts
+++ b/src/v1/entity/actions/transactions/conditionCheck/conditionCheck.ts
@@ -17,7 +17,7 @@ export type $condition = typeof $condition
 export class ConditionCheck<ENTITY extends EntityV2 = EntityV2>
   extends EntityAction<ENTITY>
   implements WriteItemTransaction<ENTITY, 'ConditionCheck'> {
-  static operationName = 'conditionCheck' as const
+  static actionName = 'conditionCheck' as const
 
   private [$key]?: KeyInput<ENTITY>
   public key: (keyInput: KeyInput<ENTITY>) => ConditionCheck<ENTITY>
@@ -35,13 +35,13 @@ export class ConditionCheck<ENTITY extends EntityV2 = EntityV2>
 
   params = (): ConditionCheckParams => {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'ConditionCheck incomplete: Missing "key" property'
       })
     }
 
     if (!this[$condition]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'ConditionCheck incomplete: Missing "condition" property'
       })
     }
diff --git a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItem.ts b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItem.ts
index 26912e4c..99a0c873 100644
--- a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItem.ts
+++ b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItem.ts
@@ -20,7 +20,7 @@ export class DeleteItemTransaction<
   >
   extends EntityAction<ENTITY>
   implements WriteItemTransaction<ENTITY, 'Delete'> {
-  static operationName = 'transactDelete' as const;
+  static actionName = 'transactDelete' as const;
 
   [$key]?: KeyInput<ENTITY>;
   [$options]: OPTIONS
@@ -43,7 +43,7 @@ export class DeleteItemTransaction<
 
   params(): TransactDeleteItemParams {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'DeleteItemTransaction incomplete: Missing "key" property'
       })
     }
diff --git a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/parseDeleteItemOptions.ts b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/parseDeleteItemOptions.ts
index 766de8a5..753bd59d 100644
--- a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/parseDeleteItemOptions.ts
+++ b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/parseDeleteItemOptions.ts
@@ -2,7 +2,7 @@ import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import { DeleteItemTransactionOptions } from '../options'
 import type { TransactDeleteItemParams } from './transactDeleteItemParams'
diff --git a/src/v1/entity/actions/transactions/transactGetItem/options.ts b/src/v1/entity/actions/transactions/transactGetItem/options.ts
index f1a87bf4..cffecb2d 100644
--- a/src/v1/entity/actions/transactions/transactGetItem/options.ts
+++ b/src/v1/entity/actions/transactions/transactGetItem/options.ts
@@ -1,5 +1,5 @@
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPaths } from 'v1/entity/actions/paths'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
 
 export type GetItemTransactionOptions<ENTITY extends EntityV2 = EntityV2> = {
   attributes?: EntityPaths<ENTITY>[]
diff --git a/src/v1/entity/actions/transactions/transactGetItem/transactGetItem.ts b/src/v1/entity/actions/transactions/transactGetItem/transactGetItem.ts
index 2d4c898e..3f9c3e0d 100644
--- a/src/v1/entity/actions/transactions/transactGetItem/transactGetItem.ts
+++ b/src/v1/entity/actions/transactions/transactGetItem/transactGetItem.ts
@@ -2,7 +2,7 @@ import type { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'
 
 import { EntityV2, EntityAction, $entity } from 'v1/entity'
 import type { KeyInput } from 'v1/entity/actions/tParse'
-import type { EntityPaths } from 'v1/entity/actions/paths'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
 import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { BaseTransaction, GetTransactionParams } from '../types'
@@ -36,7 +36,7 @@ export class GetItemTransaction<
   >
   extends EntityAction<ENTITY>
   implements GetItemTransactionInterface<ENTITY, OPTIONS> {
-  static operationName = 'transactGet' as const;
+  static actionName = 'transactGet' as const;
 
   [$key]?: KeyInput<ENTITY>
   key: (keyInput: KeyInput<ENTITY>) => GetItemTransaction<ENTITY>;
@@ -56,7 +56,7 @@ export class GetItemTransaction<
 
   params = (): TransactGetItemParams => {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'GetItemTransaction incomplete: Missing "key" property'
       })
     }
diff --git a/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/parseGetItemOptions.ts b/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/parseGetItemOptions.ts
index 1f2bde52..76327599 100644
--- a/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/parseGetItemOptions.ts
+++ b/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/parseGetItemOptions.ts
@@ -1,8 +1,8 @@
 import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
-import { parseProjection } from 'v1/operations/expression/projection/parse'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { EntityPathParser } from 'v1/entity/actions/parsePaths'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import type { GetItemTransactionOptions } from '../options'
 import type { TransactGetItemParams } from './transactGetItemParams'
@@ -20,7 +20,10 @@ export const parseGetItemTransactionOptions = <ENTITY extends EntityV2>(
   rejectExtraOptions(extraOptions)
 
   if (attributes !== undefined) {
-    const { ExpressionAttributeNames, ProjectionExpression } = parseProjection(entity, attributes)
+    const { ExpressionAttributeNames, ProjectionExpression } = entity
+      .build(EntityPathParser)
+      .parse(attributes)
+      .toCommandOptions()
 
     if (!isEmpty(ExpressionAttributeNames)) {
       transactionOptions.ExpressionAttributeNames = ExpressionAttributeNames
diff --git a/src/v1/entity/actions/transactions/transactGetItems/options.ts b/src/v1/entity/actions/transactions/transactGetItems/options.ts
index 7c66df53..0b4c3093 100644
--- a/src/v1/entity/actions/transactions/transactGetItems/options.ts
+++ b/src/v1/entity/actions/transactions/transactGetItems/options.ts
@@ -1,6 +1,8 @@
-import type { CapacityOptions } from 'v1/operations/constants/options/capacity'
+import type { CapacityOption } from 'v1/options/capacity'
 
 /**
  *  Top-level options of a transactGet option
  */
-export type TransactGetOptions = CapacityOptions
+export type TransactGetOptions = {
+  capacity?: CapacityOption
+}
diff --git a/src/v1/entity/actions/transactions/transactGetItems/parseTransactGetOptions.ts b/src/v1/entity/actions/transactions/transactGetItems/parseTransactGetOptions.ts
index 25fe2536..3d2213f2 100644
--- a/src/v1/entity/actions/transactions/transactGetItems/parseTransactGetOptions.ts
+++ b/src/v1/entity/actions/transactions/transactGetItems/parseTransactGetOptions.ts
@@ -1,7 +1,7 @@
 import type { TransactGetCommandInput } from '@aws-sdk/lib-dynamodb'
 
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import type { TransactGetOptions } from './options'
 
diff --git a/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.ts b/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.ts
index 7e9a766b..e122a739 100644
--- a/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.ts
+++ b/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.ts
@@ -7,7 +7,7 @@ import {
 
 import { EntityV2, $entity } from 'v1/entity'
 import { EntityFormatter, FormattedItem } from 'v1/entity/actions/format'
-import type { EntityPaths } from 'v1/entity/actions/paths'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
 
 import { DynamoDBToolboxError } from 'v1/errors'
 
@@ -17,14 +17,14 @@ import type { TransactGetOptions } from './options'
 import { parseTransactGetOptions } from './parseTransactGetOptions'
 
 export const getTransactGetCommandInput = (
-  operations: GetItemTransactionInterface[],
+  getItemTransactions: GetItemTransactionInterface[],
   transactGetOptions: TransactGetOptions = {}
 ): TransactGetItemsInput => {
   const options = parseTransactGetOptions(transactGetOptions ?? {})
 
   return {
     ...options,
-    TransactItems: operations
+    TransactItems: getItemTransactions
       .map(command => command.get())
       .map(({ params, type }) => ({
         [type]: params
@@ -82,7 +82,7 @@ export const formatTransactGetResponse = <TRANSACTIONS extends GetItemTransactio
   }
 
   if (response.Responses.length !== transactions.length) {
-    throw new DynamoDBToolboxError('operations.inconsistentNumberOfItems', {
+    throw new DynamoDBToolboxError('actions.inconsistentNumberOfItems', {
       message: 'Response length does not match the number of transactions',
       payload: {
         expected: transactions.length,
@@ -105,7 +105,8 @@ export const formatTransactGetResponse = <TRANSACTIONS extends GetItemTransactio
   return formattedResponses as ReturnedItems<TRANSACTIONS>
 }
 
-/** Run a `TransactGetItems` operation
+/**
+ * Send a collection of `GetItemTransaction`
  *
  * @param options Object { dynamoDBDocumentClient: Optional DynamoDBDocumentClient, transactGetOptions: Optional TransactGetOptions }
  * @param transactions Destructured array of Get Item transactions
@@ -128,7 +129,7 @@ export const transactGetItems = async <TRANSACTIONS extends GetItemTransactionIn
     options?.dynamoDBDocumentClient || transactions?.[0]?.get()?.documentClient
 
   if (!dynamoDBDocumentClient) {
-    throw new DynamoDBToolboxError('operations.incompleteOperation', {
+    throw new DynamoDBToolboxError('actions.incompleteAction', {
       message: 'DynamoDBDocumentClient not found'
     })
   }
diff --git a/src/v1/entity/actions/transactions/transactPutItem/transactPutItem.ts b/src/v1/entity/actions/transactions/transactPutItem/transactPutItem.ts
index 14e6727a..c1dce8cd 100644
--- a/src/v1/entity/actions/transactions/transactPutItem/transactPutItem.ts
+++ b/src/v1/entity/actions/transactions/transactPutItem/transactPutItem.ts
@@ -20,7 +20,7 @@ export class PutItemTransaction<
   >
   extends EntityAction<ENTITY>
   implements WriteItemTransaction<ENTITY, 'Put'> {
-  static operationName = 'transactPut' as const;
+  static actionName = 'transactPut' as const;
 
   [$item]?: PutItemInput<ENTITY>;
   [$options]: OPTIONS
@@ -43,7 +43,7 @@ export class PutItemTransaction<
 
   params(): TransactPutItemParams {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'PutItemTransaction incomplete: Missing "item" property'
       })
     }
diff --git a/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/parsePutItemOptions.ts b/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/parsePutItemOptions.ts
index 33116d3e..3a2205aa 100644
--- a/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/parsePutItemOptions.ts
+++ b/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/parsePutItemOptions.ts
@@ -2,7 +2,7 @@ import isEmpty from 'lodash.isempty'
 
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import { PutItemTransactionOptions } from '../options'
 import type { TransactPutItemParams } from './transactPutItemParams'
diff --git a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItem.ts b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItem.ts
index 0e08103f..bfc8428c 100644
--- a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItem.ts
+++ b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItem.ts
@@ -20,7 +20,7 @@ export class UpdateItemTransaction<
   >
   extends EntityAction<ENTITY>
   implements WriteItemTransaction<ENTITY, 'Update'> {
-  static operationName = 'transactUpdate' as const;
+  static actionName = 'transactUpdate' as const;
 
   [$item]?: UpdateItemInput<ENTITY>;
   [$options]: OPTIONS
@@ -43,7 +43,7 @@ export class UpdateItemTransaction<
 
   params(): TransactUpdateItemParams {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'UpdateItemTransaction incomplete: Missing "item" property'
       })
     }
diff --git a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/parseUpdateItemOptions.ts b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/parseUpdateItemOptions.ts
index 529a465c..24390a43 100644
--- a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/parseUpdateItemOptions.ts
+++ b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/parseUpdateItemOptions.ts
@@ -1,6 +1,6 @@
 import type { EntityV2 } from 'v1/entity'
 import { EntityConditionParser } from 'v1/entity/actions/parseCondition'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
 import type { UpdateItemTransactionOptions } from '../options'
 import type { TransactUpdateItemParams } from './transactUpdateItemParams'
diff --git a/src/v1/entity/actions/transactions/transactWriteItems/options.ts b/src/v1/entity/actions/transactions/transactWriteItems/options.ts
index e8bfecd9..2d3c6d4b 100644
--- a/src/v1/entity/actions/transactions/transactWriteItems/options.ts
+++ b/src/v1/entity/actions/transactions/transactWriteItems/options.ts
@@ -1,9 +1,10 @@
-import { CapacityOptions } from 'v1/operations/constants/options/capacity'
-import { ClientRequestTokenOptions } from 'v1/operations/constants/options/clientRequestToken'
-import { MetricsOptions } from 'v1/operations/constants/options/metrics'
+import { CapacityOption } from 'v1/options/capacity'
+import { ClientRequestToken } from 'v1/options/clientRequestToken'
+import { MetricsOption } from 'v1/options/metrics'
 
 /** Top-level options of a transactWrite option */
-export interface TransactWriteOptions
-  extends CapacityOptions,
-    MetricsOptions,
-    ClientRequestTokenOptions {}
+export interface TransactWriteOptions {
+  capacity?: CapacityOption
+  metrics?: MetricsOption
+  clientRequestToken?: ClientRequestToken
+}
diff --git a/src/v1/entity/actions/transactions/transactWriteItems/parseTransactWriteOptions.ts b/src/v1/entity/actions/transactions/transactWriteItems/parseTransactWriteOptions.ts
index 175ad6e3..a85c8924 100644
--- a/src/v1/entity/actions/transactions/transactWriteItems/parseTransactWriteOptions.ts
+++ b/src/v1/entity/actions/transactions/transactWriteItems/parseTransactWriteOptions.ts
@@ -1,9 +1,9 @@
 import type { TransactWriteCommandInput } from '@aws-sdk/lib-dynamodb'
 
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseMetricsOption } from 'v1/operations/utils/parseOptions/parseMetricsOption'
-import { parseClientRequestToken } from 'v1/operations/utils/parseOptions/parseClientRequestToken'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseMetricsOption } from 'v1/options/metrics'
+import { parseClientRequestToken } from 'v1/options/clientRequestToken'
 
 import type { TransactWriteOptions } from './options'
 
diff --git a/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.ts b/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.ts
index 693ad2a1..ace685f0 100644
--- a/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.ts
+++ b/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.ts
@@ -25,7 +25,8 @@ export const getTransactWriteCommandInput = (
   }
 }
 
-/** Run a `TransactWriteItems` operation
+/**
+ * Send a collection of `WriteItemTransactions`
  *
  * @param transactions
  * @param options
@@ -44,7 +45,7 @@ export const transactWriteItems = async <TRANSACTIONS extends WriteItemTransacti
     options?.dynamoDBDocumentClient || transactions?.[0]?.get()?.documentClient
 
   if (!dynamoDBDocumentClient) {
-    throw new DynamoDBToolboxError('operations.incompleteOperation', {
+    throw new DynamoDBToolboxError('actions.incompleteAction', {
       message: 'DynamoDBDocumentClient not found'
     })
   }
diff --git a/src/v1/entity/entity.ts b/src/v1/entity/entity.ts
index 605e661b..e7374ad3 100644
--- a/src/v1/entity/entity.ts
+++ b/src/v1/entity/entity.ts
@@ -98,10 +98,10 @@ export class EntityV2<
     this.computeKey = computeKey as any
   }
 
-  build<OPERATION_CLASS extends EntityAction<this> = EntityAction<this>>(
-    operationClass: new (entity: this) => OPERATION_CLASS
-  ): OPERATION_CLASS {
-    return new operationClass(this)
+  build<ACTION_CLASS extends EntityAction<this> = EntityAction<this>>(
+    actionClass: new (entity: this) => ACTION_CLASS
+  ): ACTION_CLASS {
+    return new actionClass(this)
   }
 }
 
@@ -109,10 +109,7 @@ export const $entity = Symbol('$entity')
 export type $entity = typeof $entity
 
 export class EntityAction<ENTITY extends EntityV2 = EntityV2> {
-  // Still needed?
-  static operationType = 'entity'
-  // Still needed?
-  static operationName: string;
+  static actionName: string;
 
   [$entity]: ENTITY
 
diff --git a/src/v1/errors/allErrors.ts b/src/v1/errors/allErrors.ts
index 7ddbc6b6..40f70685 100644
--- a/src/v1/errors/allErrors.ts
+++ b/src/v1/errors/allErrors.ts
@@ -1,6 +1,6 @@
 import type { SchemaErrorBlueprints } from 'v1/schema/errors'
 import type { EntityErrorBlueprints } from 'v1/entity/errors'
-import type { OperationsErrorBlueprints } from 'v1/operations/errors'
+import type { OperationsErrorBlueprints } from 'v1/options/errors'
 import type { TableErrorBlueprints } from 'v1/table/errors'
 
 import type { ErrorBlueprint } from './blueprint'
diff --git a/src/v1/index.ts b/src/v1/index.ts
index 97ebe61f..39dd641b 100644
--- a/src/v1/index.ts
+++ b/src/v1/index.ts
@@ -20,7 +20,8 @@ export type {
   FormattedValueDefaultOptions,
   FromFormatOptions
 } from './schema/actions/format'
-export type { AttrPaths, SchemaPaths, Paths } from './schema/actions/paths'
+export { PathParser } from './schema/actions/parsePaths'
+export type { AttrPaths, SchemaPaths, Paths } from './schema/actions/parsePaths'
 export { ConditionParser } from './schema/actions/parseCondition'
 export type { Condition } from './schema/actions/parseCondition'
 // TODO: Pick relevant exports
@@ -31,7 +32,7 @@ export { TableV2 } from './table'
 export { PrimaryKeyParser } from './table/actions/parsePrimaryKey'
 export type { PrimaryKey } from './table/actions/parsePrimaryKey'
 export { QueryCommand } from './table/actions/queryCommand'
-export type { QueryOptions, QueryResponse } from './table/actions/queryCommand'
+export type { Query, QueryOptions, QueryResponse } from './table/actions/queryCommand'
 export { ScanCommand } from './table/actions/scanCommand'
 export type { ScanOptions, ScanResponse } from './table/actions/scanCommand'
 export type { IndexNames, IndexSchema } from './table/actions/indexes'
@@ -77,7 +78,8 @@ export { PutItemTransaction } from './entity/actions/transactions/transactPutIte
 export { UpdateItemTransaction } from './entity/actions/transactions/transactUpdateItem'
 export { DeleteItemTransaction } from './entity/actions/transactions/transactDeleteItem'
 export { ConditionCheck } from './entity/actions/transactions/conditionCheck'
-export type { EntityPaths, EntityPathsIntersection } from './entity/actions/paths'
+export { EntityPathParser } from './entity/actions/parsePaths'
+export type { EntityPaths } from './entity/actions/parsePaths'
 export { EntityFormatter } from './entity/actions/format'
 export type { FormattedItem } from './entity/actions/format'
 export { EntityParser } from './entity/actions/parse'
@@ -92,11 +94,6 @@ export type { EntityParserInput, KeyInput } from './entity/actions/tParse'
 export { EntityConditionParser } from './entity/actions/parseCondition'
 export type { EntityCondition } from './entity/actions/parseCondition'
 
-// operations: TO REMOVE
-export { parseProjection } from './operations/expression/projection/parse'
-// TODO: Pick relevant types
-export * from './operations/types'
-
 export * from './errors'
 export * from './test-tools'
 export * from './transformers'
diff --git a/src/v1/operations/constants/options/capacity.ts b/src/v1/operations/constants/options/capacity.ts
deleted file mode 100644
index 14440e99..00000000
--- a/src/v1/operations/constants/options/capacity.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export type NoneCapacityOption = 'NONE'
-export type TotalCapacityOption = 'TOTAL'
-export type IndexesCapacityOption = 'INDEXES'
-
-export type CapacityOption = NoneCapacityOption | TotalCapacityOption | IndexesCapacityOption
-
-export interface CapacityOptions {
-  /** Determines the level of detail about either provisioned or on-demand throughput consumption that is returned in the response. */
-  capacity?: CapacityOption
-}
-
-export const capacityOptionsSet = new Set<CapacityOption>(['NONE', 'TOTAL', 'INDEXES'])
diff --git a/src/v1/operations/constants/options/clientRequestToken.ts b/src/v1/operations/constants/options/clientRequestToken.ts
deleted file mode 100644
index 057ddf44..00000000
--- a/src/v1/operations/constants/options/clientRequestToken.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export type ClientRequestToken = string
-
-export interface ClientRequestTokenOptions {
-  /** Makes the call to TransactWriteItems idempotent, meaning that multiple identical calls have the same effect as one single call. */
-  clientRequestToken?: ClientRequestToken
-}
diff --git a/src/v1/operations/constants/options/metrics.ts b/src/v1/operations/constants/options/metrics.ts
deleted file mode 100644
index d1868fd1..00000000
--- a/src/v1/operations/constants/options/metrics.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export type NoneMetricsOption = 'NONE'
-export type SizeMetricsOption = 'SIZE'
-export type MetricsOption = NoneMetricsOption | SizeMetricsOption
-
-export interface MetricsOptions {
-  /** Determines whether item collection metrics are returned. */
-  metrics?: MetricsOption
-}
-
-export const metricsOptionsSet = new Set<MetricsOption>(['NONE', 'SIZE'])
diff --git a/src/v1/operations/constants/options/returnValues.ts b/src/v1/operations/constants/options/returnValues.ts
deleted file mode 100644
index 461daa82..00000000
--- a/src/v1/operations/constants/options/returnValues.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export type NoneReturnValuesOption = 'NONE'
-export type AllOldReturnValuesOption = 'ALL_OLD'
-export type UpdatedOldReturnValuesOption = 'UPDATED_OLD'
-export type AllNewReturnValuesOption = 'ALL_NEW'
-export type UpdatedNewReturnValuesOption = 'UPDATED_NEW'
-
-export type ReturnValuesOption =
-  | NoneReturnValuesOption
-  | AllOldReturnValuesOption
-  | UpdatedOldReturnValuesOption
-  | AllNewReturnValuesOption
-  | UpdatedNewReturnValuesOption
diff --git a/src/v1/operations/constants/options/select.ts b/src/v1/operations/constants/options/select.ts
deleted file mode 100644
index e9517037..00000000
--- a/src/v1/operations/constants/options/select.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export type AllAttributesSelectOption = 'ALL_ATTRIBUTES'
-export type AllProjectedAttributesSelectOption = 'ALL_PROJECTED_ATTRIBUTES'
-export type CountSelectOption = 'COUNT'
-export type SpecificAttributesSelectOption = 'SPECIFIC_ATTRIBUTES'
-
-export type SelectOption =
-  | AllAttributesSelectOption
-  | AllProjectedAttributesSelectOption
-  | CountSelectOption
-  | SpecificAttributesSelectOption
-
-export const selectOptionsSet = new Set<SelectOption>([
-  'ALL_ATTRIBUTES',
-  'ALL_PROJECTED_ATTRIBUTES',
-  'COUNT',
-  'SPECIFIC_ATTRIBUTES'
-])
diff --git a/src/v1/operations/expression/projection/index.ts b/src/v1/operations/expression/projection/index.ts
deleted file mode 100644
index 22579e47..00000000
--- a/src/v1/operations/expression/projection/index.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export { parseProjection } from './parse'
diff --git a/src/v1/operations/expression/projection/parse.ts b/src/v1/operations/expression/projection/parse.ts
deleted file mode 100644
index b222f696..00000000
--- a/src/v1/operations/expression/projection/parse.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { Schema } from 'v1/schema'
-import type { Paths } from 'v1/schema/actions/paths'
-import type { EntityV2 } from 'v1/entity'
-import type { EntityPaths } from 'v1/entity/actions/paths'
-
-import { ProjectionParser } from './parser'
-
-export const parseSchemaProjection = <
-  SCHEMA extends Schema,
-  ATTRIBUTE_PATHS extends Paths<SCHEMA>[]
->(
-  schema: SCHEMA,
-  attributes: ATTRIBUTE_PATHS,
-  id?: string
-): {
-  ProjectionExpression: string
-  ExpressionAttributeNames: Record<string, string>
-} => {
-  const projectionExpression = new ProjectionParser(schema, id)
-  projectionExpression.parseProjection(attributes)
-  return projectionExpression.toCommandOptions()
-}
-
-export const parseProjection = <
-  ENTITY extends EntityV2,
-  ATTRIBUTE_PATHS extends EntityPaths<ENTITY>[]
->(
-  entity: ENTITY,
-  attributes: ATTRIBUTE_PATHS,
-  id?: string
-) => parseSchemaProjection(entity.schema, attributes, id)
diff --git a/src/v1/operations/types/index.ts b/src/v1/operations/types/index.ts
deleted file mode 100644
index 58ca51b8..00000000
--- a/src/v1/operations/types/index.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export type { Query } from './query'
diff --git a/src/v1/operations/utils/parseOptions/parseCapacityOption.ts b/src/v1/options/capacity.ts
similarity index 51%
rename from src/v1/operations/utils/parseOptions/parseCapacityOption.ts
rename to src/v1/options/capacity.ts
index f8e1943c..4c0a4cda 100644
--- a/src/v1/operations/utils/parseOptions/parseCapacityOption.ts
+++ b/src/v1/options/capacity.ts
@@ -1,9 +1,16 @@
 import { DynamoDBToolboxError } from 'v1/errors/dynamoDBToolboxError'
-import { CapacityOption, capacityOptionsSet } from 'v1/operations/constants/options/capacity'
+
+export type NoneCapacityOption = 'NONE'
+export type TotalCapacityOption = 'TOTAL'
+export type IndexesCapacityOption = 'INDEXES'
+
+export type CapacityOption = NoneCapacityOption | TotalCapacityOption | IndexesCapacityOption
+
+export const capacityOptionsSet = new Set<CapacityOption>(['NONE', 'TOTAL', 'INDEXES'])
 
 export const parseCapacityOption = (capacity: CapacityOption): CapacityOption => {
   if (!capacityOptionsSet.has(capacity)) {
-    throw new DynamoDBToolboxError('operations.invalidCapacityOption', {
+    throw new DynamoDBToolboxError('options.invalidCapacityOption', {
       message: `Invalid capacity option: '${String(capacity)}'. 'capacity' must be one of: ${[
         ...capacityOptionsSet
       ].join(', ')}.`,
diff --git a/src/v1/operations/utils/parseOptions/parseClientRequestToken.ts b/src/v1/options/clientRequestToken.ts
similarity index 73%
rename from src/v1/operations/utils/parseOptions/parseClientRequestToken.ts
rename to src/v1/options/clientRequestToken.ts
index 97cc79a8..48942aff 100644
--- a/src/v1/operations/utils/parseOptions/parseClientRequestToken.ts
+++ b/src/v1/options/clientRequestToken.ts
@@ -1,10 +1,11 @@
 import { DynamoDBToolboxError } from 'v1/errors/dynamoDBToolboxError'
-import { ClientRequestToken } from 'v1/operations/constants/options/clientRequestToken'
 import { isString } from 'v1/utils/validation/isString'
 
+export type ClientRequestToken = string
+
 export const parseClientRequestToken = (clientRequestToken: unknown): ClientRequestToken => {
   if (!isString(clientRequestToken)) {
-    throw new DynamoDBToolboxError('operations.invalidClientRequestTokenOption', {
+    throw new DynamoDBToolboxError('options.invalidClientRequestToken', {
       message: `Invalid client request token option: '${String(
         clientRequestToken
       )}'. 'clientRequestToken' must be a string.`,
diff --git a/src/v1/operations/utils/parseOptions/parseConsistentOption.ts b/src/v1/options/consistent.ts
similarity index 80%
rename from src/v1/operations/utils/parseOptions/parseConsistentOption.ts
rename to src/v1/options/consistent.ts
index c8a6fe09..8595da46 100644
--- a/src/v1/operations/utils/parseOptions/parseConsistentOption.ts
+++ b/src/v1/options/consistent.ts
@@ -3,14 +3,14 @@ import { isBoolean } from 'v1/utils/validation/isBoolean'
 
 export const parseConsistentOption = (consistent: boolean, index?: string): boolean => {
   if (!isBoolean(consistent)) {
-    throw new DynamoDBToolboxError('operations.invalidConsistentOption', {
+    throw new DynamoDBToolboxError('options.invalidConsistentOption', {
       message: `Invalid consistent option: '${String(consistent)}'. 'consistent' must be boolean.`,
       payload: { consistent }
     })
   }
 
   if (consistent && index !== undefined) {
-    throw new DynamoDBToolboxError('operations.invalidConsistentOption', {
+    throw new DynamoDBToolboxError('options.invalidConsistentOption', {
       message: `Invalid consistent option: '${String(
         consistent
       )}'. Queries on secondary indexes cannot be consistent.`,
diff --git a/src/v1/operations/errors.ts b/src/v1/options/errors.ts
similarity index 72%
rename from src/v1/operations/errors.ts
rename to src/v1/options/errors.ts
index f3f173fa..213f95a7 100644
--- a/src/v1/operations/errors.ts
+++ b/src/v1/options/errors.ts
@@ -1,90 +1,88 @@
 import type { ErrorBlueprint } from 'v1/errors/blueprint'
 
-import type { ExpressionParsersErrorBlueprints } from './expression/errors'
+type IncompleteActionErrorBlueprint = ErrorBlueprint<{
+  code: 'actions.incompleteAction'
+  hasPath: false
+  payload: undefined
+}>
 
-type IncompleteOperationErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.incompleteOperation'
+type InconsistentNumberOfItemsErrorBlueprint = ErrorBlueprint<{
+  code: 'actions.inconsistentNumberOfItems'
+  hasPath: false
+  payload: {
+    received: number
+    expected: number
+  }
+}>
+
+type MissingDocumentClientErrorBlueprint = ErrorBlueprint<{
+  code: 'actions.missingDocumentClient'
   hasPath: false
   payload: undefined
 }>
 
 type InvalidCapacityOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidCapacityOption'
+  code: 'options.invalidCapacityOption'
   hasPath: false
   payload: { capacity: unknown }
 }>
 
 type InvalidClientRequestTokenOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidClientRequestTokenOption'
+  code: 'options.invalidClientRequestToken'
   hasPath: false
   payload: { clientRequestToken: unknown }
 }>
 
 type InvalidConsistentOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidConsistentOption'
+  code: 'options.invalidConsistentOption'
   hasPath: false
   payload: { consistent: unknown }
 }>
 
 type InvalidIndexOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidIndexOption'
+  code: 'options.invalidIndexOption'
   hasPath: false
   payload: { index: unknown }
 }>
 
 type InvalidLimitOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidLimitOption'
+  code: 'options.invalidLimitOption'
   hasPath: false
   payload: { limit: unknown }
 }>
 
 type InvalidMaxPagesOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidMaxPagesOption'
+  code: 'options.invalidMaxPagesOption'
   hasPath: false
   payload: { maxPages: unknown }
 }>
 
 type InvalidMetricsOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidMetricsOption'
+  code: 'options.invalidMetricsOption'
   hasPath: false
   payload: { metrics: unknown }
 }>
 
 type InvalidReturnValuesOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidReturnValuesOption'
+  code: 'options.invalidReturnValuesOption'
   hasPath: false
   payload: { returnValues: unknown }
 }>
 
 type InvalidSelectOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidSelectOption'
+  code: 'options.invalidSelectOption'
   hasPath: false
   payload: { select: unknown }
 }>
 
 type UnknownOptionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.unknownOption'
+  code: 'options.unknownOption'
   hasPath: false
   payload: { option: unknown }
 }>
 
-type InconsistentNumberOfItemsErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.inconsistentNumberOfItems'
-  hasPath: false
-  payload: {
-    received: number
-    expected: number
-  }
-}>
-
-type MissingDocumentClientErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.missingDocumentClient'
-  hasPath: false
-  payload: undefined
-}>
-
 export type OperationsErrorBlueprints =
-  | IncompleteOperationErrorBlueprint
+  | IncompleteActionErrorBlueprint
   | InvalidCapacityOptionErrorBlueprint
   | InvalidClientRequestTokenOptionErrorBlueprint
   | InvalidConsistentOptionErrorBlueprint
@@ -95,6 +93,5 @@ export type OperationsErrorBlueprints =
   | InvalidReturnValuesOptionErrorBlueprint
   | InvalidSelectOptionErrorBlueprint
   | UnknownOptionErrorBlueprint
-  | ExpressionParsersErrorBlueprints
   | InconsistentNumberOfItemsErrorBlueprint
   | MissingDocumentClientErrorBlueprint
diff --git a/src/v1/operations/utils/parseOptions/parseIndexOption.ts b/src/v1/options/index.ts
similarity index 82%
rename from src/v1/operations/utils/parseOptions/parseIndexOption.ts
rename to src/v1/options/index.ts
index 549f4e34..05059627 100644
--- a/src/v1/operations/utils/parseOptions/parseIndexOption.ts
+++ b/src/v1/options/index.ts
@@ -5,14 +5,14 @@ import { isString } from 'v1/utils/validation/isString'
 
 export const parseIndexOption = (table: TableV2, index: string): string => {
   if (!isString(index)) {
-    throw new DynamoDBToolboxError('operations.invalidIndexOption', {
+    throw new DynamoDBToolboxError('options.invalidIndexOption', {
       message: `Invalid index option: '${String(index)}'. 'index' must be a string.`,
       payload: { index }
     })
   }
 
   if (table.indexes[index] === undefined) {
-    throw new DynamoDBToolboxError('operations.invalidIndexOption', {
+    throw new DynamoDBToolboxError('options.invalidIndexOption', {
       message: `Invalid index option: '${String(
         index
       )}'. Index is not defined on Table, please provide an 'indexes' option to its constructor.`,
diff --git a/src/v1/operations/utils/parseOptions/parseLimitOption.ts b/src/v1/options/limit.ts
similarity index 84%
rename from src/v1/operations/utils/parseOptions/parseLimitOption.ts
rename to src/v1/options/limit.ts
index 0f98a3d0..8c93bce4 100644
--- a/src/v1/operations/utils/parseOptions/parseLimitOption.ts
+++ b/src/v1/options/limit.ts
@@ -3,7 +3,7 @@ import { isInteger } from 'v1/utils/validation/isInteger'
 
 export const parseLimitOption = (limit: number): number => {
   if (!isInteger(limit) || limit <= 0) {
-    throw new DynamoDBToolboxError('operations.invalidLimitOption', {
+    throw new DynamoDBToolboxError('options.invalidLimitOption', {
       message: `Invalid limit option: '${String(limit)}'. 'limit' must be an integer > 0.`,
       payload: { limit }
     })
diff --git a/src/v1/operations/utils/parseOptions/parseMaxPagesOption.ts b/src/v1/options/maxPages.ts
similarity index 86%
rename from src/v1/operations/utils/parseOptions/parseMaxPagesOption.ts
rename to src/v1/options/maxPages.ts
index 71319647..13599b38 100644
--- a/src/v1/operations/utils/parseOptions/parseMaxPagesOption.ts
+++ b/src/v1/options/maxPages.ts
@@ -7,7 +7,7 @@ export const parseMaxPagesOption = (maxPages: number): number => {
   }
 
   if (!isInteger(maxPages) || maxPages <= 0) {
-    throw new DynamoDBToolboxError('operations.invalidMaxPagesOption', {
+    throw new DynamoDBToolboxError('options.invalidMaxPagesOption', {
       message: `Invalid limit option: '${String(
         maxPages
       )}'. 'limit' must be Infinity or an integer > 0.`,
diff --git a/src/v1/operations/utils/parseOptions/parseMetricsOption.ts b/src/v1/options/metrics.ts
similarity index 57%
rename from src/v1/operations/utils/parseOptions/parseMetricsOption.ts
rename to src/v1/options/metrics.ts
index 32266c6e..bcddee46 100644
--- a/src/v1/operations/utils/parseOptions/parseMetricsOption.ts
+++ b/src/v1/options/metrics.ts
@@ -1,9 +1,14 @@
 import { DynamoDBToolboxError } from 'v1/errors/dynamoDBToolboxError'
-import { metricsOptionsSet, MetricsOption } from 'v1/operations/constants/options/metrics'
+
+export type NoneMetricsOption = 'NONE'
+export type SizeMetricsOption = 'SIZE'
+export type MetricsOption = NoneMetricsOption | SizeMetricsOption
+
+export const metricsOptionsSet = new Set<MetricsOption>(['NONE', 'SIZE'])
 
 export const parseMetricsOption = (metrics: MetricsOption): MetricsOption => {
   if (!metricsOptionsSet.has(metrics)) {
-    throw new DynamoDBToolboxError('operations.invalidMetricsOption', {
+    throw new DynamoDBToolboxError('options.invalidMetricsOption', {
       message: `Invalid metrics option: '${String(metrics)}'. 'metrics' must be one of: ${[
         ...metricsOptionsSet
       ].join(', ')}.`,
diff --git a/src/v1/operations/utils/parseOptions/rejectExtraOptions.ts b/src/v1/options/rejectExtraOptions.ts
similarity index 83%
rename from src/v1/operations/utils/parseOptions/rejectExtraOptions.ts
rename to src/v1/options/rejectExtraOptions.ts
index 8ae441db..bf87d7a2 100644
--- a/src/v1/operations/utils/parseOptions/rejectExtraOptions.ts
+++ b/src/v1/options/rejectExtraOptions.ts
@@ -4,7 +4,7 @@ export const rejectExtraOptions = (extraOptions: {}): void => {
   const [extraOption] = Object.keys(extraOptions)
 
   if (extraOption !== undefined) {
-    throw new DynamoDBToolboxError('operations.unknownOption', {
+    throw new DynamoDBToolboxError('options.unknownOption', {
       message: `Unkown option: ${extraOption}.`,
       payload: { option: extraOption }
     })
diff --git a/src/v1/operations/utils/parseOptions/parseReturnValuesOption.ts b/src/v1/options/returnValues.ts
similarity index 54%
rename from src/v1/operations/utils/parseOptions/parseReturnValuesOption.ts
rename to src/v1/options/returnValues.ts
index 0bc0a6e5..ea4e57d9 100644
--- a/src/v1/operations/utils/parseOptions/parseReturnValuesOption.ts
+++ b/src/v1/options/returnValues.ts
@@ -1,12 +1,24 @@
 import { DynamoDBToolboxError } from 'v1/errors/dynamoDBToolboxError'
-import { ReturnValuesOption } from 'v1/operations/constants/options/returnValues'
+
+export type NoneReturnValuesOption = 'NONE'
+export type AllOldReturnValuesOption = 'ALL_OLD'
+export type UpdatedOldReturnValuesOption = 'UPDATED_OLD'
+export type AllNewReturnValuesOption = 'ALL_NEW'
+export type UpdatedNewReturnValuesOption = 'UPDATED_NEW'
+
+export type ReturnValuesOption =
+  | NoneReturnValuesOption
+  | AllOldReturnValuesOption
+  | UpdatedOldReturnValuesOption
+  | AllNewReturnValuesOption
+  | UpdatedNewReturnValuesOption
 
 export const parseReturnValuesOption = <ALLOWED_RETURN_VALUES_OPTION extends ReturnValuesOption>(
   allowedReturnValuesOptions: Set<ALLOWED_RETURN_VALUES_OPTION>,
   returnValues: ALLOWED_RETURN_VALUES_OPTION
 ): ALLOWED_RETURN_VALUES_OPTION => {
   if (!allowedReturnValuesOptions.has(returnValues)) {
-    throw new DynamoDBToolboxError('operations.invalidReturnValuesOption', {
+    throw new DynamoDBToolboxError('options.invalidReturnValuesOption', {
       message: `Invalid returnValues option: '${String(
         returnValues
       )}'. 'returnValues' must be one of: ${[...allowedReturnValuesOptions].join(', ')}.`,
diff --git a/src/v1/operations/utils/parseOptions/parseSelectOption.ts b/src/v1/options/select.ts
similarity index 56%
rename from src/v1/operations/utils/parseOptions/parseSelectOption.ts
rename to src/v1/options/select.ts
index d5148bd7..6bad8aed 100644
--- a/src/v1/operations/utils/parseOptions/parseSelectOption.ts
+++ b/src/v1/options/select.ts
@@ -1,14 +1,31 @@
 import isEmpty from 'lodash.isempty'
 
 import { DynamoDBToolboxError } from 'v1/errors'
-import { SelectOption, selectOptionsSet } from 'v1/operations/constants/options/select'
+
+export type AllAttributesSelectOption = 'ALL_ATTRIBUTES'
+export type AllProjectedAttributesSelectOption = 'ALL_PROJECTED_ATTRIBUTES'
+export type CountSelectOption = 'COUNT'
+export type SpecificAttributesSelectOption = 'SPECIFIC_ATTRIBUTES'
+
+export type SelectOption =
+  | AllAttributesSelectOption
+  | AllProjectedAttributesSelectOption
+  | CountSelectOption
+  | SpecificAttributesSelectOption
+
+export const selectOptionsSet = new Set<SelectOption>([
+  'ALL_ATTRIBUTES',
+  'ALL_PROJECTED_ATTRIBUTES',
+  'COUNT',
+  'SPECIFIC_ATTRIBUTES'
+])
 
 export const parseSelectOption = (
   select: SelectOption,
   { index, attributes }: { index?: string; attributes?: string[] | undefined } = {}
 ): SelectOption => {
   if (!selectOptionsSet.has(select)) {
-    throw new DynamoDBToolboxError('operations.invalidSelectOption', {
+    throw new DynamoDBToolboxError('options.invalidSelectOption', {
       message: `Invalid select option: '${String(select)}'. 'select' must be one of: ${[
         ...selectOptionsSet
       ].join(', ')}.`,
@@ -17,14 +34,14 @@ export const parseSelectOption = (
   }
 
   if (select === 'ALL_PROJECTED_ATTRIBUTES' && index === undefined) {
-    throw new DynamoDBToolboxError('operations.invalidSelectOption', {
+    throw new DynamoDBToolboxError('options.invalidSelectOption', {
       message: `Invalid select option: '${String(select)}'. Please provide an 'index' option.`,
       payload: { select }
     })
   }
 
   if (!isEmpty(attributes) && select !== 'SPECIFIC_ATTRIBUTES') {
-    throw new DynamoDBToolboxError('operations.invalidSelectOption', {
+    throw new DynamoDBToolboxError('options.invalidSelectOption', {
       message: `Invalid select option: '${String(
         select
       )}'. Select must be 'SPECIFIC_ATTRIBUTES' if a filter expression has been provided.`,
diff --git a/src/v1/playground/table.ts b/src/v1/playground/table.ts
index ceedffe4..93e868f2 100644
--- a/src/v1/playground/table.ts
+++ b/src/v1/playground/table.ts
@@ -1,7 +1,8 @@
 /* eslint-disable @typescript-eslint/no-unused-vars */
 import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
 import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'
-import type { Query } from 'v1/operations/types/query'
+
+import type { Query } from 'v1'
 
 import { TableV2, EntityAttributeSavedAs, PrimaryKey, IndexNames, IndexSchema } from 'v1'
 
diff --git a/src/v1/schema/actions/errors.ts b/src/v1/schema/actions/errors.ts
index 5bf98eb2..fc30a7c6 100644
--- a/src/v1/schema/actions/errors.ts
+++ b/src/v1/schema/actions/errors.ts
@@ -1,8 +1,10 @@
 import type { FormatterErrorBlueprints } from './format/errors'
 import type { ParserErrorBlueprints } from './parse/errors'
 import type { ConditionParserErrorBlueprints } from './parseCondition/errors'
+import type { SchemaActionUtilsErrorBlueprints } from './utils/errors'
 
 export type ActionErrorBlueprints =
   | FormatterErrorBlueprints
   | ParserErrorBlueprints
   | ConditionParserErrorBlueprints
+  | SchemaActionUtilsErrorBlueprints
diff --git a/src/v1/schema/actions/format/anyOf.ts b/src/v1/schema/actions/format/anyOf.ts
index 9ee16b30..650e6c69 100644
--- a/src/v1/schema/actions/format/anyOf.ts
+++ b/src/v1/schema/actions/format/anyOf.ts
@@ -1,5 +1,5 @@
 import type { Attribute, AnyOfAttribute } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import type { If } from 'v1/types'
 import { DynamoDBToolboxError } from 'v1/errors'
 
diff --git a/src/v1/schema/actions/format/list.ts b/src/v1/schema/actions/format/list.ts
index 3251583f..ff3eb545 100644
--- a/src/v1/schema/actions/format/list.ts
+++ b/src/v1/schema/actions/format/list.ts
@@ -1,6 +1,6 @@
 import type { If } from 'v1/types'
 import type { ListAttribute } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import { isArray } from 'v1/utils/validation/isArray'
 import { DynamoDBToolboxError } from 'v1/errors'
 
diff --git a/src/v1/schema/actions/format/map.ts b/src/v1/schema/actions/format/map.ts
index 205b9b4d..4b8b3b61 100644
--- a/src/v1/schema/actions/format/map.ts
+++ b/src/v1/schema/actions/format/map.ts
@@ -1,7 +1,7 @@
 import type { O } from 'ts-toolbelt'
 
 import type { MapAttribute, AnyAttribute, Never } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import type { If, OptionalizeUndefinableProperties } from 'v1/types'
 import { isObject } from 'v1/utils/validation'
 import { DynamoDBToolboxError } from 'v1/errors'
diff --git a/src/v1/schema/actions/format/record.ts b/src/v1/schema/actions/format/record.ts
index 53c4811c..b939d2c4 100644
--- a/src/v1/schema/actions/format/record.ts
+++ b/src/v1/schema/actions/format/record.ts
@@ -1,5 +1,5 @@
 import type { RecordAttribute, ResolvePrimitiveAttribute } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import type { If } from 'v1/types'
 import { isObject } from 'v1/utils/validation'
 import { DynamoDBToolboxError } from 'v1/errors'
diff --git a/src/v1/schema/actions/format/schema.ts b/src/v1/schema/actions/format/schema.ts
index cfb60a3d..7c52922e 100644
--- a/src/v1/schema/actions/format/schema.ts
+++ b/src/v1/schema/actions/format/schema.ts
@@ -3,7 +3,7 @@ import type { O } from 'ts-toolbelt'
 import type { OptionalizeUndefinableProperties } from 'v1/types'
 import type { Schema } from 'v1/schema'
 import type { AnyAttribute, Never } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 import { DynamoDBToolboxError } from 'v1/errors'
 import { isObject } from 'v1/utils/validation'
 
diff --git a/src/v1/schema/actions/format/types.ts b/src/v1/schema/actions/format/types.ts
index 295b6412..676b9ccc 100644
--- a/src/v1/schema/actions/format/types.ts
+++ b/src/v1/schema/actions/format/types.ts
@@ -1,6 +1,6 @@
 import type { Schema } from 'v1/schema'
 import type { Attribute } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 
 export type FormatOptions<SCHEMA extends Schema | Attribute> = {
   attributes?: Paths<SCHEMA>[]
diff --git a/src/v1/schema/actions/parseCondition/appendAttributeValueOrPath.ts b/src/v1/schema/actions/parseCondition/appendAttributeValueOrPath.ts
index da841298..c580d8f2 100644
--- a/src/v1/schema/actions/parseCondition/appendAttributeValueOrPath.ts
+++ b/src/v1/schema/actions/parseCondition/appendAttributeValueOrPath.ts
@@ -3,7 +3,7 @@ import type { Attribute } from 'v1/schema/attributes'
 import {
   isAttributePath,
   AppendAttributePathOptions
-} from 'v1/operations/expression/expressionParser'
+} from 'v1/schema/actions/utils/appendAttributePath'
 import type { ConditionParser } from './conditionParser'
 import type { AppendAttributeValueOptions } from './appendAttributeValue'
 
diff --git a/src/v1/schema/actions/parseCondition/condition.ts b/src/v1/schema/actions/parseCondition/condition.ts
index 132f574a..6d53a83d 100644
--- a/src/v1/schema/actions/parseCondition/condition.ts
+++ b/src/v1/schema/actions/parseCondition/condition.ts
@@ -10,7 +10,7 @@ import type {
   ResolvedPrimitiveAttribute,
   PrimitiveAttribute
 } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 
 export type AnyAttributeCondition<
   ATTRIBUTE_PATH extends string,
diff --git a/src/v1/schema/actions/parseCondition/conditionParser.ts b/src/v1/schema/actions/parseCondition/conditionParser.ts
index 0e6fb294..97c2a5db 100644
--- a/src/v1/schema/actions/parseCondition/conditionParser.ts
+++ b/src/v1/schema/actions/parseCondition/conditionParser.ts
@@ -1,13 +1,12 @@
 import type { NativeAttributeValue } from '@aws-sdk/util-dynamodb'
 
-import type { Schema, SchemaAction } from 'v1/schema'
+import { Schema, SchemaAction } from 'v1/schema'
 import type { Attribute } from 'v1/schema/attributes'
-
 import {
   ExpressionParser,
   appendAttributePath,
   AppendAttributePathOptions
-} from 'v1/operations/expression/expressionParser'
+} from 'v1/schema/actions/utils/appendAttributePath'
 
 import { appendAttributeValue, AppendAttributeValueOptions } from './appendAttributeValue'
 import { appendAttributeValueOrPath } from './appendAttributeValueOrPath'
@@ -16,9 +15,8 @@ import { toCommandOptions } from './toCommandOptions'
 import type { Condition } from './condition'
 
 export class ConditionParser<SCHEMA extends Schema | Attribute = Schema | Attribute>
-  implements SchemaAction<SCHEMA>, ExpressionParser {
-  schema: SCHEMA
-
+  extends SchemaAction<SCHEMA>
+  implements ExpressionParser {
   expressionAttributePrefix: `c${string}_`
   expressionAttributeNames: string[]
   expressionAttributeValues: unknown[]
@@ -26,7 +24,7 @@ export class ConditionParser<SCHEMA extends Schema | Attribute = Schema | Attrib
   id: string
 
   constructor(schema: SCHEMA, id = '') {
-    this.schema = schema
+    super(schema)
 
     this.id = id
     this.expressionAttributePrefix = `c${id}_`
diff --git a/src/v1/schema/actions/parseCondition/parseCondition/errors.ts b/src/v1/schema/actions/parseCondition/parseCondition/errors.ts
index 28a5b779..1b735094 100644
--- a/src/v1/schema/actions/parseCondition/parseCondition/errors.ts
+++ b/src/v1/schema/actions/parseCondition/parseCondition/errors.ts
@@ -1,7 +1,7 @@
 import type { ErrorBlueprint } from 'v1/errors/blueprint'
 
 type InvalidConditionErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidCondition'
+  code: 'actions.invalidCondition'
   hasPath: false
   payload: undefined
 }>
diff --git a/src/v1/schema/actions/parseCondition/parseCondition/parseCondition.ts b/src/v1/schema/actions/parseCondition/parseCondition/parseCondition.ts
index 2b3d79a3..a9b39684 100644
--- a/src/v1/schema/actions/parseCondition/parseCondition/parseCondition.ts
+++ b/src/v1/schema/actions/parseCondition/parseCondition/parseCondition.ts
@@ -42,7 +42,7 @@ export const parseCondition = (conditionParser: ConditionParser, condition: Cond
     return parseInCondition(conditionParser, condition)
   }
 
-  throw new DynamoDBToolboxError('operations.invalidCondition', {
+  throw new DynamoDBToolboxError('actions.invalidCondition', {
     message: 'Invalid condition: Unable to detect valid condition type.'
   })
 }
diff --git a/src/v1/schema/actions/parsePaths/index.ts b/src/v1/schema/actions/parsePaths/index.ts
new file mode 100644
index 00000000..0ba37321
--- /dev/null
+++ b/src/v1/schema/actions/parsePaths/index.ts
@@ -0,0 +1,2 @@
+export { PathParser } from './pathParser'
+export type { Paths, AttrPaths, SchemaPaths } from './paths'
diff --git a/src/v1/operations/expression/projection/parser.ts b/src/v1/schema/actions/parsePaths/pathParser.ts
similarity index 55%
rename from src/v1/operations/expression/projection/parser.ts
rename to src/v1/schema/actions/parsePaths/pathParser.ts
index da9a99a0..37816c59 100644
--- a/src/v1/operations/expression/projection/parser.ts
+++ b/src/v1/schema/actions/parsePaths/pathParser.ts
@@ -1,38 +1,49 @@
-import type { Schema } from 'v1/schema'
+import { Schema, SchemaAction } from 'v1/schema'
 import type { Attribute } from 'v1/schema/attributes'
-import { appendAttributePath, ExpressionParser } from 'v1/operations/expression/expressionParser'
+import {
+  appendAttributePath,
+  ExpressionParser,
+  AppendAttributePathOptions
+} from 'v1/schema/actions/utils/appendAttributePath'
 
-import type { AppendAttributePathOptions } from '../expressionParser'
-
-export class ProjectionParser implements ExpressionParser {
-  schema: Schema | Attribute
+export class PathParser<SCHEMA extends Schema | Attribute = Schema | Attribute>
+  extends SchemaAction<SCHEMA>
+  implements ExpressionParser {
   expressionAttributePrefix: `p${string}_`
   expressionAttributeNames: string[]
   expression: string
   id: string
 
-  constructor(schema: Schema | Attribute, id = '') {
-    this.schema = schema
+  constructor(schema: SCHEMA, id = '') {
+    super(schema)
+
     this.expressionAttributePrefix = `p${id}_`
     this.expressionAttributeNames = []
     this.expression = ''
     this.id = id
   }
 
-  resetExpression = (initialStr = '') => {
+  setId(nextId: string): this {
+    this.id = nextId
+    this.expressionAttributePrefix = `p${nextId}_`
+    return this
+  }
+
+  resetExpression(initialStr = ''): this {
     this.expression = initialStr
+    return this
   }
 
-  appendAttributePath = (
-    attributePath: string,
-    options: AppendAttributePathOptions = {}
-  ): Attribute => appendAttributePath(this, attributePath, options)
+  appendAttributePath(attributePath: string, options: AppendAttributePathOptions = {}): Attribute {
+    return appendAttributePath(this, attributePath, options)
+  }
 
-  appendToExpression = (projectionExpressionPart: string) => {
+  appendToExpression(projectionExpressionPart: string): this {
     this.expression += projectionExpressionPart
+    return this
   }
 
-  parseProjection = (attributes: string[]): void => {
+  parse(attributes: string[]): this {
     const [firstAttribute, ...restAttributes] = attributes
     this.appendAttributePath(firstAttribute)
 
@@ -40,15 +51,14 @@ export class ProjectionParser implements ExpressionParser {
       this.appendToExpression(', ')
       this.appendAttributePath(attribute)
     }
+
+    return this
   }
 
-  /**
-   * @debt refactor "factorize with other expressions"
-   */
-  toCommandOptions = (): {
+  toCommandOptions(): {
     ProjectionExpression: string
     ExpressionAttributeNames: Record<string, string>
-  } => {
+  } {
     const ExpressionAttributeNames: Record<string, string> = {}
 
     this.expressionAttributeNames.forEach((expressionAttributeName, index) => {
@@ -65,8 +75,8 @@ export class ProjectionParser implements ExpressionParser {
     }
   }
 
-  clone = (schema?: Schema | Attribute): ProjectionParser => {
-    const clonedParser = new ProjectionParser(schema ?? this.schema, this.id)
+  clone(schema?: Schema | Attribute): PathParser {
+    const clonedParser = new PathParser(schema ?? this.schema, this.id)
 
     clonedParser.expressionAttributeNames = [...this.expressionAttributeNames]
     clonedParser.expression = this.expression
diff --git a/src/v1/schema/actions/paths/index.ts b/src/v1/schema/actions/paths/index.ts
deleted file mode 100644
index 676f1e5f..00000000
--- a/src/v1/schema/actions/paths/index.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export * from './paths'
diff --git a/src/v1/operations/expression/expressionParser.ts b/src/v1/schema/actions/utils/appendAttributePath.ts
similarity index 98%
rename from src/v1/operations/expression/expressionParser.ts
rename to src/v1/schema/actions/utils/appendAttributePath.ts
index efb3ef80..01b8befe 100644
--- a/src/v1/operations/expression/expressionParser.ts
+++ b/src/v1/schema/actions/utils/appendAttributePath.ts
@@ -59,9 +59,9 @@ const defaultNumberAttribute = new PrimitiveAttribute({
   transform: undefined
 })
 
-class InvalidExpressionAttributePathError extends DynamoDBToolboxError<'operations.invalidExpressionAttributePath'> {
+class InvalidExpressionAttributePathError extends DynamoDBToolboxError<'actions.invalidExpressionAttributePath'> {
   constructor(attributePath: string) {
-    super('operations.invalidExpressionAttributePath', {
+    super('actions.invalidExpressionAttributePath', {
       message: `Unable to match expression attribute path with schema: ${attributePath}`,
       payload: { attributePath }
     })
diff --git a/src/v1/operations/expression/errors.ts b/src/v1/schema/actions/utils/errors.ts
similarity index 65%
rename from src/v1/operations/expression/errors.ts
rename to src/v1/schema/actions/utils/errors.ts
index c8d5c197..8c8b85f8 100644
--- a/src/v1/operations/expression/errors.ts
+++ b/src/v1/schema/actions/utils/errors.ts
@@ -1,11 +1,11 @@
 import type { ErrorBlueprint } from 'v1/errors/blueprint'
 
 type InvalidExpressionAttributePathErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.invalidExpressionAttributePath'
+  code: 'actions.invalidExpressionAttributePath'
   hasPath: false
   payload: {
     attributePath: string
   }
 }>
 
-export type ExpressionParsersErrorBlueprints = InvalidExpressionAttributePathErrorBlueprint
+export type SchemaActionUtilsErrorBlueprints = InvalidExpressionAttributePathErrorBlueprint
diff --git a/src/v1/table/actions/parsePrimaryKey/errors.ts b/src/v1/table/actions/parsePrimaryKey/errors.ts
index 2357f319..ab6bf1ff 100644
--- a/src/v1/table/actions/parsePrimaryKey/errors.ts
+++ b/src/v1/table/actions/parsePrimaryKey/errors.ts
@@ -1,7 +1,7 @@
 import type { ErrorBlueprint } from 'v1/errors/blueprint'
 
 type InvalidKeyPartErrorBlueprint = ErrorBlueprint<{
-  code: 'operations.parsePrimaryKey.invalidKeyPart'
+  code: 'actions.parsePrimaryKey.invalidKeyPart'
   hasPath: true
   payload: {
     expected: string
diff --git a/src/v1/table/actions/parsePrimaryKey/primaryKeyParser.ts b/src/v1/table/actions/parsePrimaryKey/primaryKeyParser.ts
index a5882228..905dec3b 100644
--- a/src/v1/table/actions/parsePrimaryKey/primaryKeyParser.ts
+++ b/src/v1/table/actions/parsePrimaryKey/primaryKeyParser.ts
@@ -28,7 +28,7 @@ export type PrimaryKey<TABLE extends TableV2 = TableV2> = TableV2 extends TABLE
   : never
 
 export class PrimaryKeyParser<TABLE extends TableV2 = TableV2> extends TableAction<TABLE> {
-  static operationName = 'parsePrimaryKey' as const
+  static actionName = 'parsePrimaryKey' as const
 
   constructor(table: TABLE) {
     super(table)
@@ -44,7 +44,7 @@ export class PrimaryKeyParser<TABLE extends TableV2 = TableV2> extends TableActi
     const partitionKeyValue = keyInput[partitionKey.name]
 
     if (!partitionKeyValidator(partitionKeyValue)) {
-      throw new DynamoDBToolboxError('operations.parsePrimaryKey.invalidKeyPart', {
+      throw new DynamoDBToolboxError('actions.parsePrimaryKey.invalidKeyPart', {
         message: `Invalid partition key: ${partitionKey.name}`,
         path: partitionKey.name,
         payload: {
@@ -68,7 +68,7 @@ export class PrimaryKeyParser<TABLE extends TableV2 = TableV2> extends TableActi
     const sortKeyValue = keyInput[sortKey.name]
 
     if (!sortKeyValidator(sortKeyValue)) {
-      throw new DynamoDBToolboxError('operations.parsePrimaryKey.invalidKeyPart', {
+      throw new DynamoDBToolboxError('actions.parsePrimaryKey.invalidKeyPart', {
         message: `Invalid sort key: ${sortKey.name}`,
         path: sortKey.name,
         payload: {
diff --git a/src/v1/table/actions/queryCommand/index.ts b/src/v1/table/actions/queryCommand/index.ts
index e58dd9ce..54e9be8a 100644
--- a/src/v1/table/actions/queryCommand/index.ts
+++ b/src/v1/table/actions/queryCommand/index.ts
@@ -1,3 +1,4 @@
 export { QueryCommand } from './queryCommand'
 export type { QueryResponse } from './queryCommand'
 export type { QueryOptions } from './options'
+export type { Query } from './types'
diff --git a/src/v1/table/actions/queryCommand/options.ts b/src/v1/table/actions/queryCommand/options.ts
index da5fffae..356f38c6 100644
--- a/src/v1/table/actions/queryCommand/options.ts
+++ b/src/v1/table/actions/queryCommand/options.ts
@@ -1,14 +1,15 @@
 import type { TableV2 } from 'v1/table'
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPathsIntersection } from 'v1/entity/actions/paths'
+import type { EntityPathsIntersection } from 'v1/entity/actions/parsePaths'
 import type { EntityCondition } from 'v1/entity/actions/parseCondition'
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
+import type { CapacityOption } from 'v1/options/capacity'
 import type {
   SelectOption,
   AllProjectedAttributesSelectOption,
   SpecificAttributesSelectOption
-} from 'v1/operations/constants/options/select'
-import type { Query } from 'v1/operations/types'
+} from 'v1/options/select'
+
+import type { Query } from './types'
 
 export type QueryOptions<
   TABLE extends TableV2 = TableV2,
diff --git a/src/v1/table/actions/queryCommand/queryCommand.ts b/src/v1/table/actions/queryCommand/queryCommand.ts
index ae79f105..fc1b0844 100644
--- a/src/v1/table/actions/queryCommand/queryCommand.ts
+++ b/src/v1/table/actions/queryCommand/queryCommand.ts
@@ -10,13 +10,13 @@ import type { NativeAttributeValue } from '@aws-sdk/util-dynamodb'
 import { TableV2, TableAction, $entities, $table } from 'v1/table'
 import type { EntityV2 } from 'v1/entity'
 import { EntityFormatter, FormattedItem } from 'v1/entity/actions/format'
-import type { EntityPaths } from 'v1/entity/actions/paths'
-import type { CountSelectOption } from 'v1/operations/constants/options/select'
-import type { Query } from 'v1/operations/types'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
+import type { CountSelectOption } from 'v1/options/select'
 import { DynamoDBToolboxError } from 'v1/errors'
 import { isString } from 'v1/utils/validation'
 
 import type { QueryOptions } from './options'
+import type { Query } from './types'
 import { queryParams } from './queryParams'
 
 const $query = Symbol('$query')
@@ -67,7 +67,7 @@ export class QueryCommand<
   QUERY extends Query<TABLE> = Query<TABLE>,
   OPTIONS extends QueryOptions<TABLE, ENTITIES, QUERY> = QueryOptions<TABLE, ENTITIES, QUERY>
 > extends TableAction<TABLE, ENTITIES> {
-  static operationName = 'query' as const;
+  static actionName = 'query' as const;
 
   [$query]?: QUERY;
   [$options]: OPTIONS
@@ -124,7 +124,7 @@ export class QueryCommand<
 
   params = (): QueryCommandInput => {
     if (!this[$query]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'QueryCommand incomplete: Missing "query" property'
       })
     }
diff --git a/src/v1/table/actions/queryCommand/queryParams/parseQuery.ts b/src/v1/table/actions/queryCommand/queryParams/parseQuery.ts
index fab0e9a2..38ed8cfe 100644
--- a/src/v1/table/actions/queryCommand/queryParams/parseQuery.ts
+++ b/src/v1/table/actions/queryCommand/queryParams/parseQuery.ts
@@ -11,8 +11,8 @@ import {
   Condition,
   PrimitiveAttributeExtraCondition
 } from 'v1/schema/actions/parseCondition'
-import type { Query } from 'v1/operations/types'
-import { queryOperatorSet } from 'v1/operations/types/query'
+
+import { queryOperatorSet, Query } from '../types'
 
 const defaultAttribute: Omit<ConstructorParameters<typeof PrimitiveAttribute>[0], 'type'> = {
   required: 'never',
diff --git a/src/v1/table/actions/queryCommand/queryParams/queryParams.ts b/src/v1/table/actions/queryCommand/queryParams/queryParams.ts
index 44e32ef5..667ed7d9 100644
--- a/src/v1/table/actions/queryCommand/queryParams/queryParams.ts
+++ b/src/v1/table/actions/queryCommand/queryParams/queryParams.ts
@@ -5,19 +5,18 @@ import { isBoolean } from 'v1/utils/validation'
 import { DynamoDBToolboxError } from 'v1/errors'
 import type { TableV2 } from 'v1/table'
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPaths } from 'v1/entity/actions/paths'
+import { EntityPathParser, EntityPaths } from 'v1/entity/actions/parsePaths'
 import { EntityConditionParser, EntityCondition } from 'v1/entity/actions/parseCondition'
-import type { Query } from 'v1/operations/types'
 
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseIndexOption } from 'v1/operations/utils/parseOptions/parseIndexOption'
-import { parseConsistentOption } from 'v1/operations/utils/parseOptions/parseConsistentOption'
-import { parseLimitOption } from 'v1/operations/utils/parseOptions/parseLimitOption'
-import { parseMaxPagesOption } from 'v1/operations/utils/parseOptions/parseMaxPagesOption'
-import { parseSelectOption } from 'v1/operations/utils/parseOptions/parseSelectOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
-import { parseProjection } from 'v1/operations/expression/projection/parse'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseIndexOption } from 'v1/options/index'
+import { parseConsistentOption } from 'v1/options/consistent'
+import { parseLimitOption } from 'v1/options/limit'
+import { parseMaxPagesOption } from 'v1/options/maxPages'
+import { parseSelectOption } from 'v1/options/select'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 
+import type { Query } from '../types'
 import type { QueryOptions } from '../options'
 import { parseQuery } from './parseQuery'
 
@@ -133,14 +132,20 @@ export const queryParams = <
 
       // TODO: For now, we compute the projectionExpression using the first entity. Will probably use Table schemas once they exist.
       if (projectionExpression === undefined && attributes !== undefined) {
+        const { entityAttributeName } = entity
+
         const {
           ExpressionAttributeNames: projectionExpressionAttributeNames,
           ProjectionExpression
-        } = parseProjection<EntityV2, EntityPaths[]>(entity, [
-          // entityAttributeName is required at all times for formatting
-          ...(attributes.includes(entity.entityAttributeName) ? [] : [entity.entityAttributeName]),
-          ...attributes
-        ])
+        } = entity
+          .build(EntityPathParser)
+          .parse(
+            // entityAttributeName is required at all times for formatting
+            attributes.includes(entityAttributeName)
+              ? attributes
+              : [entityAttributeName, ...attributes]
+          )
+          .toCommandOptions()
 
         Object.assign(expressionAttributeNames, projectionExpressionAttributeNames)
         projectionExpression = ProjectionExpression
diff --git a/src/v1/operations/types/query.ts b/src/v1/table/actions/queryCommand/types.ts
similarity index 100%
rename from src/v1/operations/types/query.ts
rename to src/v1/table/actions/queryCommand/types.ts
diff --git a/src/v1/table/actions/scanCommand/options.ts b/src/v1/table/actions/scanCommand/options.ts
index 4f56ce96..f311be71 100644
--- a/src/v1/table/actions/scanCommand/options.ts
+++ b/src/v1/table/actions/scanCommand/options.ts
@@ -1,14 +1,14 @@
 import type { TableV2 } from 'v1/table'
 import type { IndexNames } from 'v1/table/actions/indexes'
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPathsIntersection } from 'v1/entity/actions/paths'
+import type { EntityPathsIntersection } from 'v1/entity/actions/parsePaths'
 import type { EntityCondition } from 'v1/entity/actions/parseCondition'
-import type { CapacityOption } from 'v1/operations/constants/options/capacity'
+import type { CapacityOption } from 'v1/options/capacity'
 import type {
   SelectOption,
   AllProjectedAttributesSelectOption,
   SpecificAttributesSelectOption
-} from 'v1/operations/constants/options/select'
+} from 'v1/options/select'
 
 export type ScanOptions<
   TABLE extends TableV2 = TableV2,
diff --git a/src/v1/table/actions/scanCommand/scanCommand.ts b/src/v1/table/actions/scanCommand/scanCommand.ts
index e907c919..77b87c96 100644
--- a/src/v1/table/actions/scanCommand/scanCommand.ts
+++ b/src/v1/table/actions/scanCommand/scanCommand.ts
@@ -10,8 +10,8 @@ import type { NativeAttributeValue } from '@aws-sdk/util-dynamodb'
 import { TableV2, TableAction, $table, $entities } from 'v1/table'
 import type { EntityV2 } from 'v1/entity'
 import { EntityFormatter, FormattedItem } from 'v1/entity/actions/format'
-import type { EntityPaths } from 'v1/entity/actions/paths'
-import type { CountSelectOption } from 'v1/operations/constants/options/select'
+import type { EntityPaths } from 'v1/entity/actions/parsePaths'
+import type { CountSelectOption } from 'v1/options/select'
 import { isString } from 'v1/utils/validation'
 
 import type { ScanOptions } from './options'
@@ -59,7 +59,7 @@ export class ScanCommand<
   ENTITIES extends EntityV2[] = EntityV2[],
   OPTIONS extends ScanOptions<TABLE, ENTITIES> = ScanOptions<TABLE, ENTITIES>
 > extends TableAction<TABLE, ENTITIES> {
-  static operationName = 'scan' as const;
+  static actionName = 'scan' as const;
 
   [$options]: OPTIONS
 
diff --git a/src/v1/table/actions/scanCommand/scanParams/scanParams.ts b/src/v1/table/actions/scanCommand/scanParams/scanParams.ts
index 31526b3b..d6e17a5e 100644
--- a/src/v1/table/actions/scanCommand/scanParams/scanParams.ts
+++ b/src/v1/table/actions/scanCommand/scanParams/scanParams.ts
@@ -1,20 +1,19 @@
 import type { ScanCommandInput } from '@aws-sdk/lib-dynamodb'
 import isEmpty from 'lodash.isempty'
 
+import { DynamoDBToolboxError } from 'v1/errors'
 import type { TableV2 } from 'v1/table'
 import type { EntityV2 } from 'v1/entity'
-import type { EntityPaths } from 'v1/entity/actions/paths'
+import { EntityPathParser, EntityPaths } from 'v1/entity/actions/parsePaths'
 import { EntityConditionParser, EntityCondition } from 'v1/entity/actions/parseCondition'
-import { DynamoDBToolboxError } from 'v1/errors'
-import { parseCapacityOption } from 'v1/operations/utils/parseOptions/parseCapacityOption'
-import { parseIndexOption } from 'v1/operations/utils/parseOptions/parseIndexOption'
-import { parseConsistentOption } from 'v1/operations/utils/parseOptions/parseConsistentOption'
-import { parseLimitOption } from 'v1/operations/utils/parseOptions/parseLimitOption'
-import { parseMaxPagesOption } from 'v1/operations/utils/parseOptions/parseMaxPagesOption'
-import { parseSelectOption } from 'v1/operations/utils/parseOptions/parseSelectOption'
-import { rejectExtraOptions } from 'v1/operations/utils/parseOptions/rejectExtraOptions'
+import { parseCapacityOption } from 'v1/options/capacity'
+import { parseIndexOption } from 'v1/options/index'
+import { parseConsistentOption } from 'v1/options/consistent'
+import { parseLimitOption } from 'v1/options/limit'
+import { parseMaxPagesOption } from 'v1/options/maxPages'
+import { parseSelectOption } from 'v1/options/select'
+import { rejectExtraOptions } from 'v1/options/rejectExtraOptions'
 import { isInteger } from 'v1/utils/validation/isInteger'
-import { parseProjection } from 'v1/operations/expression/projection/parse'
 
 import type { ScanOptions } from '../options'
 
@@ -136,14 +135,20 @@ export const scanParams = <
 
       // TODO: For now, we compute the projectionExpression using the first entity. Will probably use Table schemas once they exist.
       if (projectionExpression === undefined && attributes !== undefined) {
+        const { entityAttributeName } = entity
+
         const {
           ExpressionAttributeNames: projectionExpressionAttributeNames,
           ProjectionExpression
-        } = parseProjection<EntityV2, EntityPaths[]>(entity, [
-          // entityAttributeName is required at all times for formatting
-          ...(attributes.includes(entity.entityAttributeName) ? [] : [entity.entityAttributeName]),
-          ...attributes
-        ])
+        } = entity
+          .build(EntityPathParser)
+          .parse(
+            // entityAttributeName is required at all times for formatting
+            attributes.includes(entityAttributeName)
+              ? attributes
+              : [entityAttributeName, ...attributes]
+          )
+          .toCommandOptions()
 
         Object.assign(expressionAttributeNames, projectionExpressionAttributeNames)
         projectionExpression = ProjectionExpression
diff --git a/src/v1/table/table.ts b/src/v1/table/table.ts
index 1ec19c11..79696ceb 100644
--- a/src/v1/table/table.ts
+++ b/src/v1/table/table.ts
@@ -70,7 +70,7 @@ export class TableV2<
 
   getDocumentClient = () => {
     if (this.documentClient === undefined) {
-      throw new DynamoDBToolboxError('operations.missingDocumentClient', {
+      throw new DynamoDBToolboxError('actions.missingDocumentClient', {
         message: 'You need to set a document client on your table to send a command'
       })
     }
@@ -89,8 +89,7 @@ export class TableAction<
   TABLE extends TableV2 = TableV2,
   ENTITIES extends EntityV2[] = EntityV2[]
 > {
-  static operationType = 'table'
-  static operationName: string;
+  static actionName: string;
 
   [$table]: TABLE;
   [$entities]: ENTITIES


Test patch:
diff --git a/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.unit.test.ts b/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.unit.test.ts
index c096c417..875d46f2 100644
--- a/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.unit.test.ts
+++ b/src/v1/entity/actions/batchWrite/batchDeleteItem/batchDeleteItem.unit.test.ts
@@ -38,6 +38,6 @@ describe('BatchDeleteItem', () => {
     const invalidCall = () => TestEntity.build(BatchDeleteItemRequest).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 })
diff --git a/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.unit.test.ts b/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.unit.test.ts
index 087118df..edd43a43 100644
--- a/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.unit.test.ts
+++ b/src/v1/entity/actions/batchWrite/batchPutItem/batchPutItem.unit.test.ts
@@ -39,6 +39,6 @@ describe('BatchPutItem', () => {
     const invalidCall = () => TestEntity.build(BatchPutItemRequest).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 })
diff --git a/src/v1/entity/actions/batchWrite/batchWrite.unit.test.ts b/src/v1/entity/actions/batchWrite/batchWrite.unit.test.ts
index bbead59e..bfe86333 100644
--- a/src/v1/entity/actions/batchWrite/batchWrite.unit.test.ts
+++ b/src/v1/entity/actions/batchWrite/batchWrite.unit.test.ts
@@ -65,7 +65,7 @@ describe('buildBatchWriteCommandInput', () => {
     const invalidCall = () => getBatchWriteCommandInput([])
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('batchWrites data to a single table', () => {
@@ -95,7 +95,7 @@ describe('buildBatchWriteCommandInput', () => {
       )
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets capacity options', () => {
@@ -127,9 +127,7 @@ describe('buildBatchWriteCommandInput', () => {
         { capacity: 'test' }
       )
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets metrics options', () => {
@@ -161,9 +159,7 @@ describe('buildBatchWriteCommandInput', () => {
         { metrics: 'test' }
       )
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMetricsOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidMetricsOption' }))
   })
 
   it('batchWrites data to a single table with multiple items', () => {
diff --git a/src/v1/entity/actions/commands/deleteItem/deleteItemParams/deleteItemParams.unit.test.ts b/src/v1/entity/actions/commands/deleteItem/deleteItemParams/deleteItemParams.unit.test.ts
index ab80bb24..656d1a0b 100644
--- a/src/v1/entity/actions/commands/deleteItem/deleteItemParams/deleteItemParams.unit.test.ts
+++ b/src/v1/entity/actions/commands/deleteItem/deleteItemParams/deleteItemParams.unit.test.ts
@@ -127,9 +127,7 @@ describe('delete', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets metrics options', () => {
@@ -152,9 +150,7 @@ describe('delete', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMetricsOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidMetricsOption' }))
   })
 
   it('sets returnValues options', () => {
@@ -178,7 +174,7 @@ describe('delete', () => {
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
     expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidReturnValuesOption' })
+      expect.objectContaining({ code: 'options.invalidReturnValuesOption' })
     )
   })
 
@@ -193,7 +189,7 @@ describe('delete', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets condition', () => {
@@ -215,7 +211,7 @@ describe('delete', () => {
     const invalidCall = () => TestEntity.build(DeleteItemCommand).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('transformed key', () => {
diff --git a/src/v1/entity/actions/commands/getItem/getItemParams/getItemParams.unit.test.ts b/src/v1/entity/actions/commands/getItem/getItemParams/getItemParams.unit.test.ts
index a01d39ab..9ad4a58c 100644
--- a/src/v1/entity/actions/commands/getItem/getItemParams/getItemParams.unit.test.ts
+++ b/src/v1/entity/actions/commands/getItem/getItemParams/getItemParams.unit.test.ts
@@ -129,9 +129,7 @@ describe('get', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets consistent option', () => {
@@ -155,7 +153,7 @@ describe('get', () => {
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
     expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidConsistentOption' })
+      expect.objectContaining({ code: 'options.invalidConsistentOption' })
     )
   })
 
@@ -170,7 +168,7 @@ describe('get', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('parses attribute projections', () => {
@@ -187,7 +185,7 @@ describe('get', () => {
     const invalidCall = () => TestEntity.build(GetItemCommand).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('transformed key', () => {
diff --git a/src/v1/entity/actions/commands/putItem/putItemParams/putItemParams.unit.test.ts b/src/v1/entity/actions/commands/putItem/putItemParams/putItemParams.unit.test.ts
index 8c16dcbb..dc472770 100644
--- a/src/v1/entity/actions/commands/putItem/putItemParams/putItemParams.unit.test.ts
+++ b/src/v1/entity/actions/commands/putItem/putItemParams/putItemParams.unit.test.ts
@@ -391,9 +391,7 @@ describe('put', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets metrics options', () => {
@@ -416,9 +414,7 @@ describe('put', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMetricsOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidMetricsOption' }))
   })
 
   it('sets returnValues options', () => {
@@ -442,7 +438,7 @@ describe('put', () => {
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
     expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidReturnValuesOption' })
+      expect.objectContaining({ code: 'options.invalidReturnValuesOption' })
     )
   })
 
@@ -457,7 +453,7 @@ describe('put', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets condition', () => {
@@ -479,7 +475,7 @@ describe('put', () => {
     const invalidCall = () => TestEntity.build(PutItemCommand).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('transformed key/attribute', () => {
diff --git a/src/v1/entity/actions/commands/updateItem/updateItemParams/updateItemParams.unit.test.ts b/src/v1/entity/actions/commands/updateItem/updateItemParams/updateItemParams.unit.test.ts
index 522eb243..9989506c 100644
--- a/src/v1/entity/actions/commands/updateItem/updateItemParams/updateItemParams.unit.test.ts
+++ b/src/v1/entity/actions/commands/updateItem/updateItemParams/updateItemParams.unit.test.ts
@@ -62,7 +62,7 @@ const TestEntity = new EntityV2({
     test_string: string().optional().updateDefault('default string'),
     test_number_default: number().optional().updateDefault(0),
     test_boolean_default: boolean().optional().updateDefault(false),
-    operationsCount: number()
+    touchCount: number()
       .putDefault(1)
       .updateDefault(() => $add(1))
   }).and(schema => ({
@@ -188,7 +188,7 @@ describe('update', () => {
       '#s_7': '_ct',
       '#s_8': '_ct',
       '#s_9': '_md',
-      '#a_1': 'operationsCount'
+      '#a_1': 'touchCount'
     })
     expect(ExpressionAttributeValues).toStrictEqual({
       ':s_1': 'default string',
@@ -392,7 +392,7 @@ describe('update', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -413,7 +413,7 @@ describe('update', () => {
         .item({
           email: 'test-pk',
           sort: 'test-pk',
-          // @ts-expect-error $get is only available in SET operations
+          // @ts-expect-error $get is only available in SET updates
           test_number_default: $get('test_string', $add(42))
         })
         .params()
@@ -433,7 +433,7 @@ describe('update', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -450,7 +450,7 @@ describe('update', () => {
     expect(invalidCallE).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs sum operation', () => {
+  it('performs sum update', () => {
     const {
       UpdateExpression: UpdateExpressionA,
       ExpressionAttributeNames: ExpressionAttributeNamesA,
@@ -533,7 +533,7 @@ describe('update', () => {
     expect(ExpressionAttributeValuesD).toMatchObject({ ':s_2': 5, ':s_3': 10 })
   })
 
-  it('rejects invalid sum operation', () => {
+  it('rejects invalid sum update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemCommand)
         .item({
@@ -572,7 +572,7 @@ describe('update', () => {
 
     expect(invalidCallC).toThrow(DynamoDBToolboxError)
     expect(invalidCallC).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallD = () =>
@@ -589,7 +589,7 @@ describe('update', () => {
     expect(invalidCallD).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs subtract operation', () => {
+  it('performs subtract update', () => {
     const {
       UpdateExpression: UpdateExpressionA,
       ExpressionAttributeNames: ExpressionAttributeNamesA,
@@ -672,7 +672,7 @@ describe('update', () => {
     expect(ExpressionAttributeValuesD).toMatchObject({ ':s_2': 5, ':s_3': 10 })
   })
 
-  it('rejects invalid subtract operation', () => {
+  it('rejects invalid subtract update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemCommand)
         .item({
@@ -711,7 +711,7 @@ describe('update', () => {
 
     expect(invalidCallC).toThrow(DynamoDBToolboxError)
     expect(invalidCallC).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallD = () =>
@@ -728,7 +728,7 @@ describe('update', () => {
     expect(invalidCallD).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs number and set add operations', () => {
+  it('performs number and set add updates', () => {
     const {
       UpdateExpression,
       ExpressionAttributeNames,
@@ -753,7 +753,7 @@ describe('update', () => {
     })
   })
 
-  it('rejects an invalid number add operation', () => {
+  it('rejects an invalid number add update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemCommand)
         .item({
@@ -809,7 +809,7 @@ describe('update', () => {
     })
   })
 
-  it('performs a delete operation on set', () => {
+  it('performs a delete update on set', () => {
     const {
       UpdateExpression,
       ExpressionAttributeNames,
@@ -834,7 +834,7 @@ describe('update', () => {
     })
   })
 
-  it('rejects an invalid delete operation', () => {
+  it('rejects an invalid delete update', () => {
     const invalidCall = () =>
       TestEntity.build(UpdateItemCommand)
         .item({
@@ -939,7 +939,7 @@ describe('update', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -963,7 +963,7 @@ describe('update', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_list: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             2: $get('test_string', $add(42))
           }
         })
@@ -986,7 +986,7 @@ describe('update', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1147,7 +1147,7 @@ describe('update', () => {
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
     expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
   })
 
@@ -1225,7 +1225,7 @@ describe('update', () => {
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
     expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
   })
 
@@ -1310,7 +1310,7 @@ describe('update', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -1334,7 +1334,7 @@ describe('update', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_map: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             optional: $get('test_number_default', $add(42))
           }
         })
@@ -1357,7 +1357,7 @@ describe('update', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1509,7 +1509,7 @@ describe('update', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -1533,7 +1533,7 @@ describe('update', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_record: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             foo: $get('test_number_default', $add(42))
           }
         })
@@ -1556,7 +1556,7 @@ describe('update', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1727,9 +1727,7 @@ describe('update', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('fails on invalid metrics option', () => {
@@ -1743,9 +1741,7 @@ describe('update', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMetricsOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidMetricsOption' }))
   })
 
   it('fails on invalid returnValues option', () => {
@@ -1760,7 +1756,7 @@ describe('update', () => {
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
     expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidReturnValuesOption' })
+      expect.objectContaining({ code: 'options.invalidReturnValuesOption' })
     )
   })
 
@@ -1775,7 +1771,7 @@ describe('update', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets conditions', () => {
@@ -1797,7 +1793,7 @@ describe('update', () => {
     const invalidCall = () => TestEntity.build(UpdateItemCommand).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('transformed key/attribute (partial - 1)', () => {
diff --git a/src/v1/entity/actions/transactions/conditionCheck/conditionCheckParams/conditionCheckParams.unit.test.ts b/src/v1/entity/actions/transactions/conditionCheck/conditionCheckParams/conditionCheckParams.unit.test.ts
index 928f1ed9..2daf7406 100644
--- a/src/v1/entity/actions/transactions/conditionCheck/conditionCheckParams/conditionCheckParams.unit.test.ts
+++ b/src/v1/entity/actions/transactions/conditionCheck/conditionCheckParams/conditionCheckParams.unit.test.ts
@@ -76,7 +76,7 @@ describe('condition check transaction', () => {
     const invalidCall = () => TestEntity.build(ConditionCheck).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('missing condition', () => {
@@ -84,7 +84,7 @@ describe('condition check transaction', () => {
       TestEntity.build(ConditionCheck).key({ email: 'x', sort: 'y' }).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('fails with invalid condition', () => {
@@ -98,6 +98,6 @@ describe('condition check transaction', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidCondition' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.invalidCondition' }))
   })
 })
diff --git a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/transactDeleteItemParams.unit.test.ts b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/transactDeleteItemParams.unit.test.ts
index f44976aa..777de3d4 100644
--- a/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/transactDeleteItemParams.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactDeleteItem/transactDeleteItemParams/transactDeleteItemParams.unit.test.ts
@@ -111,7 +111,7 @@ describe('delete transaction', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets condition', () => {
@@ -133,6 +133,6 @@ describe('delete transaction', () => {
     const invalidCall = () => TestEntity.build(DeleteItemTransaction).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 })
diff --git a/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/transactGetItemParams.unit.test.ts b/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/transactGetItemParams.unit.test.ts
index 46cffeaa..78300f30 100644
--- a/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/transactGetItemParams.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactGetItem/transactGetItemParams/transactGetItemParams.unit.test.ts
@@ -127,7 +127,7 @@ describe('Get transaction', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets projection', () => {
@@ -144,6 +144,6 @@ describe('Get transaction', () => {
     const invalidCall = () => TestEntity.build(GetItemTransaction).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 })
diff --git a/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.unit.test.ts b/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.unit.test.ts
index d489c0e2..359f29e3 100644
--- a/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactGetItems/transactGetItems.unit.test.ts
@@ -217,7 +217,7 @@ describe('generateTransactGetCommandInput', () => {
 
     expect(invalidTransactGetCommandInputGeneration).toThrow(DynamoDBToolboxError)
     expect(invalidTransactGetCommandInputGeneration).toThrow(
-      expect.objectContaining({ code: 'operations.unknownOption' })
+      expect.objectContaining({ code: 'options.unknownOption' })
     )
   })
   it('should generate a transaction with the correct parameters', async () => {
@@ -412,7 +412,7 @@ describe('formatTransactGetResponse', () => {
 
     expect(invalidFormatting).toThrow(DynamoDBToolboxError)
     expect(invalidFormatting).toThrow(
-      expect.objectContaining({ code: 'operations.inconsistentNumberOfItems' })
+      expect.objectContaining({ code: 'actions.inconsistentNumberOfItems' })
     )
   })
 })
diff --git a/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/transactPutItemParams.unit.test.ts b/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/transactPutItemParams.unit.test.ts
index 45e72fae..4b0085aa 100644
--- a/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/transactPutItemParams.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactPutItem/transactPutItemParams/transactPutItemParams.unit.test.ts
@@ -376,7 +376,7 @@ describe('put transaction', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets condition', () => {
@@ -398,6 +398,6 @@ describe('put transaction', () => {
     const invalidCall = () => TestEntity.build(PutItemTransaction).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 })
diff --git a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/transactUpdateItemParams.unit.test.ts b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/transactUpdateItemParams.unit.test.ts
index 951b5333..5a9e6e2b 100644
--- a/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/transactUpdateItemParams.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactUpdateItem/transactUpdateItemParams/transactUpdateItemParams.unit.test.ts
@@ -62,7 +62,7 @@ const TestEntity = new EntityV2({
     test_string: string().optional().updateDefault('default string'),
     test_number_default: number().optional().updateDefault(0),
     test_boolean_default: boolean().optional().updateDefault(false),
-    operationsCount: number()
+    touchCount: number()
       .putDefault(1)
       .updateDefault(() => $add(1))
   }).and(schema => ({
@@ -188,7 +188,7 @@ describe('update transaction', () => {
       '#s_7': '_ct',
       '#s_8': '_ct',
       '#s_9': '_md',
-      '#a_1': 'operationsCount'
+      '#a_1': 'touchCount'
     })
     expect(ExpressionAttributeValues).toStrictEqual({
       ':s_1': 'default string',
@@ -392,7 +392,7 @@ describe('update transaction', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -413,7 +413,7 @@ describe('update transaction', () => {
         .item({
           email: 'test-pk',
           sort: 'test-pk',
-          // @ts-expect-error $get is only available in SET operations
+          // @ts-expect-error $get is only available in SET updates
           test_number_default: $get('test_string', $add(42))
         })
         .params()
@@ -433,7 +433,7 @@ describe('update transaction', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -450,7 +450,7 @@ describe('update transaction', () => {
     expect(invalidCallE).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs sum operation', () => {
+  it('performs sum update', () => {
     const {
       UpdateExpression: UpdateExpressionA,
       ExpressionAttributeNames: ExpressionAttributeNamesA,
@@ -533,7 +533,7 @@ describe('update transaction', () => {
     expect(ExpressionAttributeValuesD).toMatchObject({ ':s_2': 5, ':s_3': 10 })
   })
 
-  it('rejects invalid sum operation', () => {
+  it('rejects invalid sum update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemTransaction)
         .item({
@@ -572,7 +572,7 @@ describe('update transaction', () => {
 
     expect(invalidCallC).toThrow(DynamoDBToolboxError)
     expect(invalidCallC).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallD = () =>
@@ -589,7 +589,7 @@ describe('update transaction', () => {
     expect(invalidCallD).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs subtract operation', () => {
+  it('performs subtract update', () => {
     const {
       UpdateExpression: UpdateExpressionA,
       ExpressionAttributeNames: ExpressionAttributeNamesA,
@@ -672,7 +672,7 @@ describe('update transaction', () => {
     expect(ExpressionAttributeValuesD).toMatchObject({ ':s_2': 5, ':s_3': 10 })
   })
 
-  it('rejects invalid subtract operation', () => {
+  it('rejects invalid subtract update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemTransaction)
         .item({
@@ -711,7 +711,7 @@ describe('update transaction', () => {
 
     expect(invalidCallC).toThrow(DynamoDBToolboxError)
     expect(invalidCallC).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallD = () =>
@@ -728,7 +728,7 @@ describe('update transaction', () => {
     expect(invalidCallD).toThrow(expect.objectContaining({ code: 'parsing.invalidAttributeInput' }))
   })
 
-  it('performs number and set add operations', () => {
+  it('performs number and set add updates', () => {
     const {
       UpdateExpression,
       ExpressionAttributeNames,
@@ -753,7 +753,7 @@ describe('update transaction', () => {
     })
   })
 
-  it('rejects an invalid number add operation', () => {
+  it('rejects an invalid number add update', () => {
     const invalidCallA = () =>
       TestEntity.build(UpdateItemTransaction)
         .item({
@@ -809,7 +809,7 @@ describe('update transaction', () => {
     })
   })
 
-  it('performs a delete operation on set', () => {
+  it('performs a delete update on set', () => {
     const {
       UpdateExpression,
       ExpressionAttributeNames,
@@ -834,7 +834,7 @@ describe('update transaction', () => {
     })
   })
 
-  it('rejects an invalid delete operation', () => {
+  it('rejects an invalid delete update', () => {
     const invalidCall = () =>
       TestEntity.build(UpdateItemTransaction)
         .item({
@@ -939,7 +939,7 @@ describe('update transaction', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -963,7 +963,7 @@ describe('update transaction', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_list: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             2: $get('test_string', $add(42))
           }
         })
@@ -986,7 +986,7 @@ describe('update transaction', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1147,7 +1147,7 @@ describe('update transaction', () => {
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
     expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
   })
 
@@ -1225,7 +1225,7 @@ describe('update transaction', () => {
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
     expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
   })
 
@@ -1310,7 +1310,7 @@ describe('update transaction', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -1334,7 +1334,7 @@ describe('update transaction', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_map: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             optional: $get('test_number_default', $add(42))
           }
         })
@@ -1357,7 +1357,7 @@ describe('update transaction', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1509,7 +1509,7 @@ describe('update transaction', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallB = () =>
@@ -1533,7 +1533,7 @@ describe('update transaction', () => {
           email: 'test-pk',
           sort: 'test-pk',
           test_record: {
-            // @ts-expect-error $get is only available in SET operations
+            // @ts-expect-error $get is only available in SET updates
             foo: $get('test_number_default', $add(42))
           }
         })
@@ -1556,7 +1556,7 @@ describe('update transaction', () => {
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
     expect(invalidCallD).toThrow(
-      expect.objectContaining({ code: 'operations.invalidExpressionAttributePath' })
+      expect.objectContaining({ code: 'actions.invalidExpressionAttributePath' })
     )
 
     const invalidCallE = () =>
@@ -1700,7 +1700,7 @@ describe('update transaction', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('sets conditions', () => {
@@ -1722,7 +1722,7 @@ describe('update transaction', () => {
     const invalidCall = () => TestEntity.build(UpdateItemTransaction).params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.incompleteOperation' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'actions.incompleteAction' }))
   })
 
   it('transformed key/attribute (partial - 1)', () => {
diff --git a/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.unit.test.ts b/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.unit.test.ts
index d8adae04..00d824f6 100644
--- a/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.unit.test.ts
+++ b/src/v1/entity/actions/transactions/transactWriteItems/transactWriteItems.unit.test.ts
@@ -151,7 +151,7 @@ describe('generateTransactWriteCommandInput', () => {
 
     expect(invalidTransactWriteCommandInputGeneration).toThrow(DynamoDBToolboxError)
     expect(invalidTransactWriteCommandInputGeneration).toThrow(
-      expect.objectContaining({ code: 'operations.unknownOption' })
+      expect.objectContaining({ code: 'options.unknownOption' })
     )
   })
   it('should generate a transaction with the correct parameters', async () => {
diff --git a/src/v1/schema/actions/parseCondition/condition.type.test.ts b/src/v1/schema/actions/parseCondition/condition.type.test.ts
index 6b666c91..5c244194 100644
--- a/src/v1/schema/actions/parseCondition/condition.type.test.ts
+++ b/src/v1/schema/actions/parseCondition/condition.type.test.ts
@@ -1,7 +1,7 @@
 import type { A } from 'ts-toolbelt'
 
 import type { Attribute } from 'v1/schema/attributes'
-import type { Paths } from 'v1/schema/actions/paths'
+import type { Paths } from 'v1/schema/actions/parsePaths'
 
 import type {
   Condition,
diff --git a/src/v1/operations/expression/projection/parse.unit.test.ts b/src/v1/schema/actions/parsePaths/pathParser.unit.test.ts
similarity index 64%
rename from src/v1/operations/expression/projection/parse.unit.test.ts
rename to src/v1/schema/actions/parsePaths/pathParser.unit.test.ts
index e72b89fe..60f1602c 100644
--- a/src/v1/operations/expression/projection/parse.unit.test.ts
+++ b/src/v1/schema/actions/parsePaths/pathParser.unit.test.ts
@@ -1,7 +1,7 @@
 import { schema } from 'v1/schema'
 import { string, number, anyOf, map, list } from 'v1/schema/attributes'
 
-import { parseSchemaProjection } from './parse'
+import { PathParser } from './pathParser'
 
 /**
  * @debt TODO "validate the attr value is a string"
@@ -22,23 +22,27 @@ describe('parseProjection', () => {
     })
 
     it('correctly parses projection (root)', () => {
-      expect(parseSchemaProjection(schemaWithSavedAs, ['savedAs'])).toStrictEqual({
+      expect(
+        schemaWithSavedAs.build(PathParser).parse(['savedAs']).toCommandOptions()
+      ).toStrictEqual({
         ProjectionExpression: '#p_1',
         ExpressionAttributeNames: { '#p_1': '_s' }
       })
     })
 
     it('correctly parses projection (nested)', () => {
-      expect(parseSchemaProjection(schemaWithSavedAs, ['savedAs', 'nested.savedAs'])).toStrictEqual(
-        {
-          ProjectionExpression: '#p_1, #p_2.#p_3',
-          ExpressionAttributeNames: { '#p_1': '_s', '#p_2': '_n', '#p_3': '_s' }
-        }
-      )
+      expect(
+        schemaWithSavedAs.build(PathParser).parse(['savedAs', 'nested.savedAs']).toCommandOptions()
+      ).toStrictEqual({
+        ProjectionExpression: '#p_1, #p_2.#p_3',
+        ExpressionAttributeNames: { '#p_1': '_s', '#p_2': '_n', '#p_3': '_s' }
+      })
     })
 
     it('correctly parses projection (with id)', () => {
-      expect(parseSchemaProjection(schemaWithSavedAs, ['savedAs'], '1')).toStrictEqual({
+      expect(
+        schemaWithSavedAs.build(PathParser).setId('1').parse(['savedAs']).toCommandOptions()
+      ).toStrictEqual({
         ProjectionExpression: '#p1_1',
         ExpressionAttributeNames: { '#p1_1': '_s' }
       })
@@ -46,7 +50,10 @@ describe('parseProjection', () => {
 
     it('correctly parses condition (listed)', () => {
       expect(
-        parseSchemaProjection(schemaWithSavedAs, ['savedAs', 'listed[4].savedAs'])
+        schemaWithSavedAs
+          .build(PathParser)
+          .parse(['savedAs', 'listed[4].savedAs'])
+          .toCommandOptions()
       ).toStrictEqual({
         ProjectionExpression: '#p_1, #p_2[4].#p_3',
         ExpressionAttributeNames: { '#p_1': '_s', '#p_2': '_l', '#p_3': '_s' }
@@ -60,21 +67,25 @@ describe('parseProjection', () => {
     })
 
     it('correctly parses projection (root)', () => {
-      expect(parseSchemaProjection(schemaWithAnyOf, ['anyOf'])).toStrictEqual({
+      expect(schemaWithAnyOf.build(PathParser).parse(['anyOf']).toCommandOptions()).toStrictEqual({
         ProjectionExpression: '#p_1',
         ExpressionAttributeNames: { '#p_1': 'anyOf' }
       })
     })
 
     it('correctly parses projection (nested str)', () => {
-      expect(parseSchemaProjection(schemaWithAnyOf, ['anyOf.str'])).toStrictEqual({
+      expect(
+        schemaWithAnyOf.build(PathParser).parse(['anyOf.str']).toCommandOptions()
+      ).toStrictEqual({
         ProjectionExpression: '#p_1.#p_2',
         ExpressionAttributeNames: { '#p_1': 'anyOf', '#p_2': 'str' }
       })
     })
 
     it('correctly parses projection (nested num)', () => {
-      expect(parseSchemaProjection(schemaWithAnyOf, ['anyOf.num'])).toStrictEqual({
+      expect(
+        schemaWithAnyOf.build(PathParser).parse(['anyOf.num']).toCommandOptions()
+      ).toStrictEqual({
         ProjectionExpression: '#p_1.#p_2',
         ExpressionAttributeNames: { '#p_1': 'anyOf', '#p_2': '_n' }
       })
diff --git a/src/v1/schema/actions/paths/paths.ts b/src/v1/schema/actions/parsePaths/paths.ts
similarity index 100%
rename from src/v1/schema/actions/paths/paths.ts
rename to src/v1/schema/actions/parsePaths/paths.ts
diff --git a/src/v1/schema/actions/paths/paths.test.ts b/src/v1/schema/actions/parsePaths/paths.type.test.ts
similarity index 88%
rename from src/v1/schema/actions/paths/paths.test.ts
rename to src/v1/schema/actions/parsePaths/paths.type.test.ts
index d402c271..64af94c9 100644
--- a/src/v1/schema/actions/paths/paths.test.ts
+++ b/src/v1/schema/actions/parsePaths/paths.type.test.ts
@@ -1,18 +1,6 @@
 import type { A } from 'ts-toolbelt'
 
-import { schema } from 'v1/schema'
-import {
-  any,
-  string,
-  number,
-  boolean,
-  binary,
-  set,
-  list,
-  map,
-  record,
-  anyOf
-} from 'v1/schema/attributes'
+import { schema, any, string, number, boolean, binary, set, list, map, record, anyOf } from 'v1'
 
 import type { Paths } from './paths'
 
diff --git a/src/v1/table/actions/queryCommand/queryParams/queryParams.unit.test.ts b/src/v1/table/actions/queryCommand/queryParams/queryParams.unit.test.ts
index 11afbac8..7b6cc522 100644
--- a/src/v1/table/actions/queryCommand/queryParams/queryParams.unit.test.ts
+++ b/src/v1/table/actions/queryCommand/queryParams/queryParams.unit.test.ts
@@ -162,7 +162,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
-    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'operations.invalidCondition' }))
+    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'actions.invalidCondition' }))
   })
 
   it('creates query on LSI', () => {
@@ -251,7 +251,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
-    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'operations.invalidCondition' }))
+    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'actions.invalidCondition' }))
 
     const invalidCallE = () =>
       TestTable.build(QueryCommand)
@@ -268,7 +268,7 @@ describe('query', () => {
 
     expect(invalidCallE).toThrow(DynamoDBToolboxError)
     expect(invalidCallE).toThrow(
-      expect.objectContaining({ code: 'operations.invalidConsistentOption' })
+      expect.objectContaining({ code: 'options.invalidConsistentOption' })
     )
   })
 
@@ -358,7 +358,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCallD).toThrow(DynamoDBToolboxError)
-    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'operations.invalidCondition' }))
+    expect(invalidCallD).toThrow(expect.objectContaining({ code: 'actions.invalidCondition' }))
 
     const invalidCallE = () =>
       TestTable.build(QueryCommand)
@@ -375,7 +375,7 @@ describe('query', () => {
 
     expect(invalidCallE).toThrow(DynamoDBToolboxError)
     expect(invalidCallE).toThrow(
-      expect.objectContaining({ code: 'operations.invalidConsistentOption' })
+      expect.objectContaining({ code: 'options.invalidConsistentOption' })
     )
   })
 
@@ -400,9 +400,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets consistent option', () => {
@@ -444,7 +442,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
-    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'operations.invalidIndexOption' }))
+    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'options.invalidIndexOption' }))
 
     const invalidCallB = () =>
       TestTable.build(QueryCommand)
@@ -456,7 +454,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
-    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'operations.invalidIndexOption' }))
+    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'options.invalidIndexOption' }))
   })
 
   it('sets select option', () => {
@@ -479,7 +477,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('sets "ALL_PROJECTED_ATTRIBUTES" select option if an index is provided', () => {
@@ -500,7 +498,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('accepts "SPECIFIC_ATTRIBUTES" select option if a projection expression has been provided', () => {
@@ -523,7 +521,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('sets limit option', () => {
@@ -546,7 +544,7 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidLimitOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidLimitOption' }))
   })
 
   it('ignores valid maxPages option', () => {
@@ -573,18 +571,14 @@ describe('query', () => {
         .params()
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
-    expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMaxPagesOption' })
-    )
+    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'options.invalidMaxPagesOption' }))
 
     // Unable to ts-expect-error here
     const invalidCallB = () =>
       TestTable.build(QueryCommand).query({ partition: 'foo' }).options({ maxPages: 0 }).params()
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
-    expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMaxPagesOption' })
-    )
+    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'options.invalidMaxPagesOption' }))
   })
 
   it('sets reverse option', () => {
@@ -818,6 +812,6 @@ describe('query', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 })
diff --git a/src/v1/table/actions/scanCommand/scanParams/scanParams.unit.test.ts b/src/v1/table/actions/scanCommand/scanParams/scanParams.unit.test.ts
index a492ab19..a62e09e0 100644
--- a/src/v1/table/actions/scanCommand/scanParams/scanParams.unit.test.ts
+++ b/src/v1/table/actions/scanCommand/scanParams/scanParams.unit.test.ts
@@ -92,9 +92,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(
-      expect.objectContaining({ code: 'operations.invalidCapacityOption' })
-    )
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidCapacityOption' }))
   })
 
   it('sets consistent option', () => {
@@ -114,7 +112,7 @@ describe('scan', () => {
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
     expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidConsistentOption' })
+      expect.objectContaining({ code: 'options.invalidConsistentOption' })
     )
 
     const invalidCallB = () =>
@@ -128,7 +126,7 @@ describe('scan', () => {
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
     expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidConsistentOption' })
+      expect.objectContaining({ code: 'options.invalidConsistentOption' })
     )
   })
 
@@ -156,7 +154,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
-    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'operations.invalidIndexOption' }))
+    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'options.invalidIndexOption' }))
 
     const invalidCallB = () =>
       TestTable.build(ScanCommand)
@@ -167,7 +165,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
-    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'operations.invalidIndexOption' }))
+    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'options.invalidIndexOption' }))
   })
 
   it('sets select option', () => {
@@ -186,7 +184,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('sets "ALL_PROJECTED_ATTRIBUTES" select option if an index is provided', () => {
@@ -205,7 +203,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('accepts "SPECIFIC_ATTRIBUTES" select option if a projection expression has been provided', () => {
@@ -226,7 +224,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidSelectOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidSelectOption' }))
   })
 
   it('sets limit option', () => {
@@ -245,7 +243,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.invalidLimitOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.invalidLimitOption' }))
   })
 
   it('ignores valid maxPages option', () => {
@@ -266,17 +264,13 @@ describe('scan', () => {
         .params()
 
     expect(invalidCallA).toThrow(DynamoDBToolboxError)
-    expect(invalidCallA).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMaxPagesOption' })
-    )
+    expect(invalidCallA).toThrow(expect.objectContaining({ code: 'options.invalidMaxPagesOption' }))
 
     // Unable to ts-expect-error here
     const invalidCallB = () => TestTable.build(ScanCommand).options({ maxPages: 0 }).params()
 
     expect(invalidCallB).toThrow(DynamoDBToolboxError)
-    expect(invalidCallB).toThrow(
-      expect.objectContaining({ code: 'operations.invalidMaxPagesOption' })
-    )
+    expect(invalidCallB).toThrow(expect.objectContaining({ code: 'options.invalidMaxPagesOption' }))
   })
 
   it('sets segment and totalSegments options', () => {
@@ -402,7 +396,7 @@ describe('scan', () => {
         .params()
 
     expect(invalidCall).toThrow(DynamoDBToolboxError)
-    expect(invalidCall).toThrow(expect.objectContaining({ code: 'operations.unknownOption' }))
+    expect(invalidCall).toThrow(expect.objectContaining({ code: 'options.unknownOption' }))
   })
 
   it('applies entity _et filter', () => {
diff --git a/src/v1/test-tools/mocks/commandMocker.ts b/src/v1/test-tools/mocks/actionMocker.ts
similarity index 51%
rename from src/v1/test-tools/mocks/commandMocker.ts
rename to src/v1/test-tools/mocks/actionMocker.ts
index f75fb6d7..86f80d11 100644
--- a/src/v1/test-tools/mocks/commandMocker.ts
+++ b/src/v1/test-tools/mocks/actionMocker.ts
@@ -1,7 +1,7 @@
 import { isString } from 'v1/utils/validation/isString'
 
-import type { OperationName } from './types'
-import { $operationName, $mockedEntity, $mockedImplementations } from './constants'
+import type { ActionName } from './types'
+import { $actionName, $mockedEntity, $mockedImplementations } from './constants'
 
 // NOTE: Those types come from @aws-sdk
 interface Error {
@@ -30,35 +30,33 @@ interface AwsError
   $service?: string
 }
 
-export class OperationMocker<OPERATION_NAME extends OperationName, INPUT, OPTIONS, RESPONSE> {
-  [$operationName]: OPERATION_NAME;
+export class ActionMocker<ACTION_NAME extends ActionName, INPUT, OPTIONS, RESPONSE> {
+  [$actionName]: ACTION_NAME;
   [$mockedEntity]: {
     [$mockedImplementations]: Partial<
-      Record<OPERATION_NAME, (input: INPUT, options?: OPTIONS) => RESPONSE>
+      Record<ACTION_NAME, (input: INPUT, options?: OPTIONS) => RESPONSE>
     >
   }
 
   constructor(
-    operationName: OPERATION_NAME,
+    actionName: ACTION_NAME,
     mockedEntity: {
       [$mockedImplementations]: Partial<
-        Record<OPERATION_NAME, (input: INPUT, options?: OPTIONS) => RESPONSE>
+        Record<ACTION_NAME, (input: INPUT, options?: OPTIONS) => RESPONSE>
       >
     }
   ) {
-    this[$operationName] = operationName
+    this[$actionName] = actionName
     this[$mockedEntity] = mockedEntity
   }
 
-  resolve(response: RESPONSE): OperationMocker<OPERATION_NAME, INPUT, OPTIONS, RESPONSE> {
-    this[$mockedEntity][$mockedImplementations][this[$operationName]] = () => response
+  resolve(response: RESPONSE): ActionMocker<ACTION_NAME, INPUT, OPTIONS, RESPONSE> {
+    this[$mockedEntity][$mockedImplementations][this[$actionName]] = () => response
     return this
   }
 
-  reject(
-    error?: string | Error | AwsError
-  ): OperationMocker<OPERATION_NAME, INPUT, OPTIONS, RESPONSE> {
-    this[$mockedEntity][$mockedImplementations][this[$operationName]] = () => {
+  reject(error?: string | Error | AwsError): ActionMocker<ACTION_NAME, INPUT, OPTIONS, RESPONSE> {
+    this[$mockedEntity][$mockedImplementations][this[$actionName]] = () => {
       if (error === undefined || isString(error)) {
         throw new Error(error)
       } else {
@@ -71,8 +69,8 @@ export class OperationMocker<OPERATION_NAME extends OperationName, INPUT, OPTION
 
   mockImplementation(
     implementation: (key: INPUT, options?: OPTIONS) => RESPONSE
-  ): OperationMocker<OPERATION_NAME, INPUT, OPTIONS, RESPONSE> {
-    this[$mockedEntity][$mockedImplementations][this[$operationName]] = implementation
+  ): ActionMocker<ACTION_NAME, INPUT, OPTIONS, RESPONSE> {
+    this[$mockedEntity][$mockedImplementations][this[$actionName]] = implementation
 
     return this
   }
diff --git a/src/v1/test-tools/mocks/commandResults.ts b/src/v1/test-tools/mocks/commandResults.ts
index 404271b0..e6c4c976 100644
--- a/src/v1/test-tools/mocks/commandResults.ts
+++ b/src/v1/test-tools/mocks/commandResults.ts
@@ -1,16 +1,16 @@
 import { isInteger } from 'v1/utils/validation'
 
-import { $receivedCommands } from './constants'
+import { $receivedActions } from './constants'
 
 export class CommandResults<INPUT, OPTIONS> {
-  [$receivedCommands]: [input?: INPUT, options?: OPTIONS][]
+  [$receivedActions]: [input?: INPUT, options?: OPTIONS][]
 
-  constructor(receivedCommands: [input?: INPUT, options?: OPTIONS][]) {
-    this[$receivedCommands] = receivedCommands
+  constructor(receivedActions: [input?: INPUT, options?: OPTIONS][]) {
+    this[$receivedActions] = receivedActions
   }
 
   count(): number {
-    return this[$receivedCommands].length
+    return this[$receivedActions].length
   }
 
   args(at: number): [input?: INPUT, options?: OPTIONS] | undefined {
@@ -18,10 +18,10 @@ export class CommandResults<INPUT, OPTIONS> {
       throw new Error('Please provide an integer when searching for received command arguments')
     }
 
-    return this[$receivedCommands][at]
+    return this[$receivedActions][at]
   }
 
   allArgs(): [input?: INPUT, options?: OPTIONS][] {
-    return this[$receivedCommands]
+    return this[$receivedActions]
   }
 }
diff --git a/src/v1/test-tools/mocks/constants.ts b/src/v1/test-tools/mocks/constants.ts
index 89d79971..414bc577 100644
--- a/src/v1/test-tools/mocks/constants.ts
+++ b/src/v1/test-tools/mocks/constants.ts
@@ -1,5 +1,5 @@
-export const $operationName = Symbol('$operationName')
-export type $operationName = typeof $operationName
+export const $actionName = Symbol('$actionName')
+export type $actionName = typeof $actionName
 
 export const $originalEntity = Symbol('$originalEntity')
 export type $originalEntity = typeof $originalEntity
@@ -10,5 +10,5 @@ export type $mockedEntity = typeof $mockedEntity
 export const $mockedImplementations = Symbol('$mockedImplementations')
 export type $mockedImplementations = typeof $mockedImplementations
 
-export const $receivedCommands = Symbol('$receivedCommands')
-export type $receivedCommands = typeof $receivedCommands
+export const $receivedActions = Symbol('$receivedActions')
+export type $receivedActions = typeof $receivedActions
diff --git a/src/v1/test-tools/mocks/deleteItemCommand.ts b/src/v1/test-tools/mocks/deleteItemCommand.ts
index dfedfb8c..9ee292fb 100644
--- a/src/v1/test-tools/mocks/deleteItemCommand.ts
+++ b/src/v1/test-tools/mocks/deleteItemCommand.ts
@@ -13,20 +13,19 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { MockedEntity } from './entity'
 import {
-  $operationName,
+  $actionName,
   $originalEntity,
   $mockedEntity,
   $mockedImplementations,
-  $receivedCommands
+  $receivedActions
 } from './constants'
 
 export class DeleteItemCommandMock<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends DeleteItemOptions<ENTITY> = DeleteItemOptions<ENTITY>
 > implements DeleteItemCommand<ENTITY, OPTIONS> {
-  static operationType = 'entity' as const
-  static operationName = 'delete' as const
-  static [$operationName] = 'delete' as const;
+  static actionName = 'delete' as const
+  static [$actionName] = 'delete' as const;
 
   [$entity]: ENTITY;
   [$key]?: KeyInput<ENTITY>;
@@ -56,7 +55,7 @@ export class DeleteItemCommandMock<
 
   params(): DeleteCommandInput {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'DeleteItemCommand incomplete: Missing "key" property'
       })
     }
@@ -65,13 +64,13 @@ export class DeleteItemCommandMock<
   }
 
   async send(): Promise<DeleteItemResponse<ENTITY, OPTIONS>> {
-    this[$mockedEntity][$receivedCommands].delete.push([this[$key], this[$options]])
+    this[$mockedEntity][$receivedActions].delete.push([this[$key], this[$options]])
 
     const implementation = this[$mockedEntity][$mockedImplementations].delete
 
     if (implementation !== undefined) {
       if (!this[$key]) {
-        throw new DynamoDBToolboxError('operations.incompleteOperation', {
+        throw new DynamoDBToolboxError('actions.incompleteAction', {
           message: 'DeleteItemCommand incomplete: Missing "key" property'
         })
       }
diff --git a/src/v1/test-tools/mocks/entity.ts b/src/v1/test-tools/mocks/entity.ts
index 7169315e..7f08a967 100644
--- a/src/v1/test-tools/mocks/entity.ts
+++ b/src/v1/test-tools/mocks/entity.ts
@@ -23,14 +23,14 @@ import {
 } from 'v1/entity/actions/commands/updateItem'
 import type { UpdateItemCommandClass } from 'v1/entity/actions/commands/updateItem/updateItemCommand'
 
-import type { OperationClassMocker, OperationClassResults, OperationName } from './types'
+import type { ActionClassMocker, ActionClassResults, ActionName } from './types'
 import { GetItemCommandMock } from './getItemCommand'
 import { PutItemCommandMock } from './putItemCommand'
 import { DeleteItemCommandMock } from './deleteItemCommand'
 import { UpdateItemCommandMock } from './updateItemCommand'
-import { OperationMocker } from './commandMocker'
+import { ActionMocker } from './actionMocker'
 import { CommandResults } from './commandResults'
-import { $originalEntity, $mockedImplementations, $receivedCommands } from './constants'
+import { $originalEntity, $mockedImplementations, $receivedActions } from './constants'
 
 export class MockedEntity<ENTITY extends EntityV2 = EntityV2> {
   [$originalEntity]: ENTITY;
@@ -47,7 +47,7 @@ export class MockedEntity<ENTITY extends EntityV2 = EntityV2> {
       options?: UpdateItemOptions<ENTITY>
     ) => UpdateItemResponse<ENTITY>
   }>;
-  [$receivedCommands]: {
+  [$receivedActions]: {
     get: [input?: KeyInput<ENTITY>, options?: GetItemOptions<ENTITY>][]
     put: [input?: PutItemInput<ENTITY>, options?: PutItemOptions<ENTITY>][]
     delete: [input?: KeyInput<ENTITY>, options?: DeleteItemOptions<ENTITY>][]
@@ -58,7 +58,7 @@ export class MockedEntity<ENTITY extends EntityV2 = EntityV2> {
     this[$originalEntity] = entity
 
     this[$mockedImplementations] = {}
-    this[$receivedCommands] = { get: [], put: [], delete: [], update: [] }
+    this[$receivedActions] = { get: [], put: [], delete: [], update: [] }
 
     entity.build = command => {
       switch (command) {
@@ -82,31 +82,31 @@ export class MockedEntity<ENTITY extends EntityV2 = EntityV2> {
 
   reset(): void {
     this[$mockedImplementations] = {}
-    this[$receivedCommands] = { get: [], put: [], delete: [], update: [] }
+    this[$receivedActions] = { get: [], put: [], delete: [], update: [] }
   }
 
   on<
-    OPERATION_CLASS extends
+    ACTION_CLASS extends
       | GetItemCommandClass
       | PutItemCommandClass
       | DeleteItemCommandClass
       | UpdateItemCommandClass
-  >(operation: OPERATION_CLASS): OperationClassMocker<ENTITY, OPERATION_CLASS> {
-    return new OperationMocker<OperationName, any, any, any>(
-      operation.operationName,
+  >(actionClass: ACTION_CLASS): ActionClassMocker<ENTITY, ACTION_CLASS> {
+    return new ActionMocker<ActionName, any, any, any>(
+      actionClass.actionName,
       this
-    ) as OperationClassMocker<ENTITY, OPERATION_CLASS>
+    ) as ActionClassMocker<ENTITY, ACTION_CLASS>
   }
 
   received<
-    OPERATION_CLASS extends
+    ACTION_CLASS extends
       | GetItemCommandClass
       | PutItemCommandClass
       | DeleteItemCommandClass
       | UpdateItemCommandClass
-  >(operation: OPERATION_CLASS): OperationClassResults<ENTITY, OPERATION_CLASS> {
+  >(actionClass: ACTION_CLASS): ActionClassResults<ENTITY, ACTION_CLASS> {
     return new CommandResults<unknown, unknown>(
-      this[$receivedCommands][operation.operationName]
-    ) as OperationClassResults<ENTITY, OPERATION_CLASS>
+      this[$receivedActions][actionClass.actionName]
+    ) as ActionClassResults<ENTITY, ACTION_CLASS>
   }
 }
diff --git a/src/v1/test-tools/mocks/getItemCommand.ts b/src/v1/test-tools/mocks/getItemCommand.ts
index 14490ff3..ce28f81c 100644
--- a/src/v1/test-tools/mocks/getItemCommand.ts
+++ b/src/v1/test-tools/mocks/getItemCommand.ts
@@ -9,20 +9,19 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { MockedEntity } from './entity'
 import {
-  $operationName,
+  $actionName,
   $originalEntity,
   $mockedEntity,
   $mockedImplementations,
-  $receivedCommands
+  $receivedActions
 } from './constants'
 
 export class GetItemCommandMock<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends GetItemOptions<ENTITY> = GetItemOptions<ENTITY>
 > implements GetItemCommand<ENTITY, OPTIONS> {
-  static operationType = 'entity' as const
-  static operationName = 'get' as const
-  static [$operationName] = 'get' as const;
+  static actionName = 'get' as const
+  static [$actionName] = 'get' as const;
 
   [$entity]: ENTITY;
   [$key]?: KeyInput<ENTITY>;
@@ -52,7 +51,7 @@ export class GetItemCommandMock<
 
   params(): GetCommandInput {
     if (!this[$key]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'GetItemCommand incomplete: Missing "key" property'
       })
     }
@@ -61,13 +60,13 @@ export class GetItemCommandMock<
   }
 
   async send(): Promise<GetItemResponse<ENTITY, OPTIONS>> {
-    this[$mockedEntity][$receivedCommands].get.push([this[$key], this[$options]])
+    this[$mockedEntity][$receivedActions].get.push([this[$key], this[$options]])
 
     const implementation = this[$mockedEntity][$mockedImplementations].get
 
     if (implementation !== undefined) {
       if (!this[$key]) {
-        throw new DynamoDBToolboxError('operations.incompleteOperation', {
+        throw new DynamoDBToolboxError('actions.incompleteAction', {
           message: 'GetItemCommand incomplete: Missing "key" property'
         })
       }
diff --git a/src/v1/test-tools/mocks/putItemCommand.ts b/src/v1/test-tools/mocks/putItemCommand.ts
index 1666d195..192cc462 100644
--- a/src/v1/test-tools/mocks/putItemCommand.ts
+++ b/src/v1/test-tools/mocks/putItemCommand.ts
@@ -13,20 +13,19 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { MockedEntity } from './entity'
 import {
-  $operationName,
+  $actionName,
   $originalEntity,
   $mockedEntity,
   $mockedImplementations,
-  $receivedCommands
+  $receivedActions
 } from './constants'
 
 export class PutItemCommandMock<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends PutItemOptions<ENTITY> = PutItemOptions<ENTITY>
 > implements PutItemCommand<ENTITY, OPTIONS> {
-  static operationType = 'entity' as const
-  static operationName = 'put' as const
-  static [$operationName] = 'put' as const;
+  static actionName = 'put' as const
+  static [$actionName] = 'put' as const;
 
   [$entity]: ENTITY;
   [$item]?: PutItemInput<ENTITY>;
@@ -56,7 +55,7 @@ export class PutItemCommandMock<
 
   params(): PutCommandInput {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'PutItemCommand incomplete: Missing "item" property'
       })
     }
@@ -65,13 +64,13 @@ export class PutItemCommandMock<
   }
 
   async send(): Promise<PutItemResponse<ENTITY, OPTIONS>> {
-    this[$mockedEntity][$receivedCommands].put.push([this[$item], this[$options]])
+    this[$mockedEntity][$receivedActions].put.push([this[$item], this[$options]])
 
     const implementation = this[$mockedEntity][$mockedImplementations].put
 
     if (implementation !== undefined) {
       if (!this[$item]) {
-        throw new DynamoDBToolboxError('operations.incompleteOperation', {
+        throw new DynamoDBToolboxError('actions.incompleteAction', {
           message: 'PutItemCommand incomplete: Missing "item" property'
         })
       }
diff --git a/src/v1/test-tools/mocks/types.ts b/src/v1/test-tools/mocks/types.ts
index f4f99760..d3d38042 100644
--- a/src/v1/test-tools/mocks/types.ts
+++ b/src/v1/test-tools/mocks/types.ts
@@ -21,9 +21,9 @@ import type { GetItemCommandMock } from './getItemCommand'
 import type { PutItemCommandMock } from './putItemCommand'
 import type { DeleteItemCommandMock } from './deleteItemCommand'
 import type { UpdateItemCommandMock } from './updateItemCommand'
-import type { $operationName } from './constants'
+import type { $actionName } from './constants'
 import type { CommandResults } from './commandResults'
-import type { OperationMocker } from './commandMocker'
+import type { ActionMocker } from './actionMocker'
 
 type ClassStaticProperties<CLASSES> = CLASSES extends infer CLASS
   ? {
@@ -35,61 +35,56 @@ type ClassStaticProperties<CLASSES> = CLASSES extends infer CLASS
     }
   : never
 
-type OperationMock =
+type ActionMock =
   | typeof GetItemCommandMock
   | typeof PutItemCommandMock
   | typeof DeleteItemCommandMock
   | typeof UpdateItemCommandMock
 
-export type OperationName = ClassStaticProperties<OperationMock>[$operationName]
+export type ActionName = ClassStaticProperties<ActionMock>[$actionName]
 
-export type OperationClassResults<
+export type ActionClassResults<
   ENTITY extends EntityV2,
-  OPERATION_CLASS extends
+  ACTION_CLASS extends
     | GetItemCommandClass
     | PutItemCommandClass
     | DeleteItemCommandClass
     | UpdateItemCommandClass
-> = OPERATION_CLASS extends GetItemCommandClass
+> = ACTION_CLASS extends GetItemCommandClass
   ? CommandResults<KeyInput<ENTITY>, GetItemOptions<ENTITY>>
-  : OPERATION_CLASS extends PutItemCommandClass
+  : ACTION_CLASS extends PutItemCommandClass
   ? CommandResults<PutItemInput<ENTITY>, PutItemOptions<ENTITY>>
-  : OPERATION_CLASS extends DeleteItemCommandClass
+  : ACTION_CLASS extends DeleteItemCommandClass
   ? CommandResults<KeyInput<ENTITY>, DeleteItemOptions<ENTITY>>
-  : OPERATION_CLASS extends UpdateItemCommandClass
+  : ACTION_CLASS extends UpdateItemCommandClass
   ? CommandResults<UpdateItemInput<ENTITY>, UpdateItemOptions<ENTITY>>
   : never
 
-export type OperationClassMocker<
+export type ActionClassMocker<
   ENTITY extends EntityV2,
-  OPERATION_CLASS extends
+  ACTION_CLASS extends
     | GetItemCommandClass
     | PutItemCommandClass
     | DeleteItemCommandClass
     | UpdateItemCommandClass
-> = OPERATION_CLASS extends GetItemCommandClass
-  ? OperationMocker<
-      'get',
-      KeyInput<ENTITY>,
-      GetItemOptions<ENTITY>,
-      Partial<GetItemResponse<ENTITY>>
-    >
-  : OPERATION_CLASS extends PutItemCommandClass
-  ? OperationMocker<
+> = ACTION_CLASS extends GetItemCommandClass
+  ? ActionMocker<'get', KeyInput<ENTITY>, GetItemOptions<ENTITY>, Partial<GetItemResponse<ENTITY>>>
+  : ACTION_CLASS extends PutItemCommandClass
+  ? ActionMocker<
       'put',
       PutItemInput<ENTITY>,
       PutItemOptions<ENTITY>,
       Partial<PutItemResponse<ENTITY>>
     >
-  : OPERATION_CLASS extends DeleteItemCommandClass
-  ? OperationMocker<
+  : ACTION_CLASS extends DeleteItemCommandClass
+  ? ActionMocker<
       'delete',
       KeyInput<ENTITY>,
       DeleteItemOptions<ENTITY>,
       Partial<DeleteItemResponse<ENTITY>>
     >
-  : OPERATION_CLASS extends UpdateItemCommandClass
-  ? OperationMocker<
+  : ACTION_CLASS extends UpdateItemCommandClass
+  ? ActionMocker<
       'update',
       UpdateItemInput<ENTITY>,
       UpdateItemOptions<ENTITY>,
diff --git a/src/v1/test-tools/mocks/updateItemCommand.ts b/src/v1/test-tools/mocks/updateItemCommand.ts
index c3070629..be62b8ab 100644
--- a/src/v1/test-tools/mocks/updateItemCommand.ts
+++ b/src/v1/test-tools/mocks/updateItemCommand.ts
@@ -13,20 +13,19 @@ import { DynamoDBToolboxError } from 'v1/errors'
 
 import type { MockedEntity } from './entity'
 import {
-  $operationName,
+  $actionName,
   $originalEntity,
   $mockedEntity,
   $mockedImplementations,
-  $receivedCommands
+  $receivedActions
 } from './constants'
 
 export class UpdateItemCommandMock<
   ENTITY extends EntityV2 = EntityV2,
   OPTIONS extends UpdateItemOptions<ENTITY> = UpdateItemOptions<ENTITY>
 > implements UpdateItemCommand<ENTITY, OPTIONS> {
-  static operationType = 'entity' as const
-  static operationName = 'update' as const
-  static [$operationName] = 'update' as const;
+  static actionName = 'update' as const
+  static [$actionName] = 'update' as const;
 
   [$entity]: ENTITY;
   [$item]?: UpdateItemInput<ENTITY>
@@ -55,7 +54,7 @@ export class UpdateItemCommandMock<
 
   params = (): UpdateCommandInput => {
     if (!this[$item]) {
-      throw new DynamoDBToolboxError('operations.incompleteOperation', {
+      throw new DynamoDBToolboxError('actions.incompleteAction', {
         message: 'UpdateItemCommand incomplete: Missing "item" property'
       })
     }
@@ -64,13 +63,13 @@ export class UpdateItemCommandMock<
   }
 
   send = async (): Promise<UpdateItemResponse<ENTITY, OPTIONS>> => {
-    this[$mockedEntity][$receivedCommands].update.push([this[$item], this[$options]])
+    this[$mockedEntity][$receivedActions].update.push([this[$item], this[$options]])
 
     const implementation = this[$mockedEntity][$mockedImplementations].update
 
     if (implementation !== undefined) {
       if (!this[$item]) {
-        throw new DynamoDBToolboxError('operations.incompleteOperation', {
+        throw new DynamoDBToolboxError('actions.incompleteAction', {
           message: 'UpdateItemCommand incomplete: Missing "item" property'
         })
       }