@jaypie/dynamodb 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/entities.d.ts +4 -3
- package/dist/cjs/index.cjs +24 -7
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/keyBuilders.d.ts +1 -1
- package/dist/cjs/mcp/index.cjs +22 -12
- package/dist/cjs/mcp/index.cjs.map +1 -1
- package/dist/esm/entities.d.ts +4 -3
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +24 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/keyBuilders.d.ts +1 -1
- package/dist/esm/mcp/index.js +22 -12
- package/dist/esm/mcp/index.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/client.ts","../../../src/keyBuilders.ts","../../../src/entities.ts","../../../src/queries.ts","../../../src/query.ts","../../../src/seedExport.ts"],"sourcesContent":["import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport { ConfigurationError } from \"@jaypie/errors\";\n\nimport type { DynamoClientConfig } from \"./types.js\";\n\n// Environment variable names\nconst ENV_AWS_REGION = \"AWS_REGION\";\nconst ENV_DYNAMODB_TABLE_NAME = \"DYNAMODB_TABLE_NAME\";\n\n// Defaults\nconst DEFAULT_REGION = \"us-east-1\";\nconst LOCAL_CREDENTIALS = {\n accessKeyId: \"local\",\n secretAccessKey: \"local\",\n};\n\n// Module-level state\nlet docClient: DynamoDBDocumentClient | null = null;\nlet tableName: string | null = null;\n\n/**\n * Check if endpoint indicates local development mode\n */\nfunction isLocalEndpoint(endpoint?: string): boolean {\n if (!endpoint) return false;\n return endpoint.includes(\"127.0.0.1\") || endpoint.includes(\"localhost\");\n}\n\n/**\n * Initialize the DynamoDB client\n * Must be called once at application startup before using query functions\n *\n * @param config - Client configuration\n */\nexport function initClient(config: DynamoClientConfig = {}): void {\n const { endpoint } = config;\n const region = config.region ?? process.env[ENV_AWS_REGION] ?? DEFAULT_REGION;\n\n // Auto-detect local mode and use dummy credentials\n const credentials =\n config.credentials ??\n (isLocalEndpoint(endpoint) ? LOCAL_CREDENTIALS : undefined);\n\n const dynamoClient = new DynamoDBClient({\n ...(credentials && { credentials }),\n ...(endpoint && { endpoint }),\n region,\n });\n\n docClient = DynamoDBDocumentClient.from(dynamoClient, {\n marshallOptions: {\n removeUndefinedValues: true,\n },\n });\n\n tableName = config.tableName ?? process.env[ENV_DYNAMODB_TABLE_NAME] ?? null;\n}\n\n/**\n * Get the initialized DynamoDB Document Client\n * @throws ConfigurationError if client has not been initialized\n */\nexport function getDocClient(): DynamoDBDocumentClient {\n if (!docClient) {\n throw new ConfigurationError(\n \"DynamoDB client not initialized. Call initClient() first.\",\n );\n }\n return docClient;\n}\n\n/**\n * Get the configured table name\n * @throws ConfigurationError if client has not been initialized\n */\nexport function getTableName(): string {\n if (!tableName) {\n throw new ConfigurationError(\n \"DynamoDB client not initialized. Call initClient() first.\",\n );\n }\n return tableName;\n}\n\n/**\n * Check if the client has been initialized\n */\nexport function isInitialized(): boolean {\n return docClient !== null && tableName !== null;\n}\n\n/**\n * Reset the client state (primarily for testing)\n */\nexport function resetClient(): void {\n docClient = null;\n tableName = null;\n}\n","import {\n buildCompositeKey as fabricBuildCompositeKey,\n calculateScope as fabricCalculateScope,\n getModelIndexes,\n type IndexableModel,\n populateIndexKeys as fabricPopulateIndexKeys,\n} from \"@jaypie/fabric\";\n\nimport { APEX } from \"./constants.js\";\nimport type { ParentReference, StorableEntity } from \"./types.js\";\n\n// =============================================================================\n// Key Builders\n// =============================================================================\n\n/**\n * Build a composite key from entity fields\n *\n * @param entity - Entity with fields to extract\n * @param fields - Field names to combine with SEPARATOR\n * @param suffix - Optional suffix to append (e.g., \"#deleted\")\n * @returns Composite key string\n */\nexport function buildCompositeKey(\n entity: IndexableModel,\n fields: string[],\n suffix?: string,\n): string {\n return fabricBuildCompositeKey(entity, fields, suffix);\n}\n\n/**\n * Calculate the scope from a parent reference\n * @param parent - Optional parent entity reference\n * @returns APEX (\"@\") if no parent, otherwise \"{parent.model}#{parent.id}\"\n */\nexport function calculateScope(parent?: ParentReference): string {\n if (!parent) {\n return APEX;\n }\n return fabricCalculateScope(parent);\n}\n\n/**\n * Auto-populate GSI index keys on an entity and advance its write timestamps.\n *\n * - Bumps `updatedAt` to now on every call.\n * - Backfills `createdAt` to the same now if not already set.\n * - Populates GSI attributes (pk composite and sk composite when applicable)\n * using the indexes registered for the entity's model.\n *\n * Callers (putEntity, updateEntity, deleteEntity, archiveEntity,\n * transactWriteEntities) go through this one function so `updatedAt` is\n * always fresh and never forgotten.\n *\n * @param entity - The entity to index\n * @param suffix - Optional suffix override (defaults to archived/deleted state)\n * @returns A new entity with timestamps bumped and index keys populated\n */\nexport function indexEntity<T extends StorableEntity>(\n entity: T,\n suffix?: string,\n): T {\n const now = new Date().toISOString();\n const bumped = {\n ...entity,\n createdAt: entity.createdAt ?? now,\n updatedAt: now,\n } as T;\n\n const indexes = getModelIndexes(entity.model);\n return fabricPopulateIndexKeys(\n bumped as unknown as IndexableModel,\n indexes,\n suffix,\n ) as unknown as T;\n}\n","import {\n DeleteCommand,\n GetCommand,\n PutCommand,\n TransactWriteCommand,\n} from \"@aws-sdk/lib-dynamodb\";\nimport { fabricService } from \"@jaypie/fabric\";\n\nimport { getDocClient, getTableName } from \"./client.js\";\nimport { ARCHIVED_SUFFIX, DELETED_SUFFIX } from \"./constants.js\";\nimport { indexEntity } from \"./keyBuilders.js\";\nimport type { StorableEntity } from \"./types.js\";\n\n/**\n * Calculate suffix based on entity's archived/deleted state\n */\nfunction calculateEntitySuffix(entity: {\n archivedAt?: string;\n deletedAt?: string;\n}): string {\n const hasArchived = Boolean(entity.archivedAt);\n const hasDeleted = Boolean(entity.deletedAt);\n\n if (hasArchived && hasDeleted) {\n return ARCHIVED_SUFFIX + DELETED_SUFFIX;\n }\n if (hasArchived) {\n return ARCHIVED_SUFFIX;\n }\n if (hasDeleted) {\n return DELETED_SUFFIX;\n }\n return \"\";\n}\n\n/**\n * Get a single entity by primary key (id)\n */\nexport const getEntity = fabricService({\n alias: \"getEntity\",\n description: \"Get a single entity by id\",\n input: {\n id: { type: String, description: \"Entity id (partition key)\" },\n },\n service: async ({ id }): Promise<StorableEntity | null> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new GetCommand({\n Key: { id },\n TableName: tableName,\n });\n\n const response = await docClient.send(command);\n return (response.Item as StorableEntity) ?? null;\n },\n});\n\n/**\n * Put (create or replace) an entity.\n * `indexEntity` auto-bumps `updatedAt` and backfills `createdAt`.\n */\nexport async function putEntity({\n entity,\n}: {\n entity: StorableEntity;\n}): Promise<StorableEntity> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const indexedEntity = indexEntity(entity);\n\n const command = new PutCommand({\n Item: indexedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return indexedEntity;\n}\n\n/**\n * Update an existing entity.\n * `indexEntity` auto-bumps `updatedAt` — callers never set it manually.\n */\nexport async function updateEntity({\n entity,\n}: {\n entity: StorableEntity;\n}): Promise<StorableEntity> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const updatedEntity = indexEntity(entity);\n\n const command = new PutCommand({\n Item: updatedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return updatedEntity;\n}\n\n/**\n * Soft delete an entity by setting deletedAt timestamp\n * Re-indexes with appropriate suffix based on archived/deleted state\n */\nexport const deleteEntity = fabricService({\n alias: \"deleteEntity\",\n description: \"Soft delete an entity (sets deletedAt timestamp)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const existing = await getEntity({ id });\n if (!existing) {\n return false;\n }\n\n const now = new Date().toISOString();\n\n // indexEntity will bump updatedAt again; set deletedAt here.\n const updatedEntity = {\n ...existing,\n deletedAt: now,\n };\n\n const suffix = calculateEntitySuffix(updatedEntity);\n const deletedEntity = indexEntity(updatedEntity, suffix);\n\n const command = new PutCommand({\n Item: deletedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Archive an entity by setting archivedAt timestamp\n * Re-indexes with appropriate suffix based on archived/deleted state\n */\nexport const archiveEntity = fabricService({\n alias: \"archiveEntity\",\n description: \"Archive an entity (sets archivedAt timestamp)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const existing = await getEntity({ id });\n if (!existing) {\n return false;\n }\n\n const now = new Date().toISOString();\n\n const updatedEntity = {\n ...existing,\n archivedAt: now,\n };\n\n const suffix = calculateEntitySuffix(updatedEntity);\n const archivedEntity = indexEntity(updatedEntity, suffix);\n\n const command = new PutCommand({\n Item: archivedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Hard delete an entity (permanently removes from table)\n * Use with caution - prefer deleteEntity for soft delete\n */\nexport const destroyEntity = fabricService({\n alias: \"destroyEntity\",\n description: \"Hard delete an entity (permanently removes from table)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new DeleteCommand({\n Key: { id },\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Write multiple entities atomically using DynamoDB transactions.\n * Each entity is auto-indexed via indexEntity before writing.\n * All entities are written to the same table in a single transaction.\n */\nexport async function transactWriteEntities({\n entities,\n}: {\n entities: StorableEntity[];\n}): Promise<void> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new TransactWriteCommand({\n TransactItems: entities.map((entity) => ({\n Put: {\n Item: indexEntity(entity),\n TableName: tableName,\n },\n })),\n });\n\n await docClient.send(command);\n}\n","import { QueryCommand } from \"@aws-sdk/lib-dynamodb\";\nimport { ConfigurationError } from \"@jaypie/errors\";\nimport {\n fabricService,\n getGsiAttributeNames,\n getModelIndexes,\n type IndexDefinition,\n SEPARATOR,\n} from \"@jaypie/fabric\";\n\nimport { getDocClient, getTableName } from \"./client.js\";\nimport { ARCHIVED_SUFFIX, DELETED_SUFFIX } from \"./constants.js\";\nimport { buildCompositeKey } from \"./keyBuilders.js\";\nimport type {\n QueryByAliasParams,\n QueryByCategoryParams,\n QueryByScopeParams,\n QueryByTypeParams,\n QueryByXidParams,\n QueryResult,\n StorableEntity,\n} from \"./types.js\";\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Calculate the suffix for the GSI partition key based on archived/deleted\n * flags. Suffix stays on pk so deleted/archived entities are queried as their\n * own partition (active queries skip them naturally).\n */\nfunction calculateSuffix({\n archived,\n deleted,\n}: {\n archived?: boolean;\n deleted?: boolean;\n}): string {\n if (archived && deleted) {\n return ARCHIVED_SUFFIX + DELETED_SUFFIX;\n }\n if (archived) {\n return ARCHIVED_SUFFIX;\n }\n if (deleted) {\n return DELETED_SUFFIX;\n }\n return \"\";\n}\n\n/**\n * Find the registered index for a model that matches a given partition-key\n * shape. The matching index is the first one whose pk equals the expected\n * fields. Throws ConfigurationError if no match is found.\n */\nfunction requireIndex(model: string, pkFields: string[]): IndexDefinition {\n const indexes = getModelIndexes(model);\n const match = indexes.find(\n (index) =>\n index.pk.length === pkFields.length &&\n index.pk.every((field, i) => field === pkFields[i]),\n );\n if (!match) {\n throw new ConfigurationError(\n `Model \"${model}\" has no index with pk=[${pkFields.join(\", \")}]. ` +\n `Register one with fabricIndex(${\n pkFields.length > 1 ? `\"${pkFields[1]}\"` : \"\"\n }).`,\n );\n }\n return match;\n}\n\n/**\n * Execute a GSI query.\n *\n * - pk: exact match on the index partition key\n * - skPrefix: optional begins_with on the index sort key (used when the index\n * has a composite sk like [scope, updatedAt])\n */\nasync function executeQuery<T extends StorableEntity>(\n index: IndexDefinition,\n pkValue: string,\n options: {\n ascending?: boolean;\n limit?: number;\n skPrefix?: string;\n startKey?: Record<string, unknown>;\n } = {},\n): Promise<QueryResult<T>> {\n const { ascending = false, limit, skPrefix, startKey } = options;\n const attrs = getGsiAttributeNames(index);\n const indexName = attrs.pk;\n\n const expressionAttributeNames: Record<string, string> = {\n \"#pk\": indexName,\n };\n const expressionAttributeValues: Record<string, unknown> = {\n \":pkValue\": pkValue,\n };\n let keyConditionExpression = \"#pk = :pkValue\";\n\n if (skPrefix !== undefined && attrs.sk) {\n expressionAttributeNames[\"#sk\"] = attrs.sk;\n expressionAttributeValues[\":skPrefix\"] = skPrefix;\n keyConditionExpression += \" AND begins_with(#sk, :skPrefix)\";\n }\n\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new QueryCommand({\n ExclusiveStartKey: startKey as Record<string, unknown> | undefined,\n ExpressionAttributeNames: expressionAttributeNames,\n ExpressionAttributeValues: expressionAttributeValues,\n IndexName: indexName,\n KeyConditionExpression: keyConditionExpression,\n ...(limit && { Limit: limit }),\n ScanIndexForward: ascending,\n TableName: tableName,\n });\n\n const response = await docClient.send(command);\n\n return {\n items: (response.Items ?? []) as T[],\n lastEvaluatedKey: response.LastEvaluatedKey,\n };\n}\n\nfunction scopePrefix(scope: string | undefined): string | undefined {\n return scope === undefined ? undefined : `${scope}${SEPARATOR}`;\n}\n\n// =============================================================================\n// Query Functions\n// =============================================================================\n\n/**\n * List entities of a model, optionally narrowed to a scope.\n * Requires the model to register `fabricIndex()` (pk=[model]).\n */\nexport async function queryByScope({\n archived = false,\n ascending = false,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n}: QueryByScopeParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey({ model }, [\"model\"], suffix);\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query a single entity by human-friendly alias.\n * Requires the model to register `fabricIndex(\"alias\")`.\n */\nexport const queryByAlias = fabricService({\n alias: \"queryByAlias\",\n description: \"Query a single entity by human-friendly alias\",\n input: {\n alias: { type: String, description: \"Human-friendly alias\" },\n archived: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query archived entities instead of active ones\",\n },\n deleted: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query deleted entities instead of active ones\",\n },\n model: { type: String, description: \"Entity model name\" },\n scope: {\n type: String,\n required: false,\n description: \"Optional scope narrower (begins_with on sk)\",\n },\n },\n service: async ({\n alias,\n archived,\n deleted,\n model,\n scope,\n }): Promise<StorableEntity | null> => {\n const aliasStr = alias as string;\n const archivedBool = archived as boolean | undefined;\n const deletedBool = deleted as boolean | undefined;\n const modelStr = model as string;\n const scopeStr = scope as string | undefined;\n\n const index = requireIndex(modelStr, [\"model\", \"alias\"]);\n const suffix = calculateSuffix({\n archived: archivedBool,\n deleted: deletedBool,\n });\n const pkValue = buildCompositeKey(\n { model: modelStr, alias: aliasStr },\n [\"model\", \"alias\"],\n suffix,\n );\n const result = await executeQuery<StorableEntity>(index, pkValue, {\n limit: 1,\n skPrefix: scopePrefix(scopeStr),\n });\n return result.items[0] ?? null;\n },\n});\n\n/**\n * Query entities by category classification.\n * Requires the model to register `fabricIndex(\"category\")`.\n */\nexport async function queryByCategory({\n archived = false,\n ascending = false,\n category,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n}: QueryByCategoryParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\", \"category\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n { model, category },\n [\"model\", \"category\"],\n suffix,\n );\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query entities by type classification.\n * Requires the model to register `fabricIndex(\"type\")`.\n */\nexport async function queryByType({\n archived = false,\n ascending = false,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n type,\n}: QueryByTypeParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\", \"type\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n { model, type },\n [\"model\", \"type\"],\n suffix,\n );\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query a single entity by external ID.\n * Requires the model to register `fabricIndex(\"xid\")`.\n */\nexport const queryByXid = fabricService({\n alias: \"queryByXid\",\n description: \"Query a single entity by external ID\",\n input: {\n archived: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query archived entities instead of active ones\",\n },\n deleted: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query deleted entities instead of active ones\",\n },\n model: { type: String, description: \"Entity model name\" },\n scope: {\n type: String,\n required: false,\n description: \"Optional scope narrower (begins_with on sk)\",\n },\n xid: { type: String, description: \"External ID\" },\n },\n service: async ({\n archived,\n deleted,\n model,\n scope,\n xid,\n }): Promise<StorableEntity | null> => {\n const archivedBool = archived as boolean | undefined;\n const deletedBool = deleted as boolean | undefined;\n const modelStr = model as string;\n const scopeStr = scope as string | undefined;\n const xidStr = xid as string;\n\n const index = requireIndex(modelStr, [\"model\", \"xid\"]);\n const suffix = calculateSuffix({\n archived: archivedBool,\n deleted: deletedBool,\n });\n const pkValue = buildCompositeKey(\n { model: modelStr, xid: xidStr },\n [\"model\", \"xid\"],\n suffix,\n );\n const result = await executeQuery<StorableEntity>(index, pkValue, {\n limit: 1,\n skPrefix: scopePrefix(scopeStr),\n });\n return result.items[0] ?? null;\n },\n});\n\n// Internal exports for the unified query() layer\nexport { executeQuery, requireIndex, calculateSuffix, scopePrefix };\n","/**\n * Unified Query Function with Auto-Detect Index Selection\n *\n * The query() function automatically selects the best index based on\n * the filter fields provided. This simplifies query construction by\n * removing the need to know which specific GSI to use.\n */\n\nimport { ConfigurationError } from \"@jaypie/errors\";\nimport { getModelIndexes, type IndexDefinition } from \"@jaypie/fabric\";\n\nimport { buildCompositeKey } from \"./keyBuilders.js\";\nimport {\n calculateSuffix,\n executeQuery,\n scopePrefix,\n} from \"./queries.js\";\nimport type { QueryResult, StorableEntity } from \"./types.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Query parameters for the unified query function\n */\nexport interface QueryParams<T = StorableEntity> {\n /** Whether to query archived entities instead of active ones */\n archived?: boolean;\n /** Whether to sort ascending (oldest first). Default: false */\n ascending?: boolean;\n /** Whether to query deleted entities instead of active ones */\n deleted?: boolean;\n /**\n * Filter object with field values to match. Used for index auto-detection\n * — the picker scores indexes by how many pk fields (after `model`) are\n * present in this filter.\n */\n filter?: Partial<T>;\n /** Maximum number of items to return */\n limit?: number;\n /** Model name (required) */\n model: string;\n /**\n * Optional scope narrower. Applied as `begins_with` on the GSI sort key\n * (composite scope + updatedAt). Omit to list across all scopes.\n */\n scope?: string;\n /** Pagination cursor from previous query */\n startKey?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Index Selection\n// =============================================================================\n\n/**\n * Select the best index for the given filter.\n *\n * Every model-level index has `model` as its first pk field. The picker\n * prefers the most specific index whose remaining pk fields are all\n * satisfied by the filter.\n */\nfunction selectBestIndex(\n indexes: IndexDefinition[],\n filter: Record<string, unknown>,\n): IndexDefinition {\n // Candidates: indexes whose pk starts with \"model\" and whose remaining\n // fields are all present in the filter.\n const candidates = indexes.filter((index) => {\n if (index.pk.length === 0 || index.pk[0] !== \"model\") return false;\n for (let i = 1; i < index.pk.length; i++) {\n if (filter[index.pk[i] as string] === undefined) return false;\n }\n return true;\n });\n\n if (candidates.length === 0) {\n const available = indexes\n .map((i) => `[${i.pk.join(\", \")}]`)\n .join(\", \");\n const provided = Object.keys(filter).join(\", \") || \"(none)\";\n throw new ConfigurationError(\n `No index matches filter for model. ` +\n `Filter fields: ${provided}. Available indexes: ${available}`,\n );\n }\n\n // Prefer the most specific index (longest pk).\n candidates.sort((a, b) => b.pk.length - a.pk.length);\n return candidates[0];\n}\n\n// =============================================================================\n// Main Query Function\n// =============================================================================\n\n/**\n * Query entities with automatic index selection.\n *\n * @example\n * // Uses indexModel (pk: [\"model\"]), optionally narrowed by scope\n * const records = await query({ model: \"record\", scope: \"@\" });\n *\n * @example\n * // Uses indexModelAlias (pk: [\"model\", \"alias\"])\n * const byAlias = await query({\n * model: \"record\",\n * scope: \"@\",\n * filter: { alias: \"my-record\" },\n * });\n *\n * @example\n * // Cross-scope listing (no scope narrower)\n * const all = await query({ model: \"record\" });\n */\nexport async function query<T extends StorableEntity = StorableEntity>(\n params: QueryParams<T>,\n): Promise<QueryResult<T>> {\n const {\n archived = false,\n ascending = false,\n deleted = false,\n filter,\n limit,\n model,\n scope,\n startKey,\n } = params;\n\n const indexes = getModelIndexes(model);\n const filterFields: Record<string, unknown> = {\n model,\n ...(filter as Record<string, unknown> | undefined),\n };\n const selectedIndex = selectBestIndex(indexes, filterFields);\n\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n filterFields as Record<string, unknown> & { model: string },\n selectedIndex.pk as string[],\n suffix,\n );\n\n return executeQuery<T>(selectedIndex, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n// Re-export for convenience\nexport { getModelIndexes };\n","import { putEntity } from \"./entities.js\";\nimport { queryByAlias, queryByScope } from \"./queries.js\";\nimport type { StorableEntity } from \"./types.js\";\n\n/**\n * Result of a seed operation\n */\nexport interface SeedResult {\n /** Aliases of entities that were created */\n created: string[];\n /** Error details for failed seed operations */\n errors: Array<{ alias: string; error: string }>;\n /** Aliases of entities that were skipped (already exist) */\n skipped: string[];\n}\n\n/**\n * Options for seed operations\n */\nexport interface SeedOptions {\n /** Preview without writing (default: false) */\n dryRun?: boolean;\n /** Overwrite existing entities (default: false) */\n replace?: boolean;\n}\n\n/**\n * Result of an export operation\n */\nexport interface ExportResult<T extends StorableEntity = StorableEntity> {\n /** Number of entities exported */\n count: number;\n /** Exported entities */\n entities: T[];\n}\n\n/**\n * Seed a single entity if it doesn't already exist\n *\n * @param entity - Partial entity with at least alias, model, and scope\n * @returns true if entity was created, false if it already exists\n */\nexport async function seedEntityIfNotExists<T extends Partial<StorableEntity>>(\n entity: T,\n): Promise<boolean> {\n if (!entity.alias || !entity.model || !entity.scope) {\n throw new Error(\n \"Entity must have alias, model, and scope to check existence\",\n );\n }\n\n // Check if entity already exists\n const existing = await queryByAlias({\n alias: entity.alias,\n model: entity.model,\n scope: entity.scope,\n });\n\n if (existing) {\n return false;\n }\n\n // Generate required fields if missing; indexEntity manages timestamps\n const completeEntity: StorableEntity = {\n id: entity.id ?? crypto.randomUUID(),\n model: entity.model,\n name: entity.name ?? entity.alias,\n scope: entity.scope,\n ...entity,\n } as StorableEntity;\n\n await putEntity({ entity: completeEntity });\n return true;\n}\n\n/**\n * Seed multiple entities (idempotent)\n *\n * - Checks existence by alias (via queryByAlias) before creating\n * - Auto-generates id (UUID), createdAt, updatedAt if missing\n * - Skip existing unless replace: true\n * - Returns counts of created/skipped/errors\n *\n * @param entities - Array of partial entities to seed\n * @param options - Seed options\n * @returns Result with created, skipped, and errors arrays\n */\nexport async function seedEntities<T extends Partial<StorableEntity>>(\n entities: T[],\n options: SeedOptions = {},\n): Promise<SeedResult> {\n const { dryRun = false, replace = false } = options;\n const result: SeedResult = {\n created: [],\n errors: [],\n skipped: [],\n };\n\n for (const entity of entities) {\n const alias = entity.alias ?? entity.name ?? \"unknown\";\n\n try {\n if (!entity.model || !entity.scope) {\n throw new Error(\"Entity must have model and scope\");\n }\n\n // For entities with alias, check existence\n if (entity.alias) {\n const existing = await queryByAlias({\n alias: entity.alias,\n model: entity.model,\n scope: entity.scope,\n });\n\n if (existing && !replace) {\n result.skipped.push(alias);\n continue;\n }\n\n // If replacing, use existing ID to update rather than create new\n if (existing && replace) {\n entity.id = existing.id;\n }\n }\n\n if (dryRun) {\n result.created.push(alias);\n continue;\n }\n\n // Generate required fields if missing; indexEntity manages timestamps\n const completeEntity: StorableEntity = {\n id: entity.id ?? crypto.randomUUID(),\n model: entity.model,\n name: entity.name ?? entity.alias ?? \"Unnamed\",\n scope: entity.scope,\n ...entity,\n } as StorableEntity;\n\n await putEntity({ entity: completeEntity });\n result.created.push(alias);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({ alias, error: errorMessage });\n }\n }\n\n return result;\n}\n\n/**\n * Export entities by model and scope\n *\n * - Paginates through all matching entities via queryByScope\n * - Returns entities sorted by sequence (ascending)\n *\n * @param model - The entity model name\n * @param scope - The scope (APEX or \"{parent.model}#{parent.id}\")\n * @param limit - Optional maximum number of entities to export\n * @returns Export result with entities and count\n */\nexport async function exportEntities<T extends StorableEntity>(\n model: string,\n scope: string,\n limit?: number,\n): Promise<ExportResult<T>> {\n const entities: T[] = [];\n let startKey: Record<string, unknown> | undefined;\n let remaining = limit;\n\n do {\n const batchLimit =\n remaining !== undefined ? Math.min(remaining, 100) : undefined;\n\n const { items, lastEvaluatedKey } = await queryByScope({\n ascending: true,\n limit: batchLimit,\n model,\n scope,\n startKey,\n });\n\n entities.push(...(items as T[]));\n startKey = lastEvaluatedKey;\n\n if (remaining !== undefined) {\n remaining -= items.length;\n }\n } while (startKey && (remaining === undefined || remaining > 0));\n\n return {\n count: entities.length,\n entities,\n };\n}\n\n/**\n * Export entities as a JSON string\n *\n * @param model - The entity model name\n * @param scope - The scope (APEX or \"{parent.model}#{parent.id}\")\n * @param pretty - Format JSON with indentation (default: true)\n * @returns JSON string of exported entities\n */\nexport async function exportEntitiesToJson(\n model: string,\n scope: string,\n pretty: boolean = true,\n): Promise<string> {\n const { entities } = await exportEntities(model, scope);\n return pretty ? JSON.stringify(entities, null, 2) : JSON.stringify(entities);\n}\n"],"names":["fabricBuildCompositeKey","fabricCalculateScope","fabricPopulateIndexKeys"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/client.ts","../../../src/keyBuilders.ts","../../../src/entities.ts","../../../src/queries.ts","../../../src/query.ts","../../../src/seedExport.ts"],"sourcesContent":["import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport { ConfigurationError } from \"@jaypie/errors\";\n\nimport type { DynamoClientConfig } from \"./types.js\";\n\n// Environment variable names\nconst ENV_AWS_REGION = \"AWS_REGION\";\nconst ENV_DYNAMODB_TABLE_NAME = \"DYNAMODB_TABLE_NAME\";\n\n// Defaults\nconst DEFAULT_REGION = \"us-east-1\";\nconst LOCAL_CREDENTIALS = {\n accessKeyId: \"local\",\n secretAccessKey: \"local\",\n};\n\n// Module-level state\nlet docClient: DynamoDBDocumentClient | null = null;\nlet tableName: string | null = null;\n\n/**\n * Check if endpoint indicates local development mode\n */\nfunction isLocalEndpoint(endpoint?: string): boolean {\n if (!endpoint) return false;\n return endpoint.includes(\"127.0.0.1\") || endpoint.includes(\"localhost\");\n}\n\n/**\n * Initialize the DynamoDB client\n * Must be called once at application startup before using query functions\n *\n * @param config - Client configuration\n */\nexport function initClient(config: DynamoClientConfig = {}): void {\n const { endpoint } = config;\n const region = config.region ?? process.env[ENV_AWS_REGION] ?? DEFAULT_REGION;\n\n // Auto-detect local mode and use dummy credentials\n const credentials =\n config.credentials ??\n (isLocalEndpoint(endpoint) ? LOCAL_CREDENTIALS : undefined);\n\n const dynamoClient = new DynamoDBClient({\n ...(credentials && { credentials }),\n ...(endpoint && { endpoint }),\n region,\n });\n\n docClient = DynamoDBDocumentClient.from(dynamoClient, {\n marshallOptions: {\n removeUndefinedValues: true,\n },\n });\n\n tableName = config.tableName ?? process.env[ENV_DYNAMODB_TABLE_NAME] ?? null;\n}\n\n/**\n * Get the initialized DynamoDB Document Client\n * @throws ConfigurationError if client has not been initialized\n */\nexport function getDocClient(): DynamoDBDocumentClient {\n if (!docClient) {\n throw new ConfigurationError(\n \"DynamoDB client not initialized. Call initClient() first.\",\n );\n }\n return docClient;\n}\n\n/**\n * Get the configured table name\n * @throws ConfigurationError if client has not been initialized\n */\nexport function getTableName(): string {\n if (!tableName) {\n throw new ConfigurationError(\n \"DynamoDB client not initialized. Call initClient() first.\",\n );\n }\n return tableName;\n}\n\n/**\n * Check if the client has been initialized\n */\nexport function isInitialized(): boolean {\n return docClient !== null && tableName !== null;\n}\n\n/**\n * Reset the client state (primarily for testing)\n */\nexport function resetClient(): void {\n docClient = null;\n tableName = null;\n}\n","import {\n buildCompositeKey as fabricBuildCompositeKey,\n calculateScope as fabricCalculateScope,\n getModelIndexes,\n type IndexableModel,\n populateIndexKeys as fabricPopulateIndexKeys,\n} from \"@jaypie/fabric\";\n\nimport { APEX } from \"./constants.js\";\nimport type { ParentReference, StorableEntity } from \"./types.js\";\n\n// =============================================================================\n// Key Builders\n// =============================================================================\n\n/**\n * Build a composite key from entity fields\n *\n * @param entity - Entity with fields to extract\n * @param fields - Field names to combine with SEPARATOR\n * @param suffix - Optional suffix to append (e.g., \"#deleted\")\n * @returns Composite key string\n */\nexport function buildCompositeKey(\n entity: IndexableModel,\n fields: string[],\n suffix?: string,\n): string {\n return fabricBuildCompositeKey(entity, fields, suffix);\n}\n\n/**\n * Calculate the scope from a parent reference\n * @param parent - Optional parent entity reference\n * @returns APEX (\"@\") if no parent, otherwise \"{parent.model}#{parent.id}\"\n */\nexport function calculateScope(parent?: ParentReference): string {\n if (!parent) {\n return APEX;\n }\n return fabricCalculateScope(parent);\n}\n\n/**\n * Auto-populate GSI index keys on an entity and advance its write timestamps.\n *\n * - Bumps `updatedAt` to now on every call.\n * - Backfills `createdAt` to the same now if not already set.\n * - Populates GSI attributes (pk composite and sk composite when applicable)\n * using the indexes registered for the entity's model.\n *\n * Callers (createEntity, updateEntity, deleteEntity, archiveEntity,\n * transactWriteEntities) go through this one function so `updatedAt` is\n * always fresh and never forgotten.\n *\n * @param entity - The entity to index\n * @param suffix - Optional suffix override (defaults to archived/deleted state)\n * @returns A new entity with timestamps bumped and index keys populated\n */\nexport function indexEntity<T extends StorableEntity>(\n entity: T,\n suffix?: string,\n): T {\n const now = new Date().toISOString();\n const bumped = {\n ...entity,\n createdAt: entity.createdAt ?? now,\n updatedAt: now,\n } as T;\n\n const indexes = getModelIndexes(entity.model);\n return fabricPopulateIndexKeys(\n bumped as unknown as IndexableModel,\n indexes,\n suffix,\n ) as unknown as T;\n}\n","import {\n DeleteCommand,\n GetCommand,\n PutCommand,\n TransactWriteCommand,\n} from \"@aws-sdk/lib-dynamodb\";\nimport { fabricService } from \"@jaypie/fabric\";\n\nimport { getDocClient, getTableName } from \"./client.js\";\nimport { ARCHIVED_SUFFIX, DELETED_SUFFIX } from \"./constants.js\";\nimport { indexEntity } from \"./keyBuilders.js\";\nimport type { StorableEntity } from \"./types.js\";\n\n/**\n * Calculate suffix based on entity's archived/deleted state\n */\nfunction calculateEntitySuffix(entity: {\n archivedAt?: string;\n deletedAt?: string;\n}): string {\n const hasArchived = Boolean(entity.archivedAt);\n const hasDeleted = Boolean(entity.deletedAt);\n\n if (hasArchived && hasDeleted) {\n return ARCHIVED_SUFFIX + DELETED_SUFFIX;\n }\n if (hasArchived) {\n return ARCHIVED_SUFFIX;\n }\n if (hasDeleted) {\n return DELETED_SUFFIX;\n }\n return \"\";\n}\n\n/**\n * Get a single entity by primary key (id)\n */\nexport const getEntity = fabricService({\n alias: \"getEntity\",\n description: \"Get a single entity by id\",\n input: {\n id: { type: String, description: \"Entity id (partition key)\" },\n },\n service: async ({ id }): Promise<StorableEntity | null> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new GetCommand({\n Key: { id },\n TableName: tableName,\n });\n\n const response = await docClient.send(command);\n return (response.Item as StorableEntity) ?? null;\n },\n});\n\n/**\n * Create an entity. Fails the conditional write if `id` already exists,\n * returning `null` instead of throwing. Use `updateEntity` to overwrite.\n * `indexEntity` auto-bumps `updatedAt` and backfills `createdAt`.\n */\nexport async function createEntity({\n entity,\n}: {\n entity: StorableEntity;\n}): Promise<StorableEntity | null> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const indexedEntity = indexEntity(entity);\n\n const command = new PutCommand({\n ConditionExpression: \"attribute_not_exists(id)\",\n Item: indexedEntity,\n TableName: tableName,\n });\n\n try {\n await docClient.send(command);\n } catch (error) {\n if ((error as { name?: string })?.name === \"ConditionalCheckFailedException\") {\n return null;\n }\n throw error;\n }\n return indexedEntity;\n}\n\n/**\n * Update an existing entity.\n * `indexEntity` auto-bumps `updatedAt` — callers never set it manually.\n */\nexport async function updateEntity({\n entity,\n}: {\n entity: StorableEntity;\n}): Promise<StorableEntity> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const updatedEntity = indexEntity(entity);\n\n const command = new PutCommand({\n Item: updatedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return updatedEntity;\n}\n\n/**\n * Soft delete an entity by setting deletedAt timestamp\n * Re-indexes with appropriate suffix based on archived/deleted state\n */\nexport const deleteEntity = fabricService({\n alias: \"deleteEntity\",\n description: \"Soft delete an entity (sets deletedAt timestamp)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const existing = await getEntity({ id });\n if (!existing) {\n return false;\n }\n\n const now = new Date().toISOString();\n\n // indexEntity will bump updatedAt again; set deletedAt here.\n const updatedEntity = {\n ...existing,\n deletedAt: now,\n };\n\n const suffix = calculateEntitySuffix(updatedEntity);\n const deletedEntity = indexEntity(updatedEntity, suffix);\n\n const command = new PutCommand({\n Item: deletedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Archive an entity by setting archivedAt timestamp\n * Re-indexes with appropriate suffix based on archived/deleted state\n */\nexport const archiveEntity = fabricService({\n alias: \"archiveEntity\",\n description: \"Archive an entity (sets archivedAt timestamp)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const existing = await getEntity({ id });\n if (!existing) {\n return false;\n }\n\n const now = new Date().toISOString();\n\n const updatedEntity = {\n ...existing,\n archivedAt: now,\n };\n\n const suffix = calculateEntitySuffix(updatedEntity);\n const archivedEntity = indexEntity(updatedEntity, suffix);\n\n const command = new PutCommand({\n Item: archivedEntity,\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Hard delete an entity (permanently removes from table)\n * Use with caution - prefer deleteEntity for soft delete\n */\nexport const destroyEntity = fabricService({\n alias: \"destroyEntity\",\n description: \"Hard delete an entity (permanently removes from table)\",\n input: {\n id: { type: String, description: \"Entity id\" },\n },\n service: async ({ id }): Promise<boolean> => {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new DeleteCommand({\n Key: { id },\n TableName: tableName,\n });\n\n await docClient.send(command);\n return true;\n },\n});\n\n/**\n * Write multiple entities atomically using DynamoDB transactions.\n * Each entity is auto-indexed via indexEntity before writing.\n * All entities are written to the same table in a single transaction.\n */\nexport async function transactWriteEntities({\n entities,\n}: {\n entities: StorableEntity[];\n}): Promise<void> {\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new TransactWriteCommand({\n TransactItems: entities.map((entity) => ({\n Put: {\n Item: indexEntity(entity),\n TableName: tableName,\n },\n })),\n });\n\n await docClient.send(command);\n}\n","import { QueryCommand } from \"@aws-sdk/lib-dynamodb\";\nimport { ConfigurationError } from \"@jaypie/errors\";\nimport {\n fabricService,\n getGsiAttributeNames,\n getModelIndexes,\n type IndexDefinition,\n SEPARATOR,\n} from \"@jaypie/fabric\";\n\nimport { getDocClient, getTableName } from \"./client.js\";\nimport { ARCHIVED_SUFFIX, DELETED_SUFFIX } from \"./constants.js\";\nimport { buildCompositeKey } from \"./keyBuilders.js\";\nimport type {\n QueryByAliasParams,\n QueryByCategoryParams,\n QueryByScopeParams,\n QueryByTypeParams,\n QueryByXidParams,\n QueryResult,\n StorableEntity,\n} from \"./types.js\";\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Calculate the suffix for the GSI partition key based on archived/deleted\n * flags. Suffix stays on pk so deleted/archived entities are queried as their\n * own partition (active queries skip them naturally).\n */\nfunction calculateSuffix({\n archived,\n deleted,\n}: {\n archived?: boolean;\n deleted?: boolean;\n}): string {\n if (archived && deleted) {\n return ARCHIVED_SUFFIX + DELETED_SUFFIX;\n }\n if (archived) {\n return ARCHIVED_SUFFIX;\n }\n if (deleted) {\n return DELETED_SUFFIX;\n }\n return \"\";\n}\n\n/**\n * Find the registered index for a model that matches a given partition-key\n * shape. The matching index is the first one whose pk equals the expected\n * fields. Throws ConfigurationError if no match is found.\n */\nfunction requireIndex(model: string, pkFields: string[]): IndexDefinition {\n const indexes = getModelIndexes(model);\n const match = indexes.find(\n (index) =>\n index.pk.length === pkFields.length &&\n index.pk.every((field, i) => field === pkFields[i]),\n );\n if (!match) {\n throw new ConfigurationError(\n `Model \"${model}\" has no index with pk=[${pkFields.join(\", \")}]. ` +\n `Register one with fabricIndex(${\n pkFields.length > 1 ? `\"${pkFields[1]}\"` : \"\"\n }).`,\n );\n }\n return match;\n}\n\n/**\n * Execute a GSI query.\n *\n * - pk: exact match on the index partition key\n * - skPrefix: optional begins_with on the index sort key (used when the index\n * has a composite sk like [scope, updatedAt])\n */\nasync function executeQuery<T extends StorableEntity>(\n index: IndexDefinition,\n pkValue: string,\n options: {\n ascending?: boolean;\n limit?: number;\n skPrefix?: string;\n startKey?: Record<string, unknown>;\n } = {},\n): Promise<QueryResult<T>> {\n const { ascending = false, limit, skPrefix, startKey } = options;\n const attrs = getGsiAttributeNames(index);\n const indexName = attrs.pk;\n\n const expressionAttributeNames: Record<string, string> = {\n \"#pk\": indexName,\n };\n const expressionAttributeValues: Record<string, unknown> = {\n \":pkValue\": pkValue,\n };\n let keyConditionExpression = \"#pk = :pkValue\";\n\n if (skPrefix !== undefined && attrs.sk) {\n expressionAttributeNames[\"#sk\"] = attrs.sk;\n expressionAttributeValues[\":skPrefix\"] = skPrefix;\n keyConditionExpression += \" AND begins_with(#sk, :skPrefix)\";\n }\n\n const docClient = getDocClient();\n const tableName = getTableName();\n\n const command = new QueryCommand({\n ExclusiveStartKey: startKey as Record<string, unknown> | undefined,\n ExpressionAttributeNames: expressionAttributeNames,\n ExpressionAttributeValues: expressionAttributeValues,\n IndexName: indexName,\n KeyConditionExpression: keyConditionExpression,\n ...(limit && { Limit: limit }),\n ScanIndexForward: ascending,\n TableName: tableName,\n });\n\n const response = await docClient.send(command);\n\n return {\n items: (response.Items ?? []) as T[],\n lastEvaluatedKey: response.LastEvaluatedKey,\n };\n}\n\nfunction scopePrefix(scope: string | undefined): string | undefined {\n return scope === undefined ? undefined : `${scope}${SEPARATOR}`;\n}\n\n// =============================================================================\n// Query Functions\n// =============================================================================\n\n/**\n * List entities of a model, optionally narrowed to a scope.\n * Requires the model to register `fabricIndex()` (pk=[model]).\n */\nexport async function queryByScope({\n archived = false,\n ascending = false,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n}: QueryByScopeParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey({ model }, [\"model\"], suffix);\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query a single entity by human-friendly alias.\n * Requires the model to register `fabricIndex(\"alias\")`.\n */\nexport const queryByAlias = fabricService({\n alias: \"queryByAlias\",\n description: \"Query a single entity by human-friendly alias\",\n input: {\n alias: { type: String, description: \"Human-friendly alias\" },\n archived: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query archived entities instead of active ones\",\n },\n deleted: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query deleted entities instead of active ones\",\n },\n model: { type: String, description: \"Entity model name\" },\n scope: {\n type: String,\n required: false,\n description: \"Optional scope narrower (begins_with on sk)\",\n },\n },\n service: async ({\n alias,\n archived,\n deleted,\n model,\n scope,\n }): Promise<StorableEntity | null> => {\n const aliasStr = alias as string;\n const archivedBool = archived as boolean | undefined;\n const deletedBool = deleted as boolean | undefined;\n const modelStr = model as string;\n const scopeStr = scope as string | undefined;\n\n const index = requireIndex(modelStr, [\"model\", \"alias\"]);\n const suffix = calculateSuffix({\n archived: archivedBool,\n deleted: deletedBool,\n });\n const pkValue = buildCompositeKey(\n { model: modelStr, alias: aliasStr },\n [\"model\", \"alias\"],\n suffix,\n );\n const result = await executeQuery<StorableEntity>(index, pkValue, {\n limit: 1,\n skPrefix: scopePrefix(scopeStr),\n });\n return result.items[0] ?? null;\n },\n});\n\n/**\n * Query entities by category classification.\n * Requires the model to register `fabricIndex(\"category\")`.\n */\nexport async function queryByCategory({\n archived = false,\n ascending = false,\n category,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n}: QueryByCategoryParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\", \"category\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n { model, category },\n [\"model\", \"category\"],\n suffix,\n );\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query entities by type classification.\n * Requires the model to register `fabricIndex(\"type\")`.\n */\nexport async function queryByType({\n archived = false,\n ascending = false,\n deleted = false,\n limit,\n model,\n scope,\n startKey,\n type,\n}: QueryByTypeParams): Promise<QueryResult<StorableEntity>> {\n const index = requireIndex(model, [\"model\", \"type\"]);\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n { model, type },\n [\"model\", \"type\"],\n suffix,\n );\n return executeQuery<StorableEntity>(index, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n/**\n * Query a single entity by external ID.\n * Requires the model to register `fabricIndex(\"xid\")`.\n */\nexport const queryByXid = fabricService({\n alias: \"queryByXid\",\n description: \"Query a single entity by external ID\",\n input: {\n archived: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query archived entities instead of active ones\",\n },\n deleted: {\n type: Boolean,\n default: false,\n required: false,\n description: \"Query deleted entities instead of active ones\",\n },\n model: { type: String, description: \"Entity model name\" },\n scope: {\n type: String,\n required: false,\n description: \"Optional scope narrower (begins_with on sk)\",\n },\n xid: { type: String, description: \"External ID\" },\n },\n service: async ({\n archived,\n deleted,\n model,\n scope,\n xid,\n }): Promise<StorableEntity | null> => {\n const archivedBool = archived as boolean | undefined;\n const deletedBool = deleted as boolean | undefined;\n const modelStr = model as string;\n const scopeStr = scope as string | undefined;\n const xidStr = xid as string;\n\n const index = requireIndex(modelStr, [\"model\", \"xid\"]);\n const suffix = calculateSuffix({\n archived: archivedBool,\n deleted: deletedBool,\n });\n const pkValue = buildCompositeKey(\n { model: modelStr, xid: xidStr },\n [\"model\", \"xid\"],\n suffix,\n );\n const result = await executeQuery<StorableEntity>(index, pkValue, {\n limit: 1,\n skPrefix: scopePrefix(scopeStr),\n });\n return result.items[0] ?? null;\n },\n});\n\n// Internal exports for the unified query() layer\nexport { executeQuery, requireIndex, calculateSuffix, scopePrefix };\n","/**\n * Unified Query Function with Auto-Detect Index Selection\n *\n * The query() function automatically selects the best index based on\n * the filter fields provided. This simplifies query construction by\n * removing the need to know which specific GSI to use.\n */\n\nimport { ConfigurationError } from \"@jaypie/errors\";\nimport { getModelIndexes, type IndexDefinition } from \"@jaypie/fabric\";\n\nimport { buildCompositeKey } from \"./keyBuilders.js\";\nimport {\n calculateSuffix,\n executeQuery,\n scopePrefix,\n} from \"./queries.js\";\nimport type { QueryResult, StorableEntity } from \"./types.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Query parameters for the unified query function\n */\nexport interface QueryParams<T = StorableEntity> {\n /** Whether to query archived entities instead of active ones */\n archived?: boolean;\n /** Whether to sort ascending (oldest first). Default: false */\n ascending?: boolean;\n /** Whether to query deleted entities instead of active ones */\n deleted?: boolean;\n /**\n * Filter object with field values to match. Used for index auto-detection\n * — the picker scores indexes by how many pk fields (after `model`) are\n * present in this filter.\n */\n filter?: Partial<T>;\n /** Maximum number of items to return */\n limit?: number;\n /** Model name (required) */\n model: string;\n /**\n * Optional scope narrower. Applied as `begins_with` on the GSI sort key\n * (composite scope + updatedAt). Omit to list across all scopes.\n */\n scope?: string;\n /** Pagination cursor from previous query */\n startKey?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Index Selection\n// =============================================================================\n\n/**\n * Select the best index for the given filter.\n *\n * Every model-level index has `model` as its first pk field. The picker\n * prefers the most specific index whose remaining pk fields are all\n * satisfied by the filter.\n */\nfunction selectBestIndex(\n indexes: IndexDefinition[],\n filter: Record<string, unknown>,\n): IndexDefinition {\n // Candidates: indexes whose pk starts with \"model\" and whose remaining\n // fields are all present in the filter.\n const candidates = indexes.filter((index) => {\n if (index.pk.length === 0 || index.pk[0] !== \"model\") return false;\n for (let i = 1; i < index.pk.length; i++) {\n if (filter[index.pk[i] as string] === undefined) return false;\n }\n return true;\n });\n\n if (candidates.length === 0) {\n const available = indexes\n .map((i) => `[${i.pk.join(\", \")}]`)\n .join(\", \");\n const provided = Object.keys(filter).join(\", \") || \"(none)\";\n throw new ConfigurationError(\n `No index matches filter for model. ` +\n `Filter fields: ${provided}. Available indexes: ${available}`,\n );\n }\n\n // Prefer the most specific index (longest pk).\n candidates.sort((a, b) => b.pk.length - a.pk.length);\n return candidates[0];\n}\n\n// =============================================================================\n// Main Query Function\n// =============================================================================\n\n/**\n * Query entities with automatic index selection.\n *\n * @example\n * // Uses indexModel (pk: [\"model\"]), optionally narrowed by scope\n * const records = await query({ model: \"record\", scope: \"@\" });\n *\n * @example\n * // Uses indexModelAlias (pk: [\"model\", \"alias\"])\n * const byAlias = await query({\n * model: \"record\",\n * scope: \"@\",\n * filter: { alias: \"my-record\" },\n * });\n *\n * @example\n * // Cross-scope listing (no scope narrower)\n * const all = await query({ model: \"record\" });\n */\nexport async function query<T extends StorableEntity = StorableEntity>(\n params: QueryParams<T>,\n): Promise<QueryResult<T>> {\n const {\n archived = false,\n ascending = false,\n deleted = false,\n filter,\n limit,\n model,\n scope,\n startKey,\n } = params;\n\n const indexes = getModelIndexes(model);\n const filterFields: Record<string, unknown> = {\n model,\n ...(filter as Record<string, unknown> | undefined),\n };\n const selectedIndex = selectBestIndex(indexes, filterFields);\n\n const suffix = calculateSuffix({ archived, deleted });\n const pkValue = buildCompositeKey(\n filterFields as Record<string, unknown> & { model: string },\n selectedIndex.pk as string[],\n suffix,\n );\n\n return executeQuery<T>(selectedIndex, pkValue, {\n ascending,\n limit,\n skPrefix: scopePrefix(scope),\n startKey,\n });\n}\n\n// Re-export for convenience\nexport { getModelIndexes };\n","import { createEntity, updateEntity } from \"./entities.js\";\nimport { queryByAlias, queryByScope } from \"./queries.js\";\nimport type { StorableEntity } from \"./types.js\";\n\n/**\n * Result of a seed operation\n */\nexport interface SeedResult {\n /** Aliases of entities that were created */\n created: string[];\n /** Error details for failed seed operations */\n errors: Array<{ alias: string; error: string }>;\n /** Aliases of entities that were skipped (already exist) */\n skipped: string[];\n}\n\n/**\n * Options for seed operations\n */\nexport interface SeedOptions {\n /** Preview without writing (default: false) */\n dryRun?: boolean;\n /** Overwrite existing entities (default: false) */\n replace?: boolean;\n}\n\n/**\n * Result of an export operation\n */\nexport interface ExportResult<T extends StorableEntity = StorableEntity> {\n /** Number of entities exported */\n count: number;\n /** Exported entities */\n entities: T[];\n}\n\n/**\n * Seed a single entity if it doesn't already exist\n *\n * @param entity - Partial entity with at least alias, model, and scope\n * @returns true if entity was created, false if it already exists\n */\nexport async function seedEntityIfNotExists<T extends Partial<StorableEntity>>(\n entity: T,\n): Promise<boolean> {\n if (!entity.alias || !entity.model || !entity.scope) {\n throw new Error(\n \"Entity must have alias, model, and scope to check existence\",\n );\n }\n\n // Check if entity already exists\n const existing = await queryByAlias({\n alias: entity.alias,\n model: entity.model,\n scope: entity.scope,\n });\n\n if (existing) {\n return false;\n }\n\n // Generate required fields if missing; indexEntity manages timestamps\n const completeEntity: StorableEntity = {\n id: entity.id ?? crypto.randomUUID(),\n model: entity.model,\n name: entity.name ?? entity.alias,\n scope: entity.scope,\n ...entity,\n } as StorableEntity;\n\n await createEntity({ entity: completeEntity });\n return true;\n}\n\n/**\n * Seed multiple entities (idempotent)\n *\n * - Checks existence by alias (via queryByAlias) before creating\n * - Auto-generates id (UUID), createdAt, updatedAt if missing\n * - Skip existing unless replace: true\n * - Returns counts of created/skipped/errors\n *\n * @param entities - Array of partial entities to seed\n * @param options - Seed options\n * @returns Result with created, skipped, and errors arrays\n */\nexport async function seedEntities<T extends Partial<StorableEntity>>(\n entities: T[],\n options: SeedOptions = {},\n): Promise<SeedResult> {\n const { dryRun = false, replace = false } = options;\n const result: SeedResult = {\n created: [],\n errors: [],\n skipped: [],\n };\n\n for (const entity of entities) {\n const alias = entity.alias ?? entity.name ?? \"unknown\";\n\n try {\n if (!entity.model || !entity.scope) {\n throw new Error(\"Entity must have model and scope\");\n }\n\n // For entities with alias, check existence\n let isReplace = false;\n if (entity.alias) {\n const existing = await queryByAlias({\n alias: entity.alias,\n model: entity.model,\n scope: entity.scope,\n });\n\n if (existing && !replace) {\n result.skipped.push(alias);\n continue;\n }\n\n // If replacing, use existing ID to update rather than create new\n if (existing && replace) {\n entity.id = existing.id;\n isReplace = true;\n }\n }\n\n if (dryRun) {\n result.created.push(alias);\n continue;\n }\n\n // Generate required fields if missing; indexEntity manages timestamps\n const completeEntity: StorableEntity = {\n id: entity.id ?? crypto.randomUUID(),\n model: entity.model,\n name: entity.name ?? entity.alias ?? \"Unnamed\",\n scope: entity.scope,\n ...entity,\n } as StorableEntity;\n\n if (isReplace) {\n await updateEntity({ entity: completeEntity });\n } else {\n await createEntity({ entity: completeEntity });\n }\n result.created.push(alias);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({ alias, error: errorMessage });\n }\n }\n\n return result;\n}\n\n/**\n * Export entities by model and scope\n *\n * - Paginates through all matching entities via queryByScope\n * - Returns entities sorted by sequence (ascending)\n *\n * @param model - The entity model name\n * @param scope - The scope (APEX or \"{parent.model}#{parent.id}\")\n * @param limit - Optional maximum number of entities to export\n * @returns Export result with entities and count\n */\nexport async function exportEntities<T extends StorableEntity>(\n model: string,\n scope: string,\n limit?: number,\n): Promise<ExportResult<T>> {\n const entities: T[] = [];\n let startKey: Record<string, unknown> | undefined;\n let remaining = limit;\n\n do {\n const batchLimit =\n remaining !== undefined ? Math.min(remaining, 100) : undefined;\n\n const { items, lastEvaluatedKey } = await queryByScope({\n ascending: true,\n limit: batchLimit,\n model,\n scope,\n startKey,\n });\n\n entities.push(...(items as T[]));\n startKey = lastEvaluatedKey;\n\n if (remaining !== undefined) {\n remaining -= items.length;\n }\n } while (startKey && (remaining === undefined || remaining > 0));\n\n return {\n count: entities.length,\n entities,\n };\n}\n\n/**\n * Export entities as a JSON string\n *\n * @param model - The entity model name\n * @param scope - The scope (APEX or \"{parent.model}#{parent.id}\")\n * @param pretty - Format JSON with indentation (default: true)\n * @returns JSON string of exported entities\n */\nexport async function exportEntitiesToJson(\n model: string,\n scope: string,\n pretty: boolean = true,\n): Promise<string> {\n const { entities } = await exportEntities(model, scope);\n return pretty ? JSON.stringify(entities, null, 2) : JSON.stringify(entities);\n}\n"],"names":["fabricBuildCompositeKey","fabricCalculateScope","fabricPopulateIndexKeys"],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ export declare function calculateScope(parent?: ParentReference): string;
|
|
|
23
23
|
* - Populates GSI attributes (pk composite and sk composite when applicable)
|
|
24
24
|
* using the indexes registered for the entity's model.
|
|
25
25
|
*
|
|
26
|
-
* Callers (
|
|
26
|
+
* Callers (createEntity, updateEntity, deleteEntity, archiveEntity,
|
|
27
27
|
* transactWriteEntities) go through this one function so `updatedAt` is
|
|
28
28
|
* always fresh and never forgotten.
|
|
29
29
|
*
|
package/dist/esm/mcp/index.js
CHANGED
|
@@ -97,7 +97,7 @@ function buildCompositeKey(entity, fields, suffix) {
|
|
|
97
97
|
* - Populates GSI attributes (pk composite and sk composite when applicable)
|
|
98
98
|
* using the indexes registered for the entity's model.
|
|
99
99
|
*
|
|
100
|
-
* Callers (
|
|
100
|
+
* Callers (createEntity, updateEntity, deleteEntity, archiveEntity,
|
|
101
101
|
* transactWriteEntities) go through this one function so `updatedAt` is
|
|
102
102
|
* always fresh and never forgotten.
|
|
103
103
|
*
|
|
@@ -154,18 +154,28 @@ const getEntity = fabricService({
|
|
|
154
154
|
},
|
|
155
155
|
});
|
|
156
156
|
/**
|
|
157
|
-
*
|
|
157
|
+
* Create an entity. Fails the conditional write if `id` already exists,
|
|
158
|
+
* returning `null` instead of throwing. Use `updateEntity` to overwrite.
|
|
158
159
|
* `indexEntity` auto-bumps `updatedAt` and backfills `createdAt`.
|
|
159
160
|
*/
|
|
160
|
-
async function
|
|
161
|
+
async function createEntity({ entity, }) {
|
|
161
162
|
const docClient = getDocClient();
|
|
162
163
|
const tableName = getTableName();
|
|
163
164
|
const indexedEntity = indexEntity(entity);
|
|
164
165
|
const command = new PutCommand({
|
|
166
|
+
ConditionExpression: "attribute_not_exists(id)",
|
|
165
167
|
Item: indexedEntity,
|
|
166
168
|
TableName: tableName,
|
|
167
169
|
});
|
|
168
|
-
|
|
170
|
+
try {
|
|
171
|
+
await docClient.send(command);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error?.name === "ConditionalCheckFailedException") {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
169
179
|
return indexedEntity;
|
|
170
180
|
}
|
|
171
181
|
/**
|
|
@@ -758,12 +768,12 @@ function wrapWithInit(handler) {
|
|
|
758
768
|
// MCP-specific serviceHandler wrappers for functions with complex inputs
|
|
759
769
|
// Note: These wrap the regular async functions to make them work with fabricMcp
|
|
760
770
|
/**
|
|
761
|
-
* MCP wrapper for
|
|
771
|
+
* MCP wrapper for createEntity
|
|
762
772
|
* Accepts entity JSON directly from LLM
|
|
763
773
|
*/
|
|
764
|
-
const
|
|
765
|
-
alias: "
|
|
766
|
-
description: "Create
|
|
774
|
+
const mcpCreateEntity = fabricService({
|
|
775
|
+
alias: "dynamodb_create",
|
|
776
|
+
description: "Create an entity in DynamoDB (auto-indexes GSI keys; returns null if id exists)",
|
|
767
777
|
input: {
|
|
768
778
|
// Required entity fields
|
|
769
779
|
id: { type: String, description: "Entity ID (sort key)" },
|
|
@@ -799,7 +809,7 @@ const mcpPutEntity = fabricService({
|
|
|
799
809
|
updatedAt: now,
|
|
800
810
|
xid: input.xid,
|
|
801
811
|
};
|
|
802
|
-
return
|
|
812
|
+
return createEntity({ entity });
|
|
803
813
|
},
|
|
804
814
|
});
|
|
805
815
|
/**
|
|
@@ -1006,11 +1016,11 @@ function registerDynamoDbTools(config) {
|
|
|
1006
1016
|
});
|
|
1007
1017
|
tools.push("dynamodb_get");
|
|
1008
1018
|
fabricMcp({
|
|
1009
|
-
service: wrapWithInit(
|
|
1010
|
-
name: "
|
|
1019
|
+
service: wrapWithInit(mcpCreateEntity),
|
|
1020
|
+
name: "dynamodb_create",
|
|
1011
1021
|
server,
|
|
1012
1022
|
});
|
|
1013
|
-
tools.push("
|
|
1023
|
+
tools.push("dynamodb_create");
|
|
1014
1024
|
fabricMcp({
|
|
1015
1025
|
service: wrapWithInit(mcpUpdateEntity),
|
|
1016
1026
|
name: "dynamodb_update",
|